Bug 741837 - Hook up OMTC for Gonk [r=gal]
authorCody Brocious <cbrocious@mozilla.com>
Thu, 05 Apr 2012 09:15:19 -0700
changeset 94398 5738f35ffb113d6ea2ef39f30709e855c6dc38a8
parent 94397 fab75de4ad2ed61333038cee30eb71dc7083429e
child 94399 fc2d53ab4582a60d486a9258e9cade45d0b1930b
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgal
bugs741837
milestone14.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 741837 - Hook up OMTC for Gonk [r=gal]
b2g/app/b2g.js
widget/gonk/Framebuffer.cpp
widget/gonk/Framebuffer.h
widget/gonk/nsWindow.cpp
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -302,16 +302,17 @@ pref("editor.singleLine.pasteNewlines", 
 
 // threshold where a tap becomes a drag, in 1/240" reference pixels
 // The names of the preferences are to be in sync with nsEventStateManager.cpp
 pref("ui.dragThresholdX", 25);
 pref("ui.dragThresholdY", 25);
 
 // Layers Acceleration
 pref("layers.acceleration.disabled", false);
+pref("layers.offmainthreadcomposition.enabled", true);
 
 // Web Notifications
 pref("notification.feature.enabled", true);
 
 // IndexedDB
 pref("indexedDB.feature.enabled", true);
 pref("dom.indexedDB.warningQuota", 5);
 
--- a/widget/gonk/Framebuffer.cpp
+++ b/widget/gonk/Framebuffer.cpp
@@ -144,16 +144,36 @@ Open(nsIntSize* aScreenSize)
 
     // Clear the framebuffer to a known state.
     Present(nsIntRect());
 
     *aScreenSize = size;
     return true;
 }
 
