Bug 780920, part 1: LayerManagerOGL needs to account for the world transform when reading back into a non-default target. r=roc
authorChris Jones <jones.chris.g@gmail.com>
Thu, 04 Oct 2012 00:05:23 -0700
changeset 115515 53bf054fe0f1e33215347d468ccd9777e0c85803
parent 115514 d946b507ebc2a6fb46ff4c17f8ff533b43adea92
child 115516 abefcbf2f2ee3b3feefe42fcae7e8b142255e057
push id1708
push userakeybl@mozilla.com
push dateMon, 19 Nov 2012 21:10:21 +0000
treeherdermozilla-beta@27b14fe50103 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs780920
milestone18.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 780920, part 1: LayerManagerOGL needs to account for the world transform when reading back into a non-default target. r=roc
gfx/layers/opengl/LayerManagerOGL.cpp
--- a/gfx/layers/opengl/LayerManagerOGL.cpp
+++ b/gfx/layers/opengl/LayerManagerOGL.cpp
@@ -866,16 +866,19 @@ LayerManagerOGL::Render()
     NS_WARNING("Call on destroyed layer manager");
     return;
   }
 
   nsIntRect rect;
   if (mIsRenderingToEGLSurface) {
     rect = nsIntRect(0, 0, mSurfaceSize.width, mSurfaceSize.height);
   } else {
+    // FIXME/bug XXXXXX this races with rotation changes on the main
+    // thread, and undoes all the care we take with layers txns being
+    // sent atomically with rotation changes
     mWidget->GetClientBounds(rect);
   }
   WorldTransformRect(rect);
 
   GLint width = rect.width;
   GLint height = rect.height;
 
   // We can't draw anything to something with no area
@@ -1181,17 +1184,17 @@ LayerManagerOGL::SetupBackBuffer(int aWi
 
 void
 LayerManagerOGL::CopyToTarget(gfxContext *aTarget)
 {
   nsIntRect rect;
   if (mIsRenderingToEGLSurface) {
     rect = nsIntRect(0, 0, mSurfaceSize.width, mSurfaceSize.height);
   } else {
-    mWidget->GetClientBounds(rect);
+    rect = nsIntRect(0, 0, mWidgetSize.width, mWidgetSize.height);
   }
   GLint width = rect.width;
   GLint height = rect.height;
 
   if ((int64_t(width) * int64_t(height) * int64_t(4)) > INT32_MAX) {
     NS_ERROR("Widget size too big - integer overflow!");
     return;
   }
@@ -1214,19 +1217,25 @@ LayerManagerOGL::CopyToTarget(gfxContext
     }
   }
 
   NS_ASSERTION(imageSurface->Stride() == width * 4,
                "Image Surfaces being created with weird stride!");
 
   mGLContext->ReadPixelsIntoImageSurface(imageSurface);
 
+  // Map from GL space to Cairo space and reverse the world transform.
+  gfxMatrix glToCairoTransform = mWorldMatrix;
+  glToCairoTransform.Invert();
+  glToCairoTransform.Scale(1.0, -1.0);
+  glToCairoTransform.Translate(-gfxPoint(0.0, height));
+
+  gfxContextAutoSaveRestore restore(aTarget);
   aTarget->SetOperator(gfxContext::OPERATOR_SOURCE);
-  aTarget->Scale(1.0, -1.0);
-  aTarget->Translate(-gfxPoint(0.0, height));
+  aTarget->SetMatrix(glToCairoTransform);
   aTarget->SetSource(imageSurface);
   aTarget->Paint();
 }
 
 void
 LayerManagerOGL::SetLayerProgramProjectionMatrix(const gfx3DMatrix& aMatrix)
 {
   for (unsigned int i = 0; i < mPrograms.Length(); ++i) {