Bug 814407 - reattach textures when a texture image is replaced - r=jgilbert, a=akeybl
authorBenoit Jacob <bjacob@mozilla.com>
Tue, 11 Dec 2012 16:57:30 -0500
changeset 109923 37eb9957ebb1beb6e59cc95b1896b37df7e95de3
parent 109922 807edeff94f6aa1aa0f63431c2d2bb5ca19d4f89
child 109924 95faada05b7fa0a893a09d51152323e5d19421d3
push id60
push userbjacob@mozilla.com
push dateWed, 12 Dec 2012 03:24:18 +0000
reviewersjgilbert, akeybl
bugs814407
milestone17.0.1esrpre
Bug 814407 - reattach textures when a texture image is replaced - r=jgilbert, a=akeybl
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextGL.cpp
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -1367,16 +1367,18 @@ protected:
         return mAlreadyGeneratedWarnings < 32;
     }
 
     uint64_t mLastUseIndex;
 
     void LoseOldestWebGLContextIfLimitExceeded();
     void UpdateLastUseIndex();
 
+    void ReattachTextureToAnyFramebufferToWorkAroundBugs(WebGLTexture *tex, WebGLint level);
+
 #ifdef XP_MACOSX
     // see bug 713305. This RAII helper guarantees that we're on the discrete GPU, during its lifetime
     // Debouncing note: we don't want to switch GPUs too frequently, so try to not create and destroy
     // these objects at high frequency. Having WebGLContext's hold one such object seems fine,
     // because WebGLContext objects only go away during GC, which shouldn't happen too frequently.
     // If in the future GC becomes much more frequent, we may have to revisit then (maybe use a timer).
     ForceDiscreteGPUHelperCGL mForceDiscreteGPUHelper;
 #endif
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -968,16 +968,19 @@ WebGLContext::CopyTexSubImage2D_base(Web
 
         GLint   actual_y             = clamped(y, 0, framebufferHeight);
         GLint   actual_y_plus_height = clamped(y + height, 0, framebufferHeight);
         GLsizei actual_height  = actual_y_plus_height - actual_y;
         GLint   actual_yoffset = yoffset + actual_y - y;
 
         gl->fCopyTexSubImage2D(target, level, actual_xoffset, actual_yoffset, actual_x, actual_y, actual_width, actual_height);
     }
+
+    if (!sub)
+        ReattachTextureToAnyFramebufferToWorkAroundBugs(tex, level);
 }
 
 NS_IMETHODIMP
 WebGLContext::MozCopyTexImage2D(WebGLenum target,
                                 WebGLint level,
                                 WebGLenum internalformat,
                                 WebGLint x,
                                 WebGLint y,
@@ -5191,16 +5194,18 @@ WebGLContext::CompressedTexImage2D(WebGL
 
     uint32_t byteLength = view.Length();
     if (!ValidateCompressedTextureSize(level, internalformat, width, height, byteLength, "compressedTexImage2D")) {
         return;
     }
 
     gl->fCompressedTexImage2D(target, level, internalformat, width, height, border, byteLength, view.Data());
     tex->SetImageInfo(target, level, width, height, internalformat, LOCAL_GL_UNSIGNED_BYTE);
+
+    ReattachTextureToAnyFramebufferToWorkAroundBugs(tex, level);
 }
 
 NS_IMETHODIMP
 WebGLContext::CompressedTexSubImage2D(WebGLenum target, WebGLint level, WebGLint xoffset,
                                       WebGLint yoffset, WebGLsizei width, WebGLsizei height,
                                       WebGLenum format, const JS::Value& pixels, JSContext *cx)
 {
     if (!pixels.isObject() || !JS_IsTypedArrayObject(&pixels.toObject(), cx)) {
@@ -5765,16 +5770,18 @@ WebGLContext::TexImage2D_base(WebGLenum 
     }
     
     if (error) {
         GenerateWarning("texImage2D generated error %s", ErrorName(error));
         return;
     }
 
     tex->SetImageInfo(target, level, width, height, format, type);
+
+    ReattachTextureToAnyFramebufferToWorkAroundBugs(tex, level);
 }
 
 NS_IMETHODIMP
 WebGLContext::TexImage2D_array(WebGLenum target, WebGLint level, WebGLenum internalformat,
                                WebGLsizei width, WebGLsizei height, WebGLint border,
                                WebGLenum format, WebGLenum type,
                                JSObject *pixels, JSContext *cx)
 {
@@ -6287,8 +6294,48 @@ InternalFormatForFormatAndType(WebGLenum
     default:
         break;
     }
 
     NS_ASSERTION(false, "Coding mistake -- bad format/type passed?");
     return 0;
 }
 
+void
+WebGLContext::ReattachTextureToAnyFramebufferToWorkAroundBugs(WebGLTexture *tex,
+                                                              WebGLint level)
+{
+    MOZ_ASSERT(tex);
+
+    if (!gl->WorkAroundDriverBugs())
+        return;
+
+    if (!mIsMesa)
+        return;
+
+    MakeContextCurrent();
+
+    for(WebGLFramebuffer *framebuffer = mFramebuffers.getFirst();
+        framebuffer;
+        framebuffer = framebuffer->getNext())
+    {
+        if (framebuffer->ColorAttachment().Texture() == tex) {
+            framebuffer->FramebufferTexture2D(
+              LOCAL_GL_FRAMEBUFFER, LOCAL_GL_COLOR_ATTACHMENT0,
+              tex->Target(), tex, level);
+        }
+        if (framebuffer->DepthAttachment().Texture() == tex) {
+            framebuffer->FramebufferTexture2D(
+              LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_ATTACHMENT,
+              tex->Target(), tex, level);
+        }
+        if (framebuffer->StencilAttachment().Texture() == tex) {
+            framebuffer->FramebufferTexture2D(
+              LOCAL_GL_FRAMEBUFFER, LOCAL_GL_STENCIL_ATTACHMENT,
+              tex->Target(), tex, level);
+        }
+        if (framebuffer->DepthStencilAttachment().Texture() == tex) {
+            framebuffer->FramebufferTexture2D(
+              LOCAL_GL_FRAMEBUFFER, LOCAL_GL_DEPTH_STENCIL_ATTACHMENT,
+              tex->Target(), tex, level);
+        }
+    }
+}