[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

zmo at google.com zmo at google.com
Wed Dec 22 11:09:12 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit 2d85c6d7e97f80062766150b58dd5dff87923b3a
Author: zmo at google.com <zmo at google.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Tue Jul 13 22:53:42 2010 +0000

    2010-07-04  Zhenyao Mo  <zmo at google.com>
    
            Reviewed by Darin Fisher.
    
            Need to track texture completeness
            https://bugs.webkit.org/show_bug.cgi?id=41381
    
            Test: fast/canvas/webgl/texture-complete.html
    
            * html/canvas/WebGLRenderingContext.cpp:
            (WebCore::WebGLRenderingContext::WebGLRenderingContext): Init max texture level.
            (WebCore::WebGLRenderingContext::bindTexture): Pass max texture level to setTarget().
            (WebCore::WebGLRenderingContext::copyTexImage2D): Cache full texture info rather than partial.
            (WebCore::WebGLRenderingContext::generateMipmap): Ditto.
            (WebCore::WebGLRenderingContext::texImage2DBase): Ditto.
            (WebCore::WebGLRenderingContext::validateTexFuncParameters): Also validate level.
            * html/canvas/WebGLRenderingContext.h: Add max texture level.
            * html/canvas/WebGLTexture.cpp: Update the class to fully cache texture information and track NPOT and COMPLETE states.
            (WebCore::WebGLTexture::WebGLTexture):
            (WebCore::WebGLTexture::setTarget): Check whether the texture is initialized or has been deleted.
            (WebCore::WebGLTexture::setParameteri): Ditto.
            (WebCore::WebGLTexture::setParameterf): Ditto.
            (WebCore::WebGLTexture::setLevelInfo): Set texture info.
            (WebCore::WebGLTexture::generateMipmapLevelInfo): Generate texture info for all levels after generateMipmaps() is called.
            (WebCore::WebGLTexture::getInternalFormat): Return internal format on texture face 0 level 0.
            (WebCore::WebGLTexture::isNPOT): Check whether the texture is initialized or has been deleted.
            (WebCore::WebGLTexture::needToUseBlackTexture): Ditto.
            (WebCore::WebGLTexture::_deleteObject):
            (WebCore::WebGLTexture::mapTargetToIndex): Map target to index.
            (WebCore::WebGLTexture::canGenerateMipmaps): Check whether Mipmaps can be generated.
            (WebCore::WebGLTexture::computeLevelCount): Compute texture level count from width/height.
            (WebCore::WebGLTexture::update): Update NPOT/COMPLETE states.
            * html/canvas/WebGLTexture.h: Ditto.
            (WebCore::WebGLTexture::LevelInfo::LevelInfo): Add data structure to fully cache texture info.
            (WebCore::WebGLTexture::LevelInfo::setInfo): Set information.
    2010-07-04  Zhenyao Mo  <zmo at google.com>
    
            Reviewed by Darin Fisher.
    
            Need to track texture completeness
            https://bugs.webkit.org/show_bug.cgi?id=41381
    
            * fast/canvas/webgl/texture-complete-expected.txt: Added.
            * fast/canvas/webgl/texture-complete.html: Added.
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@63253 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 57b4323..112e847 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,13 @@
+2010-07-04  Zhenyao Mo  <zmo at google.com>
+
+        Reviewed by Darin Fisher.
+
+        Need to track texture completeness
+        https://bugs.webkit.org/show_bug.cgi?id=41381
+
+        * fast/canvas/webgl/texture-complete-expected.txt: Added.
+        * fast/canvas/webgl/texture-complete.html: Added.
+
 2010-07-13  Andreas Kling  <andreas.kling at nokia.com>
 
         Reviewed by Darin Adler.
diff --git a/LayoutTests/fast/canvas/webgl/texture-complete-expected.txt b/LayoutTests/fast/canvas/webgl/texture-complete-expected.txt
new file mode 100644
index 0000000..8b5ff70
--- /dev/null
+++ b/LayoutTests/fast/canvas/webgl/texture-complete-expected.txt
@@ -0,0 +1,8 @@
+ 
+Checks that a texture that is not -texture-complete- does not draw if filtering needs mips
+
+PASS texture that is not -texture-complete- when TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/canvas/webgl/texture-complete.html b/LayoutTests/fast/canvas/webgl/texture-complete.html
new file mode 100644
index 0000000..47b1924
--- /dev/null
+++ b/LayoutTests/fast/canvas/webgl/texture-complete.html
@@ -0,0 +1,123 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+  "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+<title>WebGL "Texture Complete" texture conformance test.</title>
+<link rel="stylesheet" href="../../js/resources/js-test-style.css"/>
+<script src="../../js/resources/js-test-pre.js"></script>
+<script src="resources/utils3d.js"> </script>
+</head>
+<body>
+<canvas id="example" width="40" height="40" style="width: 40px; height: 40px;"></canvas>
+<canvas id="canvas2d" width="16" height="16" style="width: 40px; height: 40px;"></canvas>
+<div id="description"></div>
+<div id="console"></div>
+<script id="vshader" type="x-shader/x-vertex">
+attribute vec4 vPosition;
+attribute vec2 texCoord0;
+varying vec2 texCoord;
+void main()
+{
+    gl_Position = vPosition;
+    texCoord = texCoord0;
+}
+</script>
+
+<script id="fshader" type="x-shader/x-fragment">
+uniform sampler2D tex;
+varying vec2 texCoord;
+void main()
+{
+    gl_FragColor = texture2D(tex, texCoord);
+}
+</script>
+
+<script>
+function init()
+{
+  if (window.layoutTestController) {
+    layoutTestController.overridePreference("WebKitWebGLEnabled", "1");
+    layoutTestController.dumpAsText();
+  }
+
+  debug("Checks that a texture that is not -texture-complete- does not draw if"+
+        " filtering needs mips");
+  debug("");
+
+  var canvas2d = document.getElementById("canvas2d");
+  var ctx2d = canvas2d.getContext("2d");
+  ctx2d.fillStyle = "rgba(0,192,128,255)";
+  ctx2d.fillRect(0, 0, 16, 16);
+
+  gl = initWebGL("example", "vshader", "fshader", [ "vPosition", "texCoord0"],
+                 [ 0, 0, 0, 1 ], 1);
+
+  gl.disable(gl.DEPTH_TEST);
+  gl.disable(gl.BLEND);
+
+  var vertexObject = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+  gl.bufferData(gl.ARRAY_BUFFER,
+                new Float32Array([ -1,1,0, 1,1,0, -1,-1,0,
+                                   -1,-1,0, 1,1,0, 1,-1,0 ]),
+                gl.STATIC_DRAW);
+  gl.enableVertexAttribArray(0);
+  gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0);
+
+  var vertexObject = gl.createBuffer();
+  gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject);
+  gl.bufferData(gl.ARRAY_BUFFER,
+                new Float32Array([ 0,0, 1,0, 0,1,
+                                   0,1, 1,0, 1,1 ]),
+                gl.STATIC_DRAW);
+  gl.enableVertexAttribArray(1);
+  gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0);
+
+  var tex = gl.createTexture();
+  gl.bindTexture(gl.TEXTURE_2D, tex);
+  // 16x16 texture no mips
+  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, canvas2d);
+
+  var loc = gl.getUniformLocation(gl.program, "tex");
+  gl.uniform1i(loc, 0);
+
+  checkBuffer(0,0,0,255,
+      "texture that is not -texture-complete- when " +
+      "TEXTURE_MIN_FILTER not NEAREST or LINEAR should draw with 0,0,0,255");
+
+  function checkBuffer(r, g, b, a, msg) {
+    gl.clearColor(1,1,1,1);
+    gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
+    gl.drawArrays(gl.TRIANGLES, 0, 6);
+    gl.flush();
+    var buf = new Uint8Array(4 * 4 * 4);
+    gl.readPixels(0, 0, 4, 4, gl.RGBA, gl.UNSIGNED_BYTE, buf);
+    for (var i = 0; i < 4 * 4; ++i) {
+      var offset = i * 4;
+      if (buf[offset + 0] != r ||
+          buf[offset + 1] != g ||
+          buf[offset + 2] != b ||
+          buf[offset + 3] != a) {
+        debug('expected: ' + r + ', ' + g + ', ' + b + ', ' + a +
+              ' was: ' +
+              buf[offset + 0] + ', ' +
+              buf[offset + 1] + ', ' +
+              buf[offset + 2] + ', ' +
+              buf[offset + 3]);
+        testFailed(msg);
+        return;
+      }
+    }
+    testPassed(msg);
+  }
+}
+
+init();
+successfullyParsed = true;
+</script>
+
+<script src="../../js/resources/js-test-post.js"></script>
+
+</body>
+</html>
+
diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 1a98128..c92638e 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,39 @@
+2010-07-04  Zhenyao Mo  <zmo at google.com>
+
+        Reviewed by Darin Fisher.
+
+        Need to track texture completeness
+        https://bugs.webkit.org/show_bug.cgi?id=41381
+
+        Test: fast/canvas/webgl/texture-complete.html
+
+        * html/canvas/WebGLRenderingContext.cpp:
+        (WebCore::WebGLRenderingContext::WebGLRenderingContext): Init max texture level.
+        (WebCore::WebGLRenderingContext::bindTexture): Pass max texture level to setTarget().
+        (WebCore::WebGLRenderingContext::copyTexImage2D): Cache full texture info rather than partial.
+        (WebCore::WebGLRenderingContext::generateMipmap): Ditto.
+        (WebCore::WebGLRenderingContext::texImage2DBase): Ditto.
+        (WebCore::WebGLRenderingContext::validateTexFuncParameters): Also validate level.
+        * html/canvas/WebGLRenderingContext.h: Add max texture level.
+        * html/canvas/WebGLTexture.cpp: Update the class to fully cache texture information and track NPOT and COMPLETE states.
+        (WebCore::WebGLTexture::WebGLTexture):
+        (WebCore::WebGLTexture::setTarget): Check whether the texture is initialized or has been deleted.
+        (WebCore::WebGLTexture::setParameteri): Ditto.
+        (WebCore::WebGLTexture::setParameterf): Ditto.
+        (WebCore::WebGLTexture::setLevelInfo): Set texture info.
+        (WebCore::WebGLTexture::generateMipmapLevelInfo): Generate texture info for all levels after generateMipmaps() is called.
+        (WebCore::WebGLTexture::getInternalFormat): Return internal format on texture face 0 level 0.
+        (WebCore::WebGLTexture::isNPOT): Check whether the texture is initialized or has been deleted.
+        (WebCore::WebGLTexture::needToUseBlackTexture): Ditto.
+        (WebCore::WebGLTexture::_deleteObject):
+        (WebCore::WebGLTexture::mapTargetToIndex): Map target to index.
+        (WebCore::WebGLTexture::canGenerateMipmaps): Check whether Mipmaps can be generated.
+        (WebCore::WebGLTexture::computeLevelCount): Compute texture level count from width/height.
+        (WebCore::WebGLTexture::update): Update NPOT/COMPLETE states.
+        * html/canvas/WebGLTexture.h: Ditto.
+        (WebCore::WebGLTexture::LevelInfo::LevelInfo): Add data structure to fully cache texture info.
+        (WebCore::WebGLTexture::LevelInfo::setInfo): Set information.
+
 2010-07-13  Andreas Kling  <andreas.kling at nokia.com>
 
         Reviewed by Darin Adler.
