This commit is contained in:
Doug Turner 2011-12-17 21:32:48 -08:00
Родитель 01edd43220
Коммит ed7e7d5a1e
10 изменённых файлов: 256 добавлений и 12 удалений

Просмотреть файл

@ -138,6 +138,8 @@ public class GeckoAppShell
public static native void notifySmsReceived(String aSender, String aBody, long aTimestamp); public static native void notifySmsReceived(String aSender, String aBody, long aTimestamp);
public static native ByteBuffer allocateDirectBuffer(long size); public static native ByteBuffer allocateDirectBuffer(long size);
public static native void freeDirectBuffer(ByteBuffer buf); public static native void freeDirectBuffer(ByteBuffer buf);
public static native void bindWidgetTexture();
public static native boolean testDirectTexture();
// A looper thread, accessed by GeckoAppShell.getHandler // A looper thread, accessed by GeckoAppShell.getHandler
private static class LooperThread extends Thread { private static class LooperThread extends Thread {
@ -425,6 +427,14 @@ public class GeckoAppShell
Log.i(LOGTAG, "post native init"); Log.i(LOGTAG, "post native init");
// If we have direct texture available, use it
if (GeckoAppShell.testDirectTexture()) {
Log.i(LOGTAG, "Using direct texture for widget layer");
GeckoApp.mAppContext.getSoftwareLayerClient().installWidgetLayer();
} else {
Log.i(LOGTAG, "Falling back to traditional texture upload");
}
// Tell Gecko where the target byte buffer is for rendering // Tell Gecko where the target byte buffer is for rendering
GeckoAppShell.setSoftwareLayerClient(GeckoApp.mAppContext.getSoftwareLayerClient()); GeckoAppShell.setSoftwareLayerClient(GeckoApp.mAppContext.getSoftwareLayerClient());

Просмотреть файл

@ -107,6 +107,7 @@ JAVAFILES = \
gfx/TextureReaper.java \ gfx/TextureReaper.java \
gfx/TileLayer.java \ gfx/TileLayer.java \
gfx/ViewportMetrics.java \ gfx/ViewportMetrics.java \
gfx/WidgetTileLayer.java \
ui/PanZoomController.java \ ui/PanZoomController.java \
$(NULL) $(NULL)

Просмотреть файл

@ -45,6 +45,7 @@ import org.mozilla.gecko.gfx.LayerController;
import org.mozilla.gecko.gfx.LayerRenderer; import org.mozilla.gecko.gfx.LayerRenderer;
import org.mozilla.gecko.gfx.PointUtils; import org.mozilla.gecko.gfx.PointUtils;
import org.mozilla.gecko.gfx.SingleTileLayer; import org.mozilla.gecko.gfx.SingleTileLayer;
import org.mozilla.gecko.gfx.WidgetTileLayer;
import org.mozilla.gecko.FloatUtils; import org.mozilla.gecko.FloatUtils;
import org.mozilla.gecko.GeckoApp; import org.mozilla.gecko.GeckoApp;
import org.mozilla.gecko.GeckoAppShell; import org.mozilla.gecko.GeckoAppShell;
@ -76,7 +77,7 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
private IntSize mScreenSize, mViewportSize; private IntSize mScreenSize, mViewportSize;
private IntSize mBufferSize; private IntSize mBufferSize;
private ByteBuffer mBuffer; private ByteBuffer mBuffer;
private final SingleTileLayer mTileLayer; private Layer mTileLayer;
/* The viewport rect that Gecko is currently displaying. */ /* The viewport rect that Gecko is currently displaying. */
private ViewportMetrics mGeckoViewport; private ViewportMetrics mGeckoViewport;
@ -125,6 +126,10 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
} }
} }
public void installWidgetLayer() {
mTileLayer = new WidgetTileLayer(mCairoImage);
}
/** Attaches the root layer to the layer controller so that Gecko appears. */ /** Attaches the root layer to the layer controller so that Gecko appears. */
@Override @Override
public void setLayerController(LayerController layerController) { public void setLayerController(LayerController layerController) {
@ -188,7 +193,9 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
updateViewport(metadata, !mUpdateViewportOnEndDraw); updateViewport(metadata, !mUpdateViewportOnEndDraw);
mUpdateViewportOnEndDraw = false; mUpdateViewportOnEndDraw = false;
Rect rect = new Rect(x, y, x + width, y + height); Rect rect = new Rect(x, y, x + width, y + height);
mTileLayer.invalidate(rect);
if (mTileLayer instanceof SingleTileLayer)
((SingleTileLayer)mTileLayer).invalidate(rect);
} finally { } finally {
endTransaction(mTileLayer); endTransaction(mTileLayer);
} }

Просмотреть файл

