Bug 714307: Synchronize back/front buffers in gonk fallback path. r=mwu
authorChris Jones <jones.chris.g@gmail.com>
Fri, 30 Dec 2011 18:28:40 -0800
changeset 84827 b91a01700813141d43744a0e509cc9cf60e0c88b
parent 84826 a258a0b2d9e4093ae1844ba4733e1010054b5fa7
child 84828 7e94dbbde863cbef3f6981989e8dc9b7ac0fd2b1
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmwu
bugs714307
milestone12.0a1
Bug 714307: Synchronize back/front buffers in gonk fallback path. r=mwu
widget/src/gonk/Framebuffer.cpp
widget/src/gonk/Framebuffer.h
widget/src/gonk/nsWindow.cpp
--- a/widget/src/gonk/Framebuffer.cpp
+++ b/widget/src/gonk/Framebuffer.cpp
@@ -47,17 +47,19 @@
 #include <sys/types.h>
 #include <unistd.h>
 
 #include <vector>
 
 #include "android/log.h"
 
 #include "Framebuffer.h"
+#include "gfxContext.h"
 #include "gfxImageSurface.h"
+#include "gfxUtils.h"
 #include "mozilla/FileUtils.h"
 #include "nsTArray.h"
 
 #define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
 
 using namespace std;
 
 namespace mozilla {
@@ -136,17 +138,17 @@ Open(nsIntSize* aScreenSize)
     sBuffers = new BufferVector(2);
     unsigned char* data = static_cast<unsigned char*>(mem);
     for (size_t i = 0; i < 2; ++i, data += numFrameBytes) {
       memset(data, 0, numFrameBytes);
       Buffers()[i] = new gfxImageSurface(data, size, stride, format);
     }
 
     // Clear the framebuffer to a known state.
-    Present();
+    Present(nsIntRect());
 
     *aScreenSize = size;
     return true;
 }
 
 void
 Close()
 {
@@ -162,24 +164,37 @@ Close()
 }
 
 gfxASurface*
 BackBuffer()
 {
     return Buffers()[!sActiveBuffer];
 }
 
+static gfxASurface*
+FrontBuffer()
+{
+    return Buffers()[sActiveBuffer];
+}
+
 void
-Present()
+Present(const nsIntRegion& aUpdated)
 {
     sActiveBuffer = !sActiveBuffer;
 
     sVi.yres_virtual = sVi.yres * 2;
     sVi.yoffset = sActiveBuffer * sVi.yres;
     sVi.bits_per_pixel = 16;
     if (ioctl(sFd, FBIOPUT_VSCREENINFO, &sVi) < 0) {
         LOG("Error presenting front buffer");
     }
+
+    nsRefPtr<gfxContext> ctx = new gfxContext(BackBuffer());
+    gfxUtils::PathFromRegion(ctx, aUpdated);
+    ctx->Clip();
+    ctx->SetSource(FrontBuffer());
+    ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
+    ctx->Paint(1.0);
 }
 
 } // namespace Framebuffer
 
 } // namespace mozilla
--- a/widget/src/gonk/Framebuffer.h
+++ b/widget/src/gonk/Framebuffer.h
@@ -33,16 +33,17 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 class gfxASurface;
+class nsIntRegion;
 class nsIntSize;
 
 namespace mozilla {
 
 namespace Framebuffer {
 
 //
 // The general usage of Framebuffer is
@@ -66,14 +67,15 @@ bool Open(nsIntSize* aScreenSize);
 // After Close(), the result of all further calls is undefined.
 // Close() is idempotent, and Open() can be called again after
 // Close().
 void Close();
 
 // Return the buffer to be drawn into, that will be the next frame.
 gfxASurface* BackBuffer();
 
-// Swap the front buffer for the back buffer.
-void Present();
+// Swap the front buffer for the back buffer.  |aUpdated| is the
+// region of the back buffer that was repainted.
+void Present(const nsIntRegion& aUpdated);
 
 } // namespace Framebuffer
 
 } // namespace mozilla
--- a/widget/src/gonk/nsWindow.cpp
+++ b/widget/src/gonk/nsWindow.cpp
@@ -106,37 +106,35 @@ nsWindow::DoDraw(void)
     }
 
     nsPaintEvent event(true, NS_PAINT, gWindowToRedraw);
     event.region = gWindowToRedraw->mDirtyRegion;
     gWindowToRedraw->mDirtyRegion.SetEmpty();
 
     LayerManager* lm = gWindowToRedraw->GetLayerManager();
     if (LayerManager::LAYERS_OPENGL == lm->GetBackendType()) {
-        static_cast<LayerManagerOGL*>(lm)->
-            SetClippingRegion(nsIntRegion(gScreenBounds));
+        static_cast<LayerManagerOGL*>(lm)->SetClippingRegion(event.region);
         gWindowToRedraw->mEventCallback(&event);
     } else if (LayerManager::LAYERS_BASIC == lm->GetBackendType()) {
         MOZ_ASSERT(sFramebufferOpen);
 
         nsRefPtr<gfxASurface> backBuffer = Framebuffer::BackBuffer();
         {
             nsRefPtr<gfxContext> ctx = new gfxContext(backBuffer);
-            ctx->NewPath();
             gfxUtils::PathFromRegion(ctx, event.region);
             ctx->Clip();
 
             // No double-buffering needed.
             AutoLayerManagerSetup setupLayerManager(
                 gWindowToRedraw, ctx, BasicLayerManager::BUFFER_NONE);
             gWindowToRedraw->mEventCallback(&event);
         }
         backBuffer->Flush();
 
-        Framebuffer::Present();
+        Framebuffer::Present(event.region);
     } else {
         NS_RUNTIMEABORT("Unexpected layer manager type");
     }
 }
 
 nsEventStatus
 nsWindow::DispatchInputEvent(nsGUIEvent &aEvent)
 {