diff --git a/WebCore/html/canvas/WebGLRenderingContext.cpp b/WebCore/html/canvas/WebGLRenderingContext.cpp
index b166c3b..a09e3ae 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.cpp
+++ b/WebCore/html/canvas/WebGLRenderingContext.cpp
@@ -115,12 +115,12 @@ WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, Pa
     m_context->getIntegerv(GraphicsContext3D::IMPLEMENTATION_COLOR_READ_TYPE, &implementationColorReadType);
     m_implementationColorReadType = implementationColorReadType;
 
-    int maxTextureSize = 0;
-    m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &maxTextureSize);
-    m_maxTextureSize = maxTextureSize;
-    int maxCubeMapTextureSize = 0;
-    m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &maxCubeMapTextureSize);
-    m_maxCubeMapTextureSize = maxCubeMapTextureSize;
+    m_maxTextureSize = 0;
+    m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize);
+    m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize);
+    m_maxCubeMapTextureSize = 0;
+    m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize);
+    m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize);
 
     if (!isGLES2Compliant()) {
         createFallbackBlackTextures1x1();
@@ -293,17 +293,20 @@ void WebGLRenderingContext::bindTexture(unsigned long target, WebGLTexture* text
         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
         return;
     }
-    if (target == GraphicsContext3D::TEXTURE_2D)
+    int maxLevel = 0;
+    if (target == GraphicsContext3D::TEXTURE_2D) {
         m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture;
-    else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP)
+        maxLevel = m_maxTextureLevel;
+    } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) {
         m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture;
-    else {
+        maxLevel = m_maxCubeMapTextureLevel;
+    } else {
         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
         return;
     }
     m_context->bindTexture(target, texture);
     if (!isGLES2Compliant() && texture)
-        texture->setTarget(target);
+        texture->setTarget(target, maxLevel);
     cleanupAfterGraphicsCall(false);
 }
 