+bool
+GetSize(nsIntSize *aScreenSize) {
+    if (0 <= sFd)
+        return true;
+
+    ScopedClose fd(open("/dev/graphics/fb0", O_RDWR));
+    if (0 > fd.mFd) {
+        LOG("Error opening framebuffer device");
+        return false;
+    }
+
+    if (0 > ioctl(fd.mFd, FBIOGET_VSCREENINFO, &sVi)) {
+        LOG("Error getting variable screeninfo");
+        return false;
+    }
+
+    *aScreenSize = gfxIntSize(sVi.xres, sVi.yres);
+    return true;
+}
+
 void
 Close()
 {
     if (0 > sFd)
         return;
 
     munmap(Buffers()[0]->Data(), sMappedSize);
     delete sBuffers;
--- a/widget/gonk/Framebuffer.h
+++ b/widget/gonk/Framebuffer.h
@@ -64,16 +64,18 @@ namespace Framebuffer {
 // calls is undefined.  Open() is idempotent.
 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();
 
+bool GetSize(nsIntSize *aScreenSize);
+
 // Return the buffer to be drawn into, that will be the next frame.
 gfxASurface* BackBuffer();
 
 // 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
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -38,16 +38,17 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 #include <fcntl.h>
 
 #include "android/log.h"
 #include "ui/FramebufferNativeWindow.h"
 
 #include "mozilla/Hal.h"
+#include "mozilla/Preferences.h"
 #include "mozilla/FileUtils.h"
 #include "Framebuffer.h"
 #include "gfxContext.h"
 #include "gfxUtils.h"
 #include "GLContextProvider.h"
 #include "LayerManagerOGL.h"
 #include "nsAutoPtr.h"
 #include "nsAppShell.h"
@@ -71,16 +72,18 @@ static nsIntRect sVirtualBounds;
 static gfxMatrix sRotationMatrix;
 
 static nsRefPtr<GLContext> sGLContext;
 static nsTArray<nsWindow *> sTopWindows;
 static nsWindow *gWindowToRedraw = nsnull;
 static nsWindow *gFocusedWindow = nsnull;
 static android::FramebufferNativeWindow *gNativeWindow = nsnull;
 static bool sFramebufferOpen;
+static bool sUsingOMTC;
+static nsRefPtr<gfxASurface> sOMTCSurface;
 static nsCOMPtr<nsIThread> sFramebufferWatchThread;
 
 namespace {
 
 class ScreenOnOffEvent : public nsRunnable {
 public:
     ScreenOnOffEvent(bool on)
         : mIsOn(on)
@@ -150,39 +153,51 @@ private:
     nsRefPtr<ScreenOnOffEvent> mScreenOnEvent;
     nsRefPtr<ScreenOnOffEvent> mScreenOffEvent;
 };
 
 } // anonymous namespace
 
 nsWindow::nsWindow()
 {
-    if (!sGLContext && !sFramebufferOpen) {
+    if (!sGLContext && !sFramebufferOpen && !sUsingOMTC) {
         // workaround Bug 725143
         hal::SetScreenEnabled(true);
 
         // Watching screen on/off state
         NS_NewThread(getter_AddRefs(sFramebufferWatchThread), new FramebufferWatcher());
 
+        sUsingOMTC = Preferences::GetBool("layers.offmainthreadcomposition.enabled", false);
+
         // We (apparently) don't have a way to tell if allocating the
         // fbs succeeded or failed.
         gNativeWindow = new android::FramebufferNativeWindow();
-        sGLContext = GLContextProvider::CreateForWindow(this);
-        // CreateForWindow sets up gScreenBounds
-        if (!sGLContext) {
-            LOG("Failed to create GL context for fb, trying /dev/graphics/fb0");
-
-            // We can't delete gNativeWindow.
+        if (sUsingOMTC) {
+            nsIntSize screenSize;
+            bool gotFB = Framebuffer::GetSize(&screenSize);
+            MOZ_ASSERT(gotFB);
+            gScreenBounds = nsIntRect(nsIntPoint(0, 0), screenSize);
 
-            nsIntSize screenSize;
-            sFramebufferOpen = Framebuffer::Open(&screenSize);
-            gScreenBounds = nsIntRect(nsIntPoint(0, 0), screenSize);
-            if (!sFramebufferOpen) {
-                LOG("Failed to mmap fb(?!?), aborting ...");
-                NS_RUNTIMEABORT("Can't open GL context and can't fall back on /dev/graphics/fb0 ...");
+            sOMTCSurface = new gfxImageSurface(gfxIntSize(1, 1),
+                gfxASurface::ImageFormatRGB24);
+        } else {
+            sGLContext = GLContextProvider::CreateForWindow(this);
+            // CreateForWindow sets up gScreenBounds
+            if (!sGLContext) {
+                LOG("Failed to create GL context for fb, trying /dev/graphics/fb0");
+
+                // We can't delete gNativeWindow.
+
+                nsIntSize screenSize;
+                sFramebufferOpen = Framebuffer::Open(&screenSize);
+                gScreenBounds = nsIntRect(nsIntPoint(0, 0), screenSize);
+                if (!sFramebufferOpen) {
+                    LOG("Failed to mmap fb(?!?), aborting ...");
+                    NS_RUNTIMEABORT("Can't open GL context and can't fall back on /dev/graphics/fb0 ...");
+                }
             }
         }
         sVirtualBounds = gScreenBounds;
 
         nsAppShell::NotifyScreenInitialized();
     }
 }
 
@@ -209,32 +224,39 @@ nsWindow::DoDraw(void)
 
     LayerManager* lm = gWindowToRedraw->GetLayerManager();
     if (LayerManager::LAYERS_OPENGL == lm->GetBackendType()) {
         LayerManagerOGL* oglm = static_cast<LayerManagerOGL*>(lm);
         oglm->SetClippingRegion(event.region);
         oglm->SetWorldTransform(sRotationMatrix);
         gWindowToRedraw->mEventCallback(&event);
     } else if (LayerManager::LAYERS_BASIC == lm->GetBackendType()) {
-        MOZ_ASSERT(sFramebufferOpen);
+        MOZ_ASSERT(sFramebufferOpen || sUsingOMTC);
+        nsRefPtr<gfxASurface> targetSurface;
 
-        nsRefPtr<gfxASurface> backBuffer = Framebuffer::BackBuffer();
+        if(sUsingOMTC)
+            targetSurface = sOMTCSurface;
+        else
+            targetSurface = Framebuffer::BackBuffer();
+
         {
-            nsRefPtr<gfxContext> ctx = new gfxContext(backBuffer);
+            nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
             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(event.region);
+        if (!sUsingOMTC) {
+            targetSurface->Flush();
+            Framebuffer::Present(event.region);
+        }
     } else {
         NS_RUNTIMEABORT("Unexpected layer manager type");
     }
 }
 
 nsEventStatus
 nsWindow::DispatchInputEvent(nsGUIEvent &aEvent)
 {
@@ -487,16 +509,22 @@ nsWindow::GetLayerManager(PLayersChild* 
 
     nsWindow *topWindow = sTopWindows[0];
 
     if (!topWindow) {
         LOG(" -- no topwindow\n");
         return nsnull;
     }
 
+    if (sUsingOMTC) {
+        CreateCompositor();
+        if (mLayerManager)
+            return mLayerManager;
+    }
+
     if (sGLContext) {
         nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
 
         if (layerManager->Initialize(sGLContext))
             mLayerManager = layerManager;
         else
             LOG("Could not create OGL LayerManager");
     } else {