@ -53,24 +53,24 @@ public abstract class LayerClient {
} }
/** /**
* A utility function for calling TileLayer.beginTransaction with the * A utility function for calling Layer.beginTransaction with the
* appropriate LayerView. * appropriate LayerView.
*/ */
public void beginTransaction(TileLayer aTileLayer) { public void beginTransaction(Layer aLayer) {
if (mLayerController != null) { if (mLayerController != null) {
LayerView view = mLayerController.getView(); LayerView view = mLayerController.getView();
if (view != null) { if (view != null) {
aTileLayer.beginTransaction(view); aLayer.beginTransaction(view);
return; return;
} }
} }
aTileLayer.beginTransaction(); aLayer.beginTransaction();
} }
// Included for symmetry. // Included for symmetry.
public void endTransaction(TileLayer aTileLayer) { public void endTransaction(Layer aLayer) {
aTileLayer.endTransaction(); aLayer.endTransaction();
} }
} }

Просмотреть файл

@ -0,0 +1,116 @@
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla Android code.
*
* The Initial Developer of the Original Code is Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2009-2010
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* James Willcox <jwillcox@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* 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 ***** */
package org.mozilla.gecko.gfx;
import org.mozilla.gecko.gfx.LayerController;
import org.mozilla.gecko.gfx.SingleTileLayer;
import org.mozilla.gecko.GeckoAppShell;
import android.opengl.GLES11;
import android.opengl.GLES11Ext;
import android.graphics.RectF;
import android.util.Log;
import javax.microedition.khronos.opengles.GL10;
/**
* Encapsulates the logic needed to draw the single-tiled Gecko texture
*/
public class WidgetTileLayer extends Layer {
private int[] mTextureIDs;
private CairoImage mImage;
public WidgetTileLayer(CairoImage image) {
mImage = image;
}
protected boolean initialized() { return mTextureIDs != null; }
@Override
public IntSize getSize() { return mImage.getSize(); }
protected void bindAndSetGLParameters() {
GLES11.glBindTexture(GL10.GL_TEXTURE_2D, mTextureIDs[0]);
GLES11.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
GLES11.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
}
@Override
protected void finalize() throws Throwable {
if (mTextureIDs != null)
TextureReaper.get().add(mTextureIDs);
}
@Override
protected void performUpdates(GL10 gl) {
super.performUpdates(gl);
if (mTextureIDs == null) {
mTextureIDs = new int[1];
GLES11.glGenTextures(1, mTextureIDs, 0);
}
bindAndSetGLParameters();
GeckoAppShell.bindWidgetTexture();
}
@Override
public void draw(RenderContext context) {
// mTextureIDs may be null here during startup if Layer.java's draw method
// failed to acquire the transaction lock and call performUpdates.
if (!initialized())
return;
GLES11.glBindTexture(GL10.GL_TEXTURE_2D, mTextureIDs[0]);
RectF bounds;
int[] cropRect;
IntSize size = getSize();
RectF viewport = context.viewport;
bounds = getBounds(context, new FloatSize(size));
cropRect = new int[] { 0, size.height, size.width, -size.height };
bounds.offset(-viewport.left, -viewport.top);
GLES11.glTexParameteriv(GL10.GL_TEXTURE_2D, GLES11Ext.GL_TEXTURE_CROP_RECT_OES, cropRect,
0);
float top = viewport.height() - (bounds.top + bounds.height());
GLES11Ext.glDrawTexfOES(bounds.left, top, 0.0f, bounds.width(), bounds.height());
}
}

Просмотреть файл