@@ -555,10 +558,8 @@ void WebGLRenderingContext::copyTexImage2D(unsigned long target, long level, uns
     // FIXME: if the framebuffer is not complete, none of the below should be executed.
     WebGLTexture* tex = getTextureBinding(target);
     if (!isGLES2Compliant()) {
-        if (tex && !level) // only for level 0
-            tex->setSize(target, width, height);
         if (tex)
-            tex->setInternalFormat(internalformat);
+            tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE);
     }
     if (m_framebufferBinding && tex)
         m_framebufferBinding->onAttachedObjectChange(tex);
@@ -1130,18 +1131,22 @@ void WebGLRenderingContext::frontFace(unsigned long mode)
 
 void WebGLRenderingContext::generateMipmap(unsigned long target)
 {
+    RefPtr<WebGLTexture> tex;
     if (!isGLES2Compliant()) {
-        RefPtr<WebGLTexture> tex = 0;
         if (target == GraphicsContext3D::TEXTURE_2D)
             tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding;
         else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP)
             tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding;
-        if (tex && tex->isNPOT()) {
+        if (tex && !tex->canGenerateMipmaps()) {
             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
             return;
         }
     }
     m_context->generateMipmap(target);
+    if (!isGLES2Compliant()) {
+        if (tex)
+            tex->generateMipmapLevelInfo();
+    }
     cleanupAfterGraphicsCall(false);
 }
 
