Bug 709120 - Add tiled buffer support for Android/native. r=pcwalton
authorChris Lord <chrislord.net@gmail.com>
Fri, 06 Jan 2012 11:22:11 +0000
changeset 86367 a664e35073407d4e2333b170a00c808987389947
parent 86366 4eb8bdad32dd5455dfd5f9d443870062fad69d86
child 86368 4a363485a656177d6cf1e4ea320943293a195c2c
push idunknown
push userunknown
push dateunknown
reviewerspcwalton
bugs709120
milestone12.0a1
Bug 709120 - Add tiled buffer support for Android/native. r=pcwalton This adds support for rendering to a tiled software buffer when using the Java compositor. Tiles are assumed to be packed tight and stored sequentially, by row.
widget/android/AndroidJavaWrappers.cpp
widget/android/AndroidJavaWrappers.h
widget/android/nsWindow.cpp
--- a/widget/android/AndroidJavaWrappers.cpp
+++ b/widget/android/AndroidJavaWrappers.cpp
@@ -403,16 +403,20 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jo
 
     if (!jobj)
         return;
 
     mAction = jenv->GetIntField(jobj, jActionField);
     mType = jenv->GetIntField(jobj, jTypeField);
 
     switch (mType) {
+        case TILE_SIZE:
+            ReadP0Field(jenv);
+            break;
+
         case SIZE_CHANGED:
             ReadP0Field(jenv);
             ReadP1Field(jenv);
             break;
 
         case KEY_EVENT:
             mTime = jenv->GetLongField(jobj, jTimeField);
             mMetaState = jenv->GetIntField(jobj, jMetaStateField);
--- a/widget/android/AndroidJavaWrappers.h
+++ b/widget/android/AndroidJavaWrappers.h
@@ -527,16 +527,17 @@ public:
         LOAD_URI = 12,
         SURFACE_CREATED = 13,
         SURFACE_DESTROYED = 14,
         GECKO_EVENT_SYNC = 15,
         FORCED_RESIZE = 16,
         ACTIVITY_START = 17,
         BROADCAST = 19,
         VIEWPORT = 20,
+        TILE_SIZE = 21,
         dummy_java_enum_list_end
     };
 
     enum {
         IME_COMPOSITION_END = 0,
         IME_COMPOSITION_BEGIN = 1,
         IME_SET_TEXT = 2,
         IME_GET_TEXT = 3,
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -82,16 +82,17 @@ using mozilla::unused;
 
 using namespace mozilla;
 using namespace mozilla::widget;
 
 NS_IMPL_ISUPPORTS_INHERITED0(nsWindow, nsBaseWidget)
 
 // The dimensions of the current android view
 static gfxIntSize gAndroidBounds = gfxIntSize(0, 0);
+static gfxIntSize gAndroidTileSize = gfxIntSize(0, 0);
 static gfxIntSize gAndroidScreenBounds;
 
 #ifdef ACCESSIBILITY
 bool nsWindow::sAccessibilityEnabled = false;
 #endif
 
 #ifdef MOZ_JAVA_COMPOSITOR
 #include "mozilla/Mutex.h"
@@ -976,16 +977,22 @@ nsWindow::OnGlobalAndroidEvent(AndroidGe
             if (win->mFocus)
                 win->mFocus->OnKeyEvent(ae);
             break;
 
         case AndroidGeckoEvent::DRAW:
             win->OnDraw(ae);
             break;
 
+        case AndroidGeckoEvent::TILE_SIZE: {
+            gAndroidTileSize.width = ae->P0().x;
+            gAndroidTileSize.height = ae->P0().y;
+            break;
+        }
+
         case AndroidGeckoEvent::IME_EVENT:
             win->UserActivity();
             if (win->mFocus) {
                 win->mFocus->OnIMEEvent(ae);
             } else {
                 NS_WARNING("Sending unexpected IME event to top window");
                 win->OnIMEEvent(ae);
             }
@@ -1197,46 +1204,65 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
       }
 
       sDirectTexture->Lock(AndroidGraphicBuffer::UsageSoftwareWrite, &bits);
     } else {
       bits = client.LockBufferBits();
     }
     if (!bits) {
         ALOG("### Failed to lock buffer");
+    } else {
+        // If tile size is 0,0, we assume we only have a single tile
+        int tileWidth = (gAndroidTileSize.width > 0) ? gAndroidTileSize.width : gAndroidBounds.width;
+        int tileHeight = (gAndroidTileSize.height > 0) ? gAndroidTileSize.height : gAndroidBounds.height;
 
-        if (sHasDirectTexture) {
-          sDirectTexture->Unlock();
-        } else {
-          client.UnlockBuffer();
-        }
-    } else {
-        nsRefPtr<gfxImageSurface> targetSurface =
-            new gfxImageSurface(bits, gfxIntSize(gAndroidBounds.width, gAndroidBounds.height), gAndroidBounds.width * 2,
-                                gfxASurface::ImageFormatRGB16_565);
-        if (targetSurface->CairoStatus()) {
-            ALOG("### Failed to create a valid surface from the bitmap");
-        } else {
-            if (sHasDirectTexture) {
-              // XXX: lock only the dirty rect above and pass it in here
-              DrawTo(targetSurface);
-            } else {
-              DrawTo(targetSurface, ae->Rect());
-            }
+        bool drawSuccess = true;
+        int offset = 0;
+
+        for (int y = 0; y < gAndroidBounds.height; y += tileHeight) {
+            for (int x = 0; x < gAndroidBounds.width; x += tileWidth) {
+                int width = NS_MIN(tileWidth, gAndroidBounds.width - x);
+                int height = NS_MIN(tileHeight, gAndroidBounds.height - y);
+
+                nsRefPtr<gfxImageSurface> targetSurface =
+                    new gfxImageSurface(bits + offset,
+                                        gfxIntSize(width, height),
+                                        width * 2,
+                                        gfxASurface::ImageFormatRGB16_565);
 
-            if (metadataProvider) {
-                metadataProvider->GetDrawMetadata(metadata);
+                offset += width * height * 2;
+
+                if (targetSurface->CairoStatus()) {
+                    ALOG("### Failed to create a valid surface from the bitmap");
+                    drawSuccess = false;
+                    break;
+                } else {
+                    if (sHasDirectTexture) {
+                        // XXX: lock only the dirty rect above and pass it in here
+                        DrawTo(targetSurface);
+                    } else {
+                        targetSurface->SetDeviceOffset(gfxPoint(-x, -y));
+                        DrawTo(targetSurface, ae->Rect());
+                    }
+                }
             }
         }
-        if (sHasDirectTexture) {
-          sDirectTexture->Unlock();
-        } else {
-          client.UnlockBuffer();
+
+        // Don't fill in the draw metadata on an unsuccessful draw
+        if (drawSuccess && metadataProvider) {
+            metadataProvider->GetDrawMetadata(metadata);
         }
     }
+
+    if (sHasDirectTexture) {
+        sDirectTexture->Unlock();
+    } else {
+        client.UnlockBuffer();
+    }
+
     client.EndDrawing(ae->Rect(), metadata);
     return;
 #endif
 
     if (!sSurfaceExists) {
         return;
     }