@ -299,6 +299,8 @@ SHELL_WRAPPER1(cameraCallbackBridge, jbyteArray)
SHELL_WRAPPER1(notifyUriVisited, jstring) SHELL_WRAPPER1(notifyUriVisited, jstring)
SHELL_WRAPPER3(notifyBatteryChange, jdouble, jboolean, jdouble); SHELL_WRAPPER3(notifyBatteryChange, jdouble, jboolean, jdouble);
SHELL_WRAPPER3(notifySmsReceived, jstring, jstring, jlong); SHELL_WRAPPER3(notifySmsReceived, jstring, jstring, jlong);
SHELL_WRAPPER0(bindWidgetTexture);
SHELL_WRAPPER0_WITH_RETURN(testDirectTexture, bool);
static void * xul_handle = NULL; static void * xul_handle = NULL;
static time_t apk_mtime = 0; static time_t apk_mtime = 0;
@ -638,7 +640,7 @@ loadLibs(const char *apkName)
gettimeofday(&t0, 0); gettimeofday(&t0, 0);
struct rusage usage1; struct rusage usage1;
getrusage(RUSAGE_THREAD, &usage1); getrusage(RUSAGE_THREAD, &usage1);
void *zip = map_file(apkName); void *zip = map_file(apkName);
struct cdir_end *dirend = (struct cdir_end *)((char *)zip + zip_size - sizeof(*dirend)); struct cdir_end *dirend = (struct cdir_end *)((char *)zip + zip_size - sizeof(*dirend));
while ((void *)dirend > zip && while ((void *)dirend > zip &&
@ -704,6 +706,8 @@ loadLibs(const char *apkName)
GETFUNC(notifyUriVisited); GETFUNC(notifyUriVisited);
GETFUNC(notifyBatteryChange); GETFUNC(notifyBatteryChange);
GETFUNC(notifySmsReceived); GETFUNC(notifySmsReceived);
GETFUNC(bindWidgetTexture);
GETFUNC(testDirectTexture);
#undef GETFUNC #undef GETFUNC
sStartupTimeline = (uint64_t *)__wrap_dlsym(xul_handle, "_ZN7mozilla15StartupTimeline16sStartupTimelineE"); sStartupTimeline = (uint64_t *)__wrap_dlsym(xul_handle, "_ZN7mozilla15StartupTimeline16sStartupTimelineE");
gettimeofday(&t1, 0); gettimeofday(&t1, 0);

Просмотреть файл

@ -40,6 +40,7 @@
#include "nsString.h" #include "nsString.h"
#include "AndroidBridge.h" #include "AndroidBridge.h"
#include "AndroidGraphicBuffer.h"
#include <jni.h> #include <jni.h>
#include <pthread.h> #include <pthread.h>
@ -88,6 +89,8 @@ extern "C" {
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyUriVisited(JNIEnv *, jclass, jstring uri); NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyUriVisited(JNIEnv *, jclass, jstring uri);
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyBatteryChange(JNIEnv* jenv, jclass, jdouble, jboolean, jdouble); NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifyBatteryChange(JNIEnv* jenv, jclass, jdouble, jboolean, jdouble);
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifySmsReceived(JNIEnv* jenv, jclass, jstring, jstring, jlong); NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_notifySmsReceived(JNIEnv* jenv, jclass, jstring, jstring, jlong);
NS_EXPORT void JNICALL Java_org_mozilla_gecko_GeckoAppShell_bindWidgetTexture(JNIEnv* jenv, jclass);
NS_EXPORT bool JNICALL Java_org_mozilla_gecko_GeckoAppShell_testDirectTexture(JNIEnv* jenv, jclass);
} }
@ -278,3 +281,15 @@ Java_org_mozilla_gecko_GeckoAppShell_notifySmsReceived(JNIEnv* jenv, jclass,
nsCOMPtr<nsIRunnable> runnable = new NotifySmsReceivedRunnable(message); nsCOMPtr<nsIRunnable> runnable = new NotifySmsReceivedRunnable(message);
NS_DispatchToMainThread(runnable); NS_DispatchToMainThread(runnable);
} }
NS_EXPORT void JNICALL
Java_org_mozilla_gecko_GeckoAppShell_bindWidgetTexture(JNIEnv* jenv, jclass)
{
nsWindow::BindToTexture();
}
NS_EXPORT bool JNICALL
Java_org_mozilla_gecko_GeckoAppShell_testDirectTexture(JNIEnv* jenv, jclass)
{
return nsWindow::HasDirectTexture();
}

Просмотреть файл

@ -61,6 +61,8 @@ CPPSRCS = \
nsAppShell.cpp \ nsAppShell.cpp \
AndroidJavaWrappers.cpp \ AndroidJavaWrappers.cpp \
AndroidBridge.cpp \ AndroidBridge.cpp \
AndroidDirectTexture.cpp \
AndroidGraphicBuffer.cpp \
AndroidJNI.cpp \ AndroidJNI.cpp \
nsWindow.cpp \ nsWindow.cpp \
nsLookAndFeel.cpp \ nsLookAndFeel.cpp \

Просмотреть файл

