Bug 1066664 - Fix screenshot rotation. r=mwoodrow, a=bajaj
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Tue, 30 Sep 2014 16:20:48 -0400
changeset 225617 167b548389d3ec57bf3866fcc61750a6dcfa10c1
parent 225616 6aa3e380165fea27c4ee7e7e9bd19afde39c5c86
child 225618 ffdd7ad4732741ce1da79e502f050b6ae06a78d6
push id3979
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 16:35:44 +0000
treeherdermozilla-beta@30f2cc610691 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmwoodrow, bajaj
bugs1066664
milestone34.0a2
Bug 1066664 - Fix screenshot rotation. r=mwoodrow, a=bajaj This moves the screenshot (now-nonexistent) unrotation code from the opengl compositor into ClientLayerManager.cpp
gfx/layers/client/ClientLayerManager.cpp
widget/WidgetUtils.h
widget/xpwidgets/WidgetUtils.cpp
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -426,30 +426,47 @@ ClientLayerManager::RunOverfillCallback(
 void
 ClientLayerManager::MakeSnapshotIfRequired()
 {
   if (!mShadowTarget) {
     return;
   }
   if (mWidget) {
     if (CompositorChild* remoteRenderer = GetRemoteRenderer()) {
+      // The compositor doesn't draw to a different sized surface
+      // when there's a rotation. Instead we rotate the result
+      // when drawing into dt
+      nsIntRect outerBounds;
+      mWidget->GetBounds(outerBounds);
+
       nsIntRect bounds = ToOutsideIntRect(mShadowTarget->GetClipExtents());
+      if (mTargetRotation) {
+        bounds = RotateRect(bounds, outerBounds, mTargetRotation);
+      }
+
       SurfaceDescriptor inSnapshot;
       if (!bounds.IsEmpty() &&
           mForwarder->AllocSurfaceDescriptor(bounds.Size().ToIntSize(),
                                              gfxContentType::COLOR_ALPHA,
                                              &inSnapshot) &&
           remoteRenderer->SendMakeSnapshot(inSnapshot, bounds)) {
         RefPtr<DataSourceSurface> surf = GetSurfaceForDescriptor(inSnapshot);
         DrawTarget* dt = mShadowTarget->GetDrawTarget();
+
         Rect dstRect(bounds.x, bounds.y, bounds.width, bounds.height);
         Rect srcRect(0, 0, bounds.width, bounds.height);
+
+        gfx::Matrix rotate = ComputeTransformForUnRotation(outerBounds, mTargetRotation);
+
+        gfx::Matrix oldMatrix = dt->GetTransform();
+        dt->SetTransform(oldMatrix * rotate);
         dt->DrawSurface(surf, dstRect, srcRect,
                         DrawSurfaceOptions(),
                         DrawOptions(1.0f, CompositionOp::OP_OVER));
+        dt->SetTransform(oldMatrix);
       }
       mForwarder->DestroySharedSurface(&inSnapshot);
     }
   }
   mShadowTarget = nullptr;
 }
 
 void
--- a/widget/WidgetUtils.h
+++ b/widget/WidgetUtils.h
@@ -21,11 +21,18 @@ enum ScreenRotation {
   ROTATION_270,
 
   ROTATION_COUNT
 };
 
 gfx::Matrix ComputeTransformForRotation(const nsIntRect& aBounds,
                                         ScreenRotation aRotation);
 
+gfx::Matrix ComputeTransformForUnRotation(const nsIntRect& aBounds,
+                                          ScreenRotation aRotation);
+
+nsIntRect RotateRect(nsIntRect aRect,
+                     const nsIntRect& aBounds,
+                     ScreenRotation aRotation);
+
 } // namespace mozilla
 
 #endif // mozilla_WidgetUtils_h
--- a/widget/xpwidgets/WidgetUtils.cpp
+++ b/widget/xpwidgets/WidgetUtils.cpp
@@ -32,9 +32,61 @@ ComputeTransformForRotation(const nsIntR
         transform = gfx::Matrix::Rotation(floatPi * 3 / 2) * transform;
         break;
     default:
         MOZ_CRASH("Unknown rotation");
     }
     return transform;
 }
 
+gfx::Matrix
+ComputeTransformForUnRotation(const nsIntRect& aBounds,
+                              ScreenRotation aRotation)
+{
+    gfx::Matrix transform;
+    static const gfx::Float floatPi = static_cast<gfx::Float>(M_PI);
+
+    switch (aRotation) {
+    case ROTATION_0:
+        break;
+    case ROTATION_90:
+        transform.PreTranslate(0, aBounds.height);
+        transform.PreRotate(floatPi * 3 / 2);
+        break;
+    case ROTATION_180:
+        transform.PreTranslate(aBounds.width, aBounds.height);
+        transform.PreRotate(floatPi);
+        break;
+    case ROTATION_270:
+        transform.PreTranslate(aBounds.width, 0);
+        transform.PreRotate(floatPi / 2);
+        break;
+    default:
+        MOZ_CRASH("Unknown rotation");
+    }
+    return transform;
+}
+
+nsIntRect RotateRect(nsIntRect aRect,
+                     const nsIntRect& aBounds,
+                     ScreenRotation aRotation)
+{
+  switch (aRotation) {
+    case ROTATION_0:
+      return aRect;
+    case ROTATION_90:
+      return nsIntRect(aRect.y,
+                       aBounds.width - aRect.x - aRect.width,
+                       aRect.height, aRect.width);
+    case ROTATION_180:
+      return nsIntRect(aBounds.width - aRect.x - aRect.width,
+                       aBounds.height - aRect.y - aRect.height,
+                       aRect.width, aRect.height);
+    case ROTATION_270:
+      return nsIntRect(aBounds.height - aRect.y - aRect.height,
+                       aRect.x,
+                       aRect.height, aRect.width);
+    default:
+      MOZ_CRASH("Unknown rotation");
+      return aRect;
+  }
+}
 } // namespace mozilla