summaryrefslogtreecommitdiffstats
path: root/WebCore/html/canvas/WebGLTexture.cpp
diff options
context:
space:
mode:
authorBen Murdoch <benm@google.com>2010-07-22 15:37:06 +0100
committerBen Murdoch <benm@google.com>2010-07-27 10:20:25 +0100
commit967717af5423377c967781471ee106e2bb4e11c8 (patch)
tree1e701dc0a12f7f07cce1df4a7681717de77a211b /WebCore/html/canvas/WebGLTexture.cpp
parentdcc30a9fca45f634b1d3a12b276d3a0ccce99fc3 (diff)
downloadexternal_webkit-967717af5423377c967781471ee106e2bb4e11c8.zip
external_webkit-967717af5423377c967781471ee106e2bb4e11c8.tar.gz
external_webkit-967717af5423377c967781471ee106e2bb4e11c8.tar.bz2
Merge WebKit at r63859 : Initial merge by git.
Change-Id: Ie8096c63ec7c991c9a9cba8bdd9c3b74a3b8ed62
Diffstat (limited to 'WebCore/html/canvas/WebGLTexture.cpp')
-rw-r--r--WebCore/html/canvas/WebGLTexture.cpp212
1 files changed, 163 insertions, 49 deletions
diff --git a/WebCore/html/canvas/WebGLTexture.cpp b/WebCore/html/canvas/WebGLTexture.cpp
index 1cc7d5d..d832038 100644
--- a/WebCore/html/canvas/WebGLTexture.cpp
+++ b/WebCore/html/canvas/WebGLTexture.cpp
@@ -45,32 +45,39 @@ WebGLTexture::WebGLTexture(WebGLRenderingContext* ctx)
, m_magFilter(GraphicsContext3D::LINEAR)
, m_wrapS(GraphicsContext3D::REPEAT)
, m_wrapT(GraphicsContext3D::REPEAT)
- , m_internalFormat(0)
, m_isNPOT(false)
+ , m_isComplete(false)
, m_needToUseBlackTexture(false)
{
setObject(context()->graphicsContext3D()->createTexture());
- for (int ii = 0; ii < 6; ++ii) {
- m_width[ii] = 0;
- m_height[ii] = 0;
- }
}
-void WebGLTexture::setTarget(unsigned long target)
+void WebGLTexture::setTarget(unsigned long target, int maxLevel)
{
+ if (!object())
+ return;
// Target is finalized the first time bindTexture() is called.
if (m_target)
return;
switch (target) {
case GraphicsContext3D::TEXTURE_2D:
+ m_target = target;
+ m_info.resize(1);
+ m_info[0].resize(maxLevel);
+ break;
case GraphicsContext3D::TEXTURE_CUBE_MAP:
m_target = target;
+ m_info.resize(6);
+ for (int ii = 0; ii < 6; ++ii)
+ m_info[ii].resize(maxLevel);
break;
}
}
void WebGLTexture::setParameteri(unsigned long pname, int param)
{
+ if (!object() || !m_target)
+ return;
switch (pname) {
case GraphicsContext3D::TEXTURE_MIN_FILTER:
switch (param) {
@@ -113,88 +120,195 @@ void WebGLTexture::setParameteri(unsigned long pname, int param)
default:
return;
}
- updateNPOTStates();
+ update();
}
void WebGLTexture::setParameterf(unsigned long pname, float param)
{
+ if (!object() || !m_target)
+ return;
int iparam = static_cast<int>(param);
setParameteri(pname, iparam);
}
-void WebGLTexture::setSize(unsigned long target, unsigned width, unsigned height)
+void WebGLTexture::setLevelInfo(unsigned long target, int level, unsigned long internalFormat, int width, int height, unsigned long type)
{
- if (!width || !height)
+ if (!object() || !m_target)
return;
- int iTarget = -1;
+ // We assume level, internalFormat, width, height, and type have all been
+ // validated already.
+ int index = mapTargetToIndex(target);
+ if (index < 0)
+ return;
+ m_info[index][level].setInfo(internalFormat, width, height, type);
+ update();
+}
+
+void WebGLTexture::generateMipmapLevelInfo()
+{
+ if (!object() || !m_target)
+ return;
+ if (!canGenerateMipmaps())
+ return;
+ if (m_isComplete)
+ return;
+ for (size_t ii = 0; ii < m_info.size(); ++ii) {
+ const LevelInfo& info0 = m_info[ii][0];
+ int width = info0.width;
+ int height = info0.height;
+ int levelCount = computeLevelCount(width, height);
+ for (int level = 1; level < levelCount; ++level) {
+ width = std::max(1, width >> 1);
+ height = std::max(1, height >> 1);
+ LevelInfo& info = m_info[ii][level];
+ info.setInfo(info0.internalFormat, width, height, info0.type);
+ }
+ }
+ m_isComplete = true;
+}
+
+unsigned long WebGLTexture::getInternalFormat() const
+{
+ if (!object() || !m_target)
+ return 0;
+ return m_info[0][0].internalFormat;
+}
+
+bool WebGLTexture::isNPOT(unsigned width, unsigned height)
+{
+ if (!width || !height)
+ return false;
+ if ((width & (width - 1)) || (height & (height - 1)))
+ return true;
+ return false;
+}
+
+bool WebGLTexture::isNPOT() const
+{
+ if (!object())
+ return false;
+ return m_isNPOT;
+}
+
+bool WebGLTexture::needToUseBlackTexture() const
+{
+ if (!object())
+ return false;
+ return m_needToUseBlackTexture;
+}
+
+void WebGLTexture::_deleteObject(Platform3DObject object)
+{
+ context()->graphicsContext3D()->deleteTexture(object);
+}
+
+int WebGLTexture::mapTargetToIndex(unsigned long target)
+{
if (m_target == GraphicsContext3D::TEXTURE_2D) {
if (target == GraphicsContext3D::TEXTURE_2D)
- iTarget = 0;
- } else if (m_target == GraphicsContext3D::TEXTURE_CUBE_MAP && width == height) {
+ return 0;
+ } else if (m_target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
switch (target) {
case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
- iTarget = 0;
- break;
+ return 0;
case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
- iTarget = 1;
- break;
+ return 1;
case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
- iTarget = 2;
- break;
+ return 2;
case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
- iTarget = 3;
- break;
+ return 3;
case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
- iTarget = 4;
- break;
+ return 4;
case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
- iTarget = 5;
- break;
+ return 5;
}
}
- if (iTarget < 0)
- return;
- m_width[iTarget] = width;
- m_height[iTarget] = height;
- updateNPOTStates();
+ return -1;
}
-bool WebGLTexture::isNPOT(unsigned width, unsigned height)
+bool WebGLTexture::canGenerateMipmaps()
{
- if (!width || !height)
+ if (isNPOT())
return false;
- if ((width & (width - 1)) || (height & (height - 1)))
- return true;
- return false;
+ const LevelInfo& first = m_info[0][0];
+ for (size_t ii = 0; ii < m_info.size(); ++ii) {
+ const LevelInfo& info = m_info[ii][0];
+ if (!info.valid
+ || info.width != first.width || info.height != first.height
+ || info.internalFormat != first.internalFormat || info.type != first.type)
+ return false;
+ }
+ return true;
}
-void WebGLTexture::_deleteObject(Platform3DObject object)
+int WebGLTexture::computeLevelCount(int width, int height)
{
- context()->graphicsContext3D()->deleteTexture(object);
+ // return 1 + log2Floor(std::max(width, height));
+ int n = std::max(width, height);
+ if (n <= 0)
+ return 0;
+ int log = 0;
+ int value = n;
+ for (int ii = 4; ii >= 0; --ii) {
+ int shift = (1 << ii);
+ int x = (value >> shift);
+ if (x) {
+ value = x;
+ log += shift;
+ }
+ }
+ ASSERT(value == 1);
+ return log + 1;
}
-void WebGLTexture::updateNPOTStates()
+void WebGLTexture::update()
{
- int numTargets = 0;
- if (m_target == GraphicsContext3D::TEXTURE_2D)
- numTargets = 1;
- else if (m_target == GraphicsContext3D::TEXTURE_CUBE_MAP)
- numTargets = 6;
m_isNPOT = false;
- unsigned w0 = m_width[0], h0 = m_height[0];
- for (int ii = 0; ii < numTargets; ++ii) {
- if (ii && (!m_width[ii] || !m_height[ii] || m_width[ii] != w0 || m_height[ii] != h0)) {
- // We only set NPOT for complete cube map textures.
- m_isNPOT = false;
+ for (size_t ii = 0; ii < m_info.size(); ++ii) {
+ if (isNPOT(m_info[ii][0].width, m_info[ii][0].height)) {
+ m_isNPOT = true;
break;
}
- if (isNPOT(m_width[ii], m_height[ii]))
- m_isNPOT = true;
}
+ m_isComplete = true;
+ const LevelInfo& first = m_info[0][0];
+ int levelCount = computeLevelCount(first.width, first.height);
+ if (levelCount < 1)
+ m_isComplete = false;
+ else {
+ for (size_t ii = 0; ii < m_info.size() && m_isComplete; ++ii) {
+ const LevelInfo& info0 = m_info[ii][0];
+ if (!info0.valid
+ || info0.width != first.width || info0.height != first.height
+ || info0.internalFormat != first.internalFormat || info0.type != first.type) {
+ m_isComplete = false;
+ break;
+ }
+ int width = info0.width;
+ int height = info0.height;
+ for (int level = 1; level < levelCount; ++level) {
+ width = std::max(1, width >> 1);
+ height = std::max(1, height >> 1);
+ const LevelInfo& info = m_info[ii][level];
+ if (!info.valid
+ || info.width != width || info.height != height
+ || info.internalFormat != info0.internalFormat || info.type != info0.type) {
+ m_isComplete = false;
+ break;
+ }
+
+ }
+ }
+ }
+
m_needToUseBlackTexture = false;
+ // NPOT
if (m_isNPOT && ((m_minFilter != GraphicsContext3D::NEAREST && m_minFilter != GraphicsContext3D::LINEAR)
|| m_wrapS != GraphicsContext3D::CLAMP_TO_EDGE || m_wrapT != GraphicsContext3D::CLAMP_TO_EDGE))
m_needToUseBlackTexture = true;
+ // Completeness
+ if (!m_isComplete && m_minFilter != GraphicsContext3D::NEAREST && m_minFilter != GraphicsContext3D::LINEAR)
+ m_needToUseBlackTexture = true;
}
}