@ -39,6 +39,7 @@
#include <android/log.h> #include <android/log.h>
#include <math.h> #include <math.h>
#include <unistd.h>
#include "mozilla/dom/ContentParent.h" #include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentChild.h"
@ -92,6 +93,20 @@ static gfxIntSize gAndroidScreenBounds;
bool nsWindow::sAccessibilityEnabled = false; bool nsWindow::sAccessibilityEnabled = false;
#endif #endif
#ifdef MOZ_JAVA_COMPOSITOR
#include "mozilla/Mutex.h"
#include "nsThreadUtils.h"
#include "AndroidDirectTexture.h"
static AndroidDirectTexture* sDirectTexture = new AndroidDirectTexture(2048, 2048,
AndroidGraphicBuffer::UsageSoftwareWrite | AndroidGraphicBuffer::UsageTexture,
gfxASurface::ImageFormatRGB16_565);
static bool sHasDirectTexture = true;
#endif
class ContentCreationNotifier; class ContentCreationNotifier;
static nsCOMPtr<ContentCreationNotifier> gContentCreationNotifier; static nsCOMPtr<ContentCreationNotifier> gContentCreationNotifier;
// A helper class to send updates when content processes // A helper class to send updates when content processes
@ -808,6 +823,49 @@ nsWindow::GetThebesSurface()
return new gfxImageSurface(gfxIntSize(5,5), gfxImageSurface::ImageFormatRGB24); return new gfxImageSurface(gfxIntSize(5,5), gfxImageSurface::ImageFormatRGB24);
} }
void
nsWindow::BindToTexture()
{
sDirectTexture->Bind();
}
bool
nsWindow::HasDirectTexture()
{
// If we already tested, return early
if (!sHasDirectTexture)
return false;
AndroidGraphicBuffer* buffer = new AndroidGraphicBuffer(512, 512,
AndroidGraphicBuffer::UsageSoftwareWrite | AndroidGraphicBuffer::UsageTexture,
gfxASurface::ImageFormatRGB16_565);
unsigned char* bits = NULL;
if (!buffer->Lock(AndroidGraphicBuffer::UsageSoftwareWrite, &bits) || !bits) {
ALOG("failed to lock graphic buffer");
buffer->Unlock();
sHasDirectTexture = false;
goto cleanup;
}
if (!buffer->Unlock()) {
ALOG("failed to unlock graphic buffer");
sHasDirectTexture = false;
goto cleanup;
}
if (!buffer->Reallocate(1024, 1024, gfxASurface::ImageFormatRGB16_565)) {
ALOG("failed to reallocate graphic buffer");
sHasDirectTexture = false;
goto cleanup;
}
cleanup:
delete buffer;
return sHasDirectTexture;
}
void void
nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae) nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
{ {
@ -1111,9 +1169,26 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
client.BeginDrawing(); client.BeginDrawing();
nsAutoString metadata; nsAutoString metadata;
unsigned char *bits = client.LockBufferBits(); unsigned char *bits = NULL;
if (sHasDirectTexture) {
if ((sDirectTexture->Width() != gAndroidBounds.width ||
sDirectTexture->Height() != gAndroidBounds.height) &&
gAndroidBounds.width != 0 && gAndroidBounds.height != 0) {
sDirectTexture->Reallocate(gAndroidBounds.width, gAndroidBounds.height);
}
sDirectTexture->Lock(AndroidGraphicBuffer::UsageSoftwareWrite, &bits);
} else {
bits = client.LockBufferBits();
}
if (!bits) { if (!bits) {
ALOG("### Failed to lock buffer"); ALOG("### Failed to lock buffer");
if (sHasDirectTexture) {
sDirectTexture->Unlock();
} else {
client.UnlockBuffer();
}
} else { } else {
nsRefPtr<gfxImageSurface> targetSurface = nsRefPtr<gfxImageSurface> targetSurface =
new gfxImageSurface(bits, gfxIntSize(gAndroidBounds.width, gAndroidBounds.height), gAndroidBounds.width * 2, new gfxImageSurface(bits, gfxIntSize(gAndroidBounds.width, gAndroidBounds.height), gAndroidBounds.width * 2,
@ -1121,7 +1196,12 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
if (targetSurface->CairoStatus()) { if (targetSurface->CairoStatus()) {
ALOG("### Failed to create a valid surface from the bitmap"); ALOG("### Failed to create a valid surface from the bitmap");
} else { } else {
DrawTo(targetSurface, ae->Rect()); if (sHasDirectTexture) {
// XXX: lock only the dirty rect above and pass it in here
DrawTo(targetSurface);
} else {
DrawTo(targetSurface, ae->Rect());
}
{ {
nsCOMPtr<nsIAndroidDrawMetadataProvider> metadataProvider = nsCOMPtr<nsIAndroidDrawMetadataProvider> metadataProvider =
@ -1130,7 +1210,11 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
metadataProvider->GetDrawMetadata(metadata); metadataProvider->GetDrawMetadata(metadata);
} }
} }
client.UnlockBuffer(); if (sHasDirectTexture) {
sDirectTexture->Unlock();
} else {
client.UnlockBuffer();
}
} }
client.EndDrawing(ae->Rect(), metadata); client.EndDrawing(ae->Rect(), metadata);
return; return;

Просмотреть файл

@ -177,6 +177,11 @@ public:
static bool sAccessibilityEnabled; static bool sAccessibilityEnabled;
#endif #endif
#ifdef MOZ_JAVA_COMPOSITOR
static void BindToTexture();
static bool HasDirectTexture();
#endif
protected: protected:
void BringToFront(); void BringToFront();
nsWindow *FindTopLevel(); nsWindow *FindTopLevel();