mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 575421 - Improve 2D drawing path on Android, r=vlad
This commit is contained in:
parent
00e8f7da8b
commit
63f56cde6f
@ -60,8 +60,6 @@ abstract public class GeckoApp
|
||||
public static GeckoSurfaceView surfaceView;
|
||||
public static GeckoApp mAppContext;
|
||||
|
||||
public static boolean useSoftwareDrawing;
|
||||
|
||||
void launch()
|
||||
{
|
||||
// unpack files in the components directory
|
||||
@ -121,8 +119,6 @@ abstract public class GeckoApp
|
||||
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
|
||||
ViewGroup.LayoutParams.FILL_PARENT));
|
||||
|
||||
useSoftwareDrawing = true; //isInEmulator() == 1;
|
||||
|
||||
if (!GeckoAppShell.sGeckoRunning) {
|
||||
// Load our JNI libs; we need to do this before launch() because
|
||||
// setInitialSize will be called even before Gecko is actually up
|
||||
|
@ -100,6 +100,13 @@ class GeckoSurfaceView
|
||||
Log.w("GeckoAppJava", "surfaceChanged while mInDrawing is true!");
|
||||
}
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
mSoftwareBuffer = null;
|
||||
else if (mSoftwareBuffer == null ||
|
||||
mSoftwareBuffer.capacity() < (width * height * 2) ||
|
||||
mWidth != width || mHeight != height)
|
||||
mSoftwareBuffer = ByteBuffer.allocateDirect(width * height * 2);
|
||||
|
||||
mFormat = format;
|
||||
mWidth = width;
|
||||
mHeight = height;
|
||||
@ -122,8 +129,6 @@ class GeckoSurfaceView
|
||||
}
|
||||
|
||||
mSurfaceChanged = true;
|
||||
|
||||
//Log.i("GeckoAppJava", "<< surfaceChanged");
|
||||
} finally {
|
||||
mSurfaceLock.unlock();
|
||||
}
|
||||
@ -137,14 +142,10 @@ class GeckoSurfaceView
|
||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||
Log.i("GeckoAppJava", "surface destroyed");
|
||||
mSurfaceValid = false;
|
||||
mSoftwareBuffer = null;
|
||||
}
|
||||
|
||||
public ByteBuffer getSoftwareDrawBuffer() {
|
||||
//#ifdef DEBUG
|
||||
if (!mSurfaceLock.isHeldByCurrentThread())
|
||||
Log.e("GeckoAppJava", "getSoftwareDrawBuffer called outside of mSurfaceLock!");
|
||||
//#endif
|
||||
|
||||
return mSoftwareBuffer;
|
||||
}
|
||||
|
||||
@ -154,42 +155,8 @@ class GeckoSurfaceView
|
||||
|
||||
public static final int DRAW_ERROR = 0;
|
||||
public static final int DRAW_GLES_2 = 1;
|
||||
public static final int DRAW_SOFTWARE = 2;
|
||||
|
||||
int innerBeginDrawing() {
|
||||
/*
|
||||
* Software (non-GL) rendering
|
||||
*/
|
||||
if (GeckoApp.useSoftwareDrawing) {
|
||||
if (mWidth != mBufferWidth ||
|
||||
mHeight != mBufferHeight ||
|
||||
mSurfaceChanged)
|
||||
{
|
||||
if (mWidth*mHeight != mBufferWidth*mBufferHeight)
|
||||
mSoftwareBuffer = ByteBuffer.allocateDirect(mWidth*mHeight*4);
|
||||
|
||||
mSoftwareBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
|
||||
|
||||
mBufferWidth = mWidth;
|
||||
mBufferHeight = mHeight;
|
||||
mSurfaceChanged = false;
|
||||
}
|
||||
|
||||
mSoftwareCanvas = getHolder().lockCanvas(null);
|
||||
if (mSoftwareCanvas == null) {
|
||||
Log.e("GeckoAppJava", "lockCanvas failed! << beginDrawing");
|
||||
return DRAW_ERROR;
|
||||
}
|
||||
|
||||
return DRAW_SOFTWARE;
|
||||
}
|
||||
|
||||
return DRAW_GLES_2;
|
||||
}
|
||||
|
||||
public int beginDrawing() {
|
||||
//Log.i("GeckoAppJava", ">> beginDrawing");
|
||||
|
||||
if (mInDrawing) {
|
||||
Log.e("GeckoAppJava", "Recursive beginDrawing call!");
|
||||
return DRAW_ERROR;
|
||||
@ -214,21 +181,11 @@ class GeckoSurfaceView
|
||||
return DRAW_ERROR;
|
||||
}
|
||||
|
||||
// call the inner function to do the work, so we can sanely unlock on error
|
||||
int result = innerBeginDrawing();
|
||||
|
||||
if (result == DRAW_ERROR) {
|
||||
mSurfaceLock.unlock();
|
||||
return DRAW_ERROR;
|
||||
}
|
||||
|
||||
mInDrawing = true;
|
||||
return result;
|
||||
return DRAW_GLES_2;
|
||||
}
|
||||
|
||||
public void endDrawing() {
|
||||
//Log.w("GeckoAppJava", ">> endDrawing");
|
||||
|
||||
if (!mInDrawing) {
|
||||
Log.e("GeckoAppJava", "endDrawing without beginDrawing!");
|
||||
return;
|
||||
@ -239,30 +196,36 @@ class GeckoSurfaceView
|
||||
Log.e("GeckoAppJava", "endDrawing with false mSurfaceValid");
|
||||
return;
|
||||
}
|
||||
|
||||
if (GeckoApp.useSoftwareDrawing) {
|
||||
if (!mSurfaceChanged) {
|
||||
mSoftwareBitmap.copyPixelsFromBuffer(mSoftwareBuffer);
|
||||
mSoftwareCanvas.drawBitmap(mSoftwareBitmap, 0, 0, null);
|
||||
|
||||
getHolder().unlockCanvasAndPost(mSoftwareCanvas);
|
||||
mSoftwareCanvas = null;
|
||||
}
|
||||
}
|
||||
} catch (java.lang.IllegalArgumentException ex) {
|
||||
mSurfaceChanged = true;
|
||||
} finally {
|
||||
mInDrawing = false;
|
||||
|
||||
//#ifdef DEBUG
|
||||
if (!mSurfaceLock.isHeldByCurrentThread())
|
||||
Log.e("GeckoAppJava", "endDrawing while mSurfaceLock not held by current thread!");
|
||||
//#endif
|
||||
|
||||
mSurfaceLock.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void draw2D(ByteBuffer buffer) {
|
||||
Canvas c = getHolder().lockCanvas();
|
||||
if (c == null)
|
||||
return;
|
||||
if (buffer != mSoftwareBuffer) {
|
||||
getHolder().unlockCanvasAndPost(c);
|
||||
return;
|
||||
}
|
||||
if (mSoftwareBitmap == null ||
|
||||
mSoftwareBitmap.getHeight() != mHeight ||
|
||||
mSoftwareBitmap.getWidth() != mWidth) {
|
||||
mSoftwareBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.RGB_565);
|
||||
}
|
||||
mSoftwareBitmap.copyPixelsFromBuffer(mSoftwareBuffer);
|
||||
c.drawBitmap(mSoftwareBitmap, 0, 0, null);
|
||||
getHolder().unlockCanvasAndPost(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCheckIsTextEditor () {
|
||||
return false;
|
||||
@ -347,7 +310,6 @@ class GeckoSurfaceView
|
||||
// Software rendering
|
||||
ByteBuffer mSoftwareBuffer;
|
||||
Bitmap mSoftwareBitmap;
|
||||
Canvas mSoftwareCanvas;
|
||||
}
|
||||
|
||||
class GeckoInputConnection
|
||||
|
@ -87,8 +87,11 @@ already_AddRefed<gfxASurface>
|
||||
gfxAndroidPlatform::CreateOffscreenSurface(const gfxIntSize& size,
|
||||
gfxASurface::gfxImageFormat imageFormat)
|
||||
{
|
||||
nsRefPtr<gfxASurface> newSurface =
|
||||
new gfxImageSurface (size, imageFormat);
|
||||
nsRefPtr<gfxASurface> newSurface;
|
||||
if (imageFormat == gfxImageSurface::ImageFormatRGB24)
|
||||
newSurface = new gfxImageSurface (size, gfxASurface::ImageFormatRGB16_565);
|
||||
else
|
||||
newSurface = new gfxImageSurface (size, imageFormat);
|
||||
|
||||
return newSurface.forget();
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ jmethodID AndroidLocation::jGetTimeMethod = 0;
|
||||
jclass AndroidGeckoSurfaceView::jGeckoSurfaceViewClass = 0;
|
||||
jmethodID AndroidGeckoSurfaceView::jBeginDrawingMethod = 0;
|
||||
jmethodID AndroidGeckoSurfaceView::jEndDrawingMethod = 0;
|
||||
jmethodID AndroidGeckoSurfaceView::jDraw2DMethod = 0;
|
||||
jmethodID AndroidGeckoSurfaceView::jGetSoftwareDrawBufferMethod = 0;
|
||||
jmethodID AndroidGeckoSurfaceView::jGetHolderMethod = 0;
|
||||
|
||||
@ -147,6 +148,7 @@ AndroidGeckoSurfaceView::InitGeckoSurfaceViewClass(JNIEnv *jEnv)
|
||||
jBeginDrawingMethod = getMethod("beginDrawing", "()I");
|
||||
jGetSoftwareDrawBufferMethod = getMethod("getSoftwareDrawBuffer", "()Ljava/nio/ByteBuffer;");
|
||||
jEndDrawingMethod = getMethod("endDrawing", "()V");
|
||||
jDraw2DMethod = getMethod("draw2D", "(Ljava/nio/ByteBuffer;)V");
|
||||
jGetHolderMethod = getMethod("getHolder", "()Landroid/view/SurfaceHolder;");
|
||||
}
|
||||
|
||||
@ -361,23 +363,16 @@ AndroidGeckoSurfaceView::EndDrawing()
|
||||
JNI()->CallVoidMethod(wrapped_obj, jEndDrawingMethod);
|
||||
}
|
||||
|
||||
unsigned char *
|
||||
AndroidGeckoSurfaceView::GetSoftwareDrawBuffer(int *cap)
|
||||
void
|
||||
AndroidGeckoSurfaceView::Draw2D(jobject buffer)
|
||||
{
|
||||
jobject buf = JNI()->CallObjectMethod(wrapped_obj, jGetSoftwareDrawBufferMethod);
|
||||
if (!buf)
|
||||
return nsnull;
|
||||
JNI()->CallVoidMethod(wrapped_obj, jDraw2DMethod, buffer);
|
||||
}
|
||||
|
||||
void *bp = JNI()->GetDirectBufferAddress(buf);
|
||||
jlong blen = JNI()->GetDirectBufferCapacity(buf);
|
||||
|
||||
if (!bp || blen == -1)
|
||||
return nsnull;
|
||||
|
||||
if (cap)
|
||||
*cap = blen;
|
||||
|
||||
return (unsigned char*) bp;
|
||||
jobject
|
||||
AndroidGeckoSurfaceView::GetSoftwareDrawBuffer()
|
||||
{
|
||||
return JNI()->CallObjectMethod(wrapped_obj, jGetSoftwareDrawBufferMethod);
|
||||
}
|
||||
|
||||
jobject
|
||||
|
@ -163,13 +163,13 @@ public:
|
||||
|
||||
enum {
|
||||
DRAW_ERROR = 0,
|
||||
DRAW_GLES_2 = 1,
|
||||
DRAW_SOFTWARE = 2
|
||||
DRAW_GLES_2 = 1
|
||||
};
|
||||
|
||||
int BeginDrawing();
|
||||
unsigned char *GetSoftwareDrawBuffer(int *cap);
|
||||
jobject GetSoftwareDrawBuffer();
|
||||
void EndDrawing();
|
||||
void Draw2D(jobject buffer);
|
||||
|
||||
// must have a JNI local frame when calling this,
|
||||
// and you'd better know what you're doing
|
||||
@ -179,6 +179,7 @@ protected:
|
||||
static jclass jGeckoSurfaceViewClass;
|
||||
static jmethodID jBeginDrawingMethod;
|
||||
static jmethodID jEndDrawingMethod;
|
||||
static jmethodID jDraw2DMethod;
|
||||
static jmethodID jGetSoftwareDrawBufferMethod;
|
||||
static jmethodID jGetHolderMethod;
|
||||
};
|
||||
|
@ -580,8 +580,7 @@ nsWindow::OnGlobalAndroidEvent(AndroidGeckoEvent *ae)
|
||||
int nh = ae->P0().y;
|
||||
|
||||
if (nw == gAndroidBounds.width &&
|
||||
nh == gAndroidBounds.height)
|
||||
{
|
||||
nh == gAndroidBounds.height) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -683,12 +682,12 @@ nsWindow::DrawTo(gfxASurface *targetSurface)
|
||||
if (coveringChildIndex == -1) {
|
||||
ALOG("nsWindow[%p]::DrawTo no covering child, drawing this", (void*) this);
|
||||
|
||||
nsPaintEvent event(PR_TRUE, NS_PAINT, this);
|
||||
event.region = boundsRect;
|
||||
switch (GetLayerManager()->GetBackendType()) {
|
||||
case LayerManager::LAYERS_BASIC: {
|
||||
nsRefPtr<gfxContext> ctx = new gfxContext(targetSurface);
|
||||
|
||||
nsPaintEvent event(PR_TRUE, NS_PAINT, this);
|
||||
event.region = boundsRect;
|
||||
{
|
||||
AutoLayerManagerSetup setupLayerManager(this, ctx);
|
||||
status = DispatchEvent(&event);
|
||||
@ -703,19 +702,16 @@ nsWindow::DrawTo(gfxASurface *targetSurface)
|
||||
|
||||
// XXX if we got an ignore for the parent, do we still want to draw the children?
|
||||
// We don't really have a good way not to...
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case LayerManager::LAYERS_OPENGL: {
|
||||
static_cast<mozilla::layers::LayerManagerOGL*>(GetLayerManager())->
|
||||
SetClippingRegion(nsIntRegion(boundsRect));
|
||||
|
||||
nsPaintEvent event(PR_TRUE, NS_PAINT, this);
|
||||
event.region = boundsRect;
|
||||
status = DispatchEvent(&event);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
NS_ERROR("Invalid layer manager");
|
||||
@ -733,8 +729,7 @@ nsWindow::DrawTo(gfxASurface *targetSurface)
|
||||
|
||||
for (PRUint32 i = coveringChildIndex; i < mChildren.Length(); ++i) {
|
||||
if (mChildren[i]->mBounds.IsEmpty() ||
|
||||
!mChildren[i]->mBounds.Intersects(boundsRect))
|
||||
{
|
||||
!mChildren[i]->mBounds.Intersects(boundsRect)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -755,20 +750,6 @@ nsWindow::DrawTo(gfxASurface *targetSurface)
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
static int
|
||||
next_power_of_two(int v)
|
||||
{
|
||||
v--;
|
||||
v |= v >> 1;
|
||||
v |= v >> 2;
|
||||
v |= v >> 4;
|
||||
v |= v >> 8;
|
||||
v |= v >> 16;
|
||||
v++;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
void
|
||||
nsWindow::OnDraw(AndroidGeckoEvent *ae)
|
||||
{
|
||||
@ -794,43 +775,36 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
|
||||
return;
|
||||
}
|
||||
|
||||
int drawType = sview.BeginDrawing();
|
||||
|
||||
if (drawType == AndroidGeckoSurfaceView::DRAW_ERROR) {
|
||||
ALOG("##### BeginDrawing failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (GetLayerManager()->GetBackendType() == LayerManager::LAYERS_BASIC) {
|
||||
drawType = AndroidGeckoSurfaceView::DRAW_SOFTWARE;
|
||||
} else {
|
||||
drawType = AndroidGeckoSurfaceView::DRAW_GLES_2;
|
||||
}
|
||||
jobject bytebuf = sview.GetSoftwareDrawBuffer();
|
||||
if (!bytebuf) {
|
||||
ALOG("no buffer to draw into - skipping draw");
|
||||
return;
|
||||
}
|
||||
|
||||
if (drawType == AndroidGeckoSurfaceView::DRAW_SOFTWARE) {
|
||||
int bufCap;
|
||||
unsigned char *buf = sview.GetSoftwareDrawBuffer(&bufCap);
|
||||
if (!buf || bufCap != mBounds.width * mBounds.height * 4) {
|
||||
ALOG("### Software drawing, but too small a buffer %d expected %d (or no buffer %p)!", bufCap, mBounds.width * mBounds.height * 4, (void*)buf);
|
||||
sview.EndDrawing();
|
||||
void *buf = AndroidBridge::JNI()->GetDirectBufferAddress(bytebuf);
|
||||
int cap = AndroidBridge::JNI()->GetDirectBufferCapacity(bytebuf);
|
||||
if (!buf || cap < (mBounds.width * mBounds.height * 2)) {
|
||||
ALOG("### Software drawing, but too small a buffer %d expected %d (or no buffer %p)!", cap, mBounds.width * mBounds.height * 2, buf);
|
||||
return;
|
||||
}
|
||||
|
||||
nsRefPtr<gfxImageSurface> targetSurface =
|
||||
new gfxImageSurface(buf,
|
||||
new gfxImageSurface((unsigned char *)buf,
|
||||
gfxIntSize(mBounds.width, mBounds.height),
|
||||
mBounds.width * 4,
|
||||
gfxASurface::ImageFormatARGB32);
|
||||
mBounds.width * 2,
|
||||
gfxASurface::ImageFormatRGB16_565);
|
||||
|
||||
DrawTo(targetSurface);
|
||||
sview.Draw2D(bytebuf);
|
||||
} else {
|
||||
int drawType = sview.BeginDrawing();
|
||||
|
||||
// need to swap B and R channels, to get ABGR instead of ARGB
|
||||
unsigned int *ibuf = (unsigned int*) buf;
|
||||
unsigned int *ibufMax = ibuf + mBounds.width * mBounds.height;
|
||||
while (ibuf < ibufMax) {
|
||||
*ibuf++ = (*ibuf & 0xff00ff00) | ((*ibuf & 0x00ff0000) >> 16) | ((*ibuf & 0x000000ff) << 16);
|
||||
if (drawType == AndroidGeckoSurfaceView::DRAW_ERROR) {
|
||||
ALOG("##### BeginDrawing failed!");
|
||||
return;
|
||||
}
|
||||
} else if (drawType == AndroidGeckoSurfaceView::DRAW_GLES_2) {
|
||||
|
||||
NS_ASSERTION(sGLContext, "Drawing with GLES without a GL context?");
|
||||
|
||||
sGLContext->fClear(LOCAL_GL_COLOR_BUFFER_BIT | LOCAL_GL_DEPTH_BUFFER_BIT);
|
||||
@ -839,9 +813,8 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
|
||||
|
||||
if (sGLContext)
|
||||
sGLContext->SwapBuffers();
|
||||
sview.EndDrawing();
|
||||
}
|
||||
|
||||
sview.EndDrawing();
|
||||
}
|
||||
|
||||
void
|
||||
|
Loading…
Reference in New Issue
Block a user