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.
--- 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;
}