@@ -2130,10 +2135,8 @@ void WebGLRenderingContext::texImage2DBase(unsigned target, unsigned level, unsi
                           border, format, type, pixels);
     WebGLTexture* tex = getTextureBinding(target);
     if (!isGLES2Compliant()) {
-        if (tex && !level) // only for level 0
-            tex->setSize(target, width, height);
         if (tex)
-            tex->setInternalFormat(internalformat);
+            tex->setLevelInfo(target, level, internalformat, width, height, type);
     }
     if (m_framebufferBinding && tex)
         m_framebufferBinding->onAttachedObjectChange(tex);
@@ -3417,9 +3420,6 @@ bool WebGLRenderingContext::validateTexFuncParameters(unsigned long target, long
     if (!validateTexFuncFormatAndType(format, type))
         return false;
 
-    if (isGLES2Compliant())
-        return true;
-
     if (width < 0 || height < 0 || level < 0) {
         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
         return false;
@@ -3427,7 +3427,7 @@ bool WebGLRenderingContext::validateTexFuncParameters(unsigned long target, long
 
     switch (target) {
     case GraphicsContext3D::TEXTURE_2D:
-        if (width > m_maxTextureSize || height > m_maxTextureSize) {
+        if (width > m_maxTextureSize || height > m_maxTextureSize || level > m_maxTextureLevel) {
             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
             return false;
         }
@@ -3438,7 +3438,7 @@ bool WebGLRenderingContext::validateTexFuncParameters(unsigned long target, long
     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
-        if (width != height || width > m_maxCubeMapTextureSize) {
+        if (width != height || width > m_maxCubeMapTextureSize || level > m_maxCubeMapTextureLevel) {
             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
             return false;
         }
diff --git a/WebCore/html/canvas/WebGLRenderingContext.h b/WebCore/html/canvas/WebGLRenderingContext.h
index dc000b6..fa0d9d0 100644
--- a/WebCore/html/canvas/WebGLRenderingContext.h
+++ b/WebCore/html/canvas/WebGLRenderingContext.h
@@ -412,8 +412,10 @@ class WebKitCSSMatrix;
         RefPtr<WebGLTexture> m_blackTexture2D;
         RefPtr<WebGLTexture> m_blackTextureCubeMap;
 
-        long m_maxTextureSize;
-        long m_maxCubeMapTextureSize;
+        int m_maxTextureSize;
+        int m_maxCubeMapTextureSize;
+        int m_maxTextureLevel;
+        int m_maxCubeMapTextureLevel;
 
         int m_packAlignment;
         int m_unpackAlignment;
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;
 }
 
 }
diff --git a/WebCore/html/canvas/WebGLTexture.h b/WebCore/html/canvas/WebGLTexture.h
index 4d16b59..d4a32f0 100644
--- a/WebCore/html/canvas/WebGLTexture.h
+++ b/WebCore/html/canvas/WebGLTexture.h
@@ -30,6 +30,7 @@
 
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
 
 namespace WebCore {
     
@@ -47,19 +48,26 @@ namespace WebCore {
             cubeMapRWrapModeInitialized = initialized;
         }
 
-        void setTarget(unsigned long);
+        void setTarget(unsigned long target, int maxLevel);
         void setParameteri(unsigned long pname, int param);
         void setParameterf(unsigned long pname, float param);
-        void setSize(unsigned long target, unsigned width, unsigned height);
 
-        void setInternalFormat(unsigned long internalformat) { m_internalFormat = internalformat; }
-        unsigned long getInternalFormat() const { return m_internalFormat; }
+        void setLevelInfo(unsigned long target, int level, unsigned long internalFormat, int width, int height, unsigned long type);
 
+        bool canGenerateMipmaps();
+        // Generate all level information.
+        void generateMipmapLevelInfo();
+
+        unsigned long getInternalFormat() const;
+
+        // Whether width/height is NotPowerOfTwo.
         static bool isNPOT(unsigned, unsigned);
 
-        bool isNPOT() const { return m_isNPOT; }
+        bool isNPOT() const;
         // Determine if texture sampling should always return [0, 0, 0, 1] (OpenGL ES 2.0 Sec 3.8.2).
-        bool needToUseBlackTexture() const { return m_needToUseBlackTexture; }
+        bool needToUseBlackTexture() const;
+
+        static int computeLevelCount(int width, int height);
 
     protected:
         WebGLTexture(WebGLRenderingContext*);
@@ -69,7 +77,9 @@ namespace WebCore {
     private:
         virtual bool isTexture() const { return true; }
 
-        void updateNPOTStates();
+        void update();
+
+        int mapTargetToIndex(unsigned long);
 
         bool cubeMapRWrapModeInitialized;
 
@@ -80,12 +90,37 @@ namespace WebCore {
         int m_wrapS;
         int m_wrapT;
 
-        unsigned long m_internalFormat;
-
-        unsigned m_width[6];
-        unsigned m_height[6];
+        class LevelInfo {
+        public:
+            LevelInfo()
+                : valid(false)
+                , internalFormat(0)
+                , width(0)
+                , height(0)
+                , type(0)
+            {
+            }
+
+            void setInfo(unsigned long internalFmt, int w, int h, unsigned long tp)
+            {
+                valid = true;
+                internalFormat = internalFmt;
+                width = w;
+                height = h;
+                type = tp;
+            }
+
+            bool valid;
+            unsigned long internalFormat;
+            int width;
+            int height;
+            unsigned long type;
+        };
+
+        Vector<Vector<LevelInfo> > m_info;
 
         bool m_isNPOT;
+        bool m_isComplete;
         bool m_needToUseBlackTexture;
     };
     

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list