Bug 743612: Fix OMTC on gonk. r=cjones
authorCody Brocious <cbrocious@mozilla.com>
Tue, 26 Jun 2012 16:38:50 +0200
changeset 97698 a047da349d5973742be094e56df963430415679e
parent 97697 074372a19576798de5262fc00676f4091c23e686
child 97699 65536f28b65ee6f44ab80969944975e9de7da633
push id22993
push useremorley@mozilla.com
push dateWed, 27 Jun 2012 10:31:27 +0000
treeherdermozilla-central@1a56f1f011c9 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs743612
milestone16.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 743612: Fix OMTC on gonk. r=cjones
widget/gonk/Framebuffer.cpp
widget/gonk/Framebuffer.h
widget/gonk/nsWindow.cpp
--- a/widget/gonk/Framebuffer.cpp
+++ b/widget/gonk/Framebuffer.cpp
@@ -34,16 +34,17 @@ namespace mozilla {
 namespace Framebuffer {
 
 static int sFd = -1;
 static size_t sMappedSize;
 static struct fb_var_screeninfo sVi;
 static size_t sActiveBuffer;
 typedef vector<nsRefPtr<gfxImageSurface> > BufferVector;
 BufferVector* sBuffers;
+static gfxIntSize *sScreenSize = nsnull;
 
 BufferVector& Buffers() { return *sBuffers; }
 
 bool
 SetGraphicsMode()
 {
     ScopedClose fd(open("/dev/tty0", O_RDWR | O_SYNC));
     if (0 > fd.get()) {
@@ -52,17 +53,17 @@ SetGraphicsMode()
     } else if (ioctl(fd.get(), KDSETMODE, (void*) KD_GRAPHICS)) {
         LOG("Error setting graphics mode on /dev/tty0");
         return false;
     }
     return true;
 }
 
 bool
-Open(nsIntSize* aScreenSize)
+Open()
 {
     if (0 <= sFd)
         return true;
 
     if (!SetGraphicsMode())
         return false;
 
     ScopedClose fd(open("/dev/graphics/fb0", O_RDWR));
@@ -93,63 +94,70 @@ Open(nsIntSize* aScreenSize)
     sFd = fd.get();
     fd.forget();
 
     // The android porting doc requires a /dev/graphics/fb0 device
     // that's double buffered with r5g6b5 format.  Hence the
     // hard-coded numbers here.
     gfxASurface::gfxImageFormat format = gfxASurface::ImageFormatRGB16_565;
     int bytesPerPixel = gfxASurface::BytePerPixelFromFormat(format);
-    gfxIntSize size(sVi.xres, sVi.yres);
-    long stride = size.width * bytesPerPixel;
-    size_t numFrameBytes = stride * size.height;
+    if (!sScreenSize) {
+        sScreenSize = new gfxIntSize(sVi.xres, sVi.yres);
+    }
+    long stride = sScreenSize->width * bytesPerPixel;
+    size_t numFrameBytes = stride * sScreenSize->height;
 
     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);
+      Buffers()[i] = new gfxImageSurface(data, *sScreenSize, stride, format);
     }
 
     // Clear the framebuffer to a known state.
     Present(nsIntRect());
 
-    *aScreenSize = size;
     return true;
 }
 
 bool
 GetSize(nsIntSize *aScreenSize) {
-    if (0 <= sFd)
+    // If the framebuffer has been opened, we should always have the size.
+    if (0 <= sFd || sScreenSize) {
+        *aScreenSize = *sScreenSize;
         return true;
+    }
 
     ScopedClose fd(open("/dev/graphics/fb0", O_RDWR));
     if (0 > fd.get()) {
         LOG("Error opening framebuffer device");
         return false;
     }
 
     if (0 > ioctl(fd.get(), FBIOGET_VSCREENINFO, &sVi)) {
         LOG("Error getting variable screeninfo");
         return false;
     }
 
-    *aScreenSize = gfxIntSize(sVi.xres, sVi.yres);
+    sScreenSize = new gfxIntSize(sVi.xres, sVi.yres);
+    *aScreenSize = *sScreenSize;
     return true;
 }
 
 void
 Close()
 {
     if (0 > sFd)
         return;
 
     munmap(Buffers()[0]->Data(), sMappedSize);
     delete sBuffers;
     sBuffers = NULL;
+    delete sScreenSize;
+    sScreenSize = NULL;
 
     close(sFd);
     sFd = -1;
 }
 
 gfxASurface*
 BackBuffer()
 {
--- a/widget/gonk/Framebuffer.h
+++ b/widget/gonk/Framebuffer.h
@@ -21,26 +21,27 @@ namespace Framebuffer {
 // -- ready to paint next frame --
 //  nsRefPtr<gfxASurface> backBuffer = BackBuffer();
 //  // ...
 //  Paint(backBuffer);
 //  // ...
 //  Present();
 //
 
-// Return true if the fbdev was successfully opened, along with the
-// dimensions of the screen.  If this fails, the result of all further
-// calls is undefined.  Open() is idempotent.
-bool Open(nsIntSize* aScreenSize);
+// Return true if the fbdev was successfully opened.  If this fails, 
+// the result of all further calls is undefined.  Open() is idempotent.
+bool Open();
 
 // After Close(), the result of all further calls is undefined.
 // Close() is idempotent, and Open() can be called again after
 // Close().
 void Close();
 
+// Return true if the fbdev was successfully opened or the size was
+// already cached.
 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);
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -44,16 +44,17 @@ 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 bool sScreenInitialized;
 static nsRefPtr<gfxASurface> sOMTCSurface;
 static pthread_t sFramebufferWatchThread;
 
 namespace {
 
 class ScreenOnOffEvent : public nsRunnable {
 public:
     ScreenOnOffEvent(bool on)
@@ -115,56 +116,41 @@ static void *frameBufferWatcher(void *) 
     
     return NULL;
 }
 
 } // anonymous namespace
 
 nsWindow::nsWindow()
 {
-    if (!sGLContext && !sFramebufferOpen && !sUsingOMTC) {
+    if (!sScreenInitialized) {
         // workaround Bug 725143
         hal::SetScreenEnabled(true);
 
         // Watching screen on/off state by using a pthread
         // which implicitly calls exit() when the main thread ends
         if (pthread_create(&sFramebufferWatchThread, NULL, frameBufferWatcher, NULL)) {
             NS_RUNTIMEABORT("Failed to create framebufferWatcherThread, aborting...");
         }
 
         sUsingOMTC = UseOffMainThreadCompositing();
 
+        if (sUsingOMTC) {
+          sOMTCSurface = new gfxImageSurface(gfxIntSize(1, 1),
+                                             gfxASurface::ImageFormatRGB24);
+        }
+
         // We (apparently) don't have a way to tell if allocating the
         // fbs succeeded or failed.
         gNativeWindow = new android::FramebufferNativeWindow();
-        if (sUsingOMTC) {
-            nsIntSize screenSize;
-            bool gotFB = Framebuffer::GetSize(&screenSize);
-            MOZ_ASSERT(gotFB);
-            gScreenBounds = nsIntRect(nsIntPoint(0, 0), screenSize);
 
-            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 ...");
-                }
-            }
-        }
+        nsIntSize screenSize;
+        bool gotFB = Framebuffer::GetSize(&screenSize);
+        MOZ_ASSERT(gotFB);
+        gScreenBounds = nsIntRect(nsIntPoint(0, 0), screenSize);
 
         char propValue[PROPERTY_VALUE_MAX];
         property_get("ro.sf.hwrotation", propValue, "0");
         sPhysicalScreenRotation = atoi(propValue) / 90;
 
         // Unlike nsScreenGonk::SetRotation(), only support 0 and 180 as there
         // are no known screens that are mounted at 90 or 270 at the moment.
         switch (sPhysicalScreenRotation) {
@@ -176,16 +162,18 @@ nsWindow::nsWindow()
             sRotationMatrix.Rotate(M_PI);
             break;
         default:
             MOZ_NOT_REACHED("Unknown rotation");
             break;
         }
         sVirtualBounds = gScreenBounds;
 
+        sScreenInitialized = true;
+
         nsAppShell::NotifyScreenInitialized();
     }
 }
 
 nsWindow::~nsWindow()
 {
 }
 
@@ -487,41 +475,56 @@ nsWindow::GetLayerManager(PLayersChild* 
                           LayerManagerPersistence aPersistence,
                           bool* aAllowRetaining)
 {
     if (aAllowRetaining)
         *aAllowRetaining = true;
     if (mLayerManager)
         return mLayerManager;
 
+      // Set mUseAcceleratedRendering here to make it consistent with
+      // nsBaseWidget::GetLayerManager
+    mUseAcceleratedRendering = GetShouldAccelerate();
+    if (!mUseAcceleratedRendering) {
+        sFramebufferOpen = Framebuffer::Open();
+        if (!sFramebufferOpen) {
+            LOG("Failed to mmap fb(?!?), aborting ...");
+            NS_RUNTIMEABORT("Can't open GL context and can't fall back on /dev/graphics/fb0 ...");
+        }
+    }
+
     nsWindow *topWindow = sTopWindows[0];
 
     if (!topWindow) {
         LOG(" -- no topwindow\n");
         return nsnull;
     }
 
     if (sUsingOMTC) {
         CreateCompositor();
         if (mLayerManager)
             return mLayerManager;
     }
 
+    DebugOnly<nsIntRect> fbBounds = gScreenBounds;
+    sGLContext = GLContextProvider::CreateForWindow(this);
+    MOZ_ASSERT(fbBounds.value == gScreenBounds);
     if (sGLContext) {
         nsRefPtr<LayerManagerOGL> layerManager = new LayerManagerOGL(this);
 
-        if (layerManager->Initialize(sGLContext))
+        if (layerManager->Initialize(sGLContext)) {
             mLayerManager = layerManager;
-        else
+            return mLayerManager;
+        } else {
             LOG("Could not create OGL LayerManager");
-    } else {
-        MOZ_ASSERT(sFramebufferOpen);
-        mLayerManager = new BasicShadowLayerManager(this);
+        }
     }
 
+    mLayerManager = new BasicShadowLayerManager(this);
+
     return mLayerManager;
 }
 
 gfxASurface *
 nsWindow::GetThebesSurface()
 {
     /* This is really a dummy surface; this is only used when doing reflow, because
      * we need a RenderingContext to measure text against.