mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 724928 - Tell Gecko not to draw areas we aren't interested in. r=kats
Alter GeckoSoftwareLayerClient.beginDrawing so that it can return a rectangle of the buffer that it's interested in. Gecko then uses this to clip the dirty region, which often saves on unnecessary drawing during flings.
This commit is contained in:
parent
cdc622f177
commit
5e69f80ec8
@ -189,7 +189,8 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean beginDrawing(int width, int height, int tileWidth, int tileHeight, String metadata, boolean hasDirectTexture) {
|
||||
public Rect beginDrawing(int width, int height, int tileWidth, int tileHeight,
|
||||
String metadata, boolean hasDirectTexture) {
|
||||
setHasDirectTexture(hasDirectTexture);
|
||||
|
||||
// Make sure the tile-size matches. If it doesn't, we could crash trying
|
||||
@ -197,15 +198,17 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
||||
if (mHasDirectTexture) {
|
||||
if (tileWidth != 0 || tileHeight != 0) {
|
||||
Log.e(LOGTAG, "Aborting draw, incorrect tile size of " + tileWidth + "x" + tileHeight);
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
if (tileWidth != TILE_SIZE.width || tileHeight != TILE_SIZE.height) {
|
||||
Log.e(LOGTAG, "Aborting draw, incorrect tile size of " + tileWidth + "x" + tileHeight);
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
LayerController controller = getLayerController();
|
||||
|
||||
try {
|
||||
JSONObject viewportObject = new JSONObject(metadata);
|
||||
mNewGeckoViewport = new ViewportMetrics(viewportObject);
|
||||
@ -213,12 +216,49 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
||||
// Update the background color, if it's present.
|
||||
String backgroundColorString = viewportObject.optString("backgroundColor");
|
||||
if (backgroundColorString != null) {
|
||||
LayerController controller = getLayerController();
|
||||
controller.setCheckerboardColor(parseColorFromGecko(backgroundColorString));
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "Aborting draw, bad viewport description: " + metadata);
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Make sure we don't spend time painting areas we aren't interested in.
|
||||
// Only do this if the Gecko viewport isn't going to override our viewport.
|
||||
Rect bufferRect = new Rect(0, 0, width, height);
|
||||
|
||||
if (!mUpdateViewportOnEndDraw) {
|
||||
// First, find out our ideal displayport. We do this by taking the
|
||||
// clamped viewport origin and taking away the optimum viewport offset.
|
||||
// This would be what we would send to Gecko if adjustViewport were
|
||||
// called now.
|
||||
ViewportMetrics currentMetrics = controller.getViewportMetrics();
|
||||
PointF currentBestOrigin = RectUtils.getOrigin(currentMetrics.getClampedViewport());
|
||||
PointF viewportOffset = currentMetrics.getOptimumViewportOffset(new IntSize(width, height));
|
||||
currentBestOrigin.offset(-viewportOffset.x, -viewportOffset.y);
|
||||
|
||||
Rect currentRect = RectUtils.round(new RectF(currentBestOrigin.x, currentBestOrigin.y,
|
||||
currentBestOrigin.x + width, currentBestOrigin.y + height));
|
||||
|
||||
// Second, store Gecko's displayport.
|
||||
PointF currentOrigin = mNewGeckoViewport.getDisplayportOrigin();
|
||||
bufferRect = RectUtils.round(new RectF(currentOrigin.x, currentOrigin.y,
|
||||
currentOrigin.x + width, currentOrigin.y + height));
|
||||
|
||||
|
||||
// Take the intersection of the two as the area we're interested in rendering.
|
||||
if (!bufferRect.intersect(currentRect)) {
|
||||
// If there's no intersection, we have no need to render anything,
|
||||
// but make sure to update the viewport size.
|
||||
beginTransaction(mTileLayer);
|
||||
try {
|
||||
updateViewport(true);
|
||||
} finally {
|
||||
endTransaction(mTileLayer);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
bufferRect.offset(Math.round(-currentOrigin.x), Math.round(-currentOrigin.y));
|
||||
}
|
||||
|
||||
beginTransaction(mTileLayer);
|
||||
@ -227,26 +267,23 @@ public class GeckoSoftwareLayerClient extends LayerClient implements GeckoEventL
|
||||
if (mBufferSize.width != width || mBufferSize.height != height) {
|
||||
mBufferSize = new IntSize(width, height);
|
||||
|
||||
// We only need to allocate buffer memory if we're using MultiTileLayer.
|
||||
if (!(mTileLayer instanceof MultiTileLayer)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Reallocate the buffer if necessary
|
||||
int bpp = CairoUtils.bitsPerPixelForCairoFormat(mFormat) / 8;
|
||||
int size = mBufferSize.getArea() * bpp;
|
||||
if (mBuffer == null || mBuffer.capacity() != size) {
|
||||
// Free the old buffer
|
||||
if (mBuffer != null) {
|
||||
GeckoAppShell.freeDirectBuffer(mBuffer);
|
||||
mBuffer = null;
|
||||
}
|
||||
if (mTileLayer instanceof MultiTileLayer) {
|
||||
int bpp = CairoUtils.bitsPerPixelForCairoFormat(mFormat) / 8;
|
||||
int size = mBufferSize.getArea() * bpp;
|
||||
if (mBuffer == null || mBuffer.capacity() != size) {
|
||||
// Free the old buffer
|
||||
if (mBuffer != null) {
|
||||
GeckoAppShell.freeDirectBuffer(mBuffer);
|
||||
mBuffer = null;
|
||||
}
|
||||
|
||||
mBuffer = GeckoAppShell.allocateDirectBuffer(size);
|
||||
mBuffer = GeckoAppShell.allocateDirectBuffer(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return bufferRect;
|
||||
}
|
||||
|
||||
private void updateViewport(final boolean onlyUpdatePageSize) {
|
||||
|
@ -38,6 +38,8 @@
|
||||
package org.mozilla.gecko.gfx;
|
||||
|
||||
import org.mozilla.gecko.FloatUtils;
|
||||
import android.graphics.Point;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.RectF;
|
||||
import org.json.JSONException;
|
||||
@ -109,6 +111,14 @@ public final class RectUtils {
|
||||
return new IntSize(rect.width(), rect.height());
|
||||
}
|
||||
|
||||
public static Point getOrigin(Rect rect) {
|
||||
return new Point(rect.left, rect.top);
|
||||
}
|
||||
|
||||
public static PointF getOrigin(RectF rect) {
|
||||
return new PointF(rect.left, rect.top);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the rect that represents a linear transition between `from` and `to` at time `t`,
|
||||
* which is on the scale [0, 1).
|
||||
|
@ -331,7 +331,7 @@ AndroidGeckoSoftwareLayerClient::InitGeckoSoftwareLayerClientClass(JNIEnv *jEnv)
|
||||
|
||||
jLockBufferMethod = getMethod("lockBuffer", "()Ljava/nio/ByteBuffer;");
|
||||
jUnlockBufferMethod = getMethod("unlockBuffer", "()V");
|
||||
jBeginDrawingMethod = getMethod("beginDrawing", "(IIIILjava/lang/String;Z)Z");
|
||||
jBeginDrawingMethod = getMethod("beginDrawing", "(IIIILjava/lang/String;Z)Landroid/graphics/Rect;");
|
||||
jEndDrawingMethod = getMethod("endDrawing", "(IIII)V");
|
||||
#endif
|
||||
}
|
||||
@ -392,8 +392,8 @@ AndroidGeckoEvent::ReadRectField(JNIEnv *jenv)
|
||||
if (!r.isNull()) {
|
||||
mRect.SetRect(r.Left(),
|
||||
r.Top(),
|
||||
r.Right() - r.Left(),
|
||||
r.Bottom() - r.Top());
|
||||
r.Width(),
|
||||
r.Height());
|
||||
} else {
|
||||
mRect.SetEmpty();
|
||||
}
|
||||
@ -690,7 +690,7 @@ AndroidGeckoSoftwareLayerClient::UnlockBuffer()
|
||||
}
|
||||
|
||||
bool
|
||||
AndroidGeckoSoftwareLayerClient::BeginDrawing(int aWidth, int aHeight, int aTileWidth, int aTileHeight, const nsAString &aMetadata, bool aHasDirectTexture)
|
||||
AndroidGeckoSoftwareLayerClient::BeginDrawing(int aWidth, int aHeight, int aTileWidth, int aTileHeight, nsIntRect &aDirtyRect, const nsAString &aMetadata, bool aHasDirectTexture)
|
||||
{
|
||||
NS_ASSERTION(!isNull(), "BeginDrawing() called on null software layer client!");
|
||||
JNIEnv *env = AndroidBridge::GetJNIEnv();
|
||||
@ -699,7 +699,20 @@ AndroidGeckoSoftwareLayerClient::BeginDrawing(int aWidth, int aHeight, int aTile
|
||||
|
||||
AndroidBridge::AutoLocalJNIFrame(env, 1);
|
||||
jstring jMetadata = env->NewString(nsPromiseFlatString(aMetadata).get(), aMetadata.Length());
|
||||
return env->CallBooleanMethod(wrapped_obj, jBeginDrawingMethod, aWidth, aHeight, aTileWidth, aTileHeight, jMetadata, aHasDirectTexture);
|
||||
|
||||
jobject rectObject = env->CallObjectMethod(wrapped_obj, jBeginDrawingMethod,
|
||||
aWidth, aHeight, aTileWidth, aTileHeight,
|
||||
jMetadata, aHasDirectTexture);
|
||||
|
||||
if (rectObject == nsnull)
|
||||
return false;
|
||||
|
||||
AndroidRect rect(env, rectObject);
|
||||
nsIntRect newDirtyRect = aDirtyRect.Intersect(nsIntRect(rect.Top(), rect.Left(),
|
||||
rect.Width(), rect.Height()));
|
||||
aDirtyRect.SetRect(newDirtyRect.x, newDirtyRect.y, newDirtyRect.width, newDirtyRect.height);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -135,6 +135,8 @@ public:
|
||||
int Left() { return mLeft; }
|
||||
int Right() { return mRight; }
|
||||
int Top() { return mTop; }
|
||||
int Width() { return mRight - mLeft; }
|
||||
int Height() { return mBottom - mTop; }
|
||||
|
||||
protected:
|
||||
int mBottom;
|
||||
@ -161,7 +163,7 @@ public:
|
||||
jobject LockBuffer();
|
||||
unsigned char *LockBufferBits();
|
||||
void UnlockBuffer();
|
||||
bool BeginDrawing(int aWidth, int aHeight, int aTileWidth, int aTileHeight, const nsAString &aMetadata, bool aHasDirectTexture);
|
||||
bool BeginDrawing(int aWidth, int aHeight, int aTileWidth, int aTileHeight, nsIntRect &aDirtyRect, const nsAString &aMetadata, bool aHasDirectTexture);
|
||||
void EndDrawing(const nsIntRect &aRect);
|
||||
|
||||
private:
|
||||
|
@ -1208,16 +1208,16 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
|
||||
metadataProvider->GetDrawMetadata(metadata);
|
||||
}
|
||||
|
||||
nsIntRect dirtyRect = ae->Rect().Intersect(nsIntRect(0, 0, gAndroidBounds.width, gAndroidBounds.height));
|
||||
|
||||
AndroidGeckoSoftwareLayerClient &client =
|
||||
AndroidBridge::Bridge()->GetSoftwareLayerClient();
|
||||
if (!client.BeginDrawing(gAndroidBounds.width, gAndroidBounds.height,
|
||||
gAndroidTileSize.width, gAndroidTileSize.height,
|
||||
metadata, HasDirectTexture())) {
|
||||
dirtyRect, metadata, HasDirectTexture())) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIntRect dirtyRect = ae->Rect().Intersect(nsIntRect(0, 0, gAndroidBounds.width, gAndroidBounds.height));
|
||||
|
||||
unsigned char *bits = NULL;
|
||||
if (HasDirectTexture()) {
|
||||
if (sDirectTexture->Width() != gAndroidBounds.width ||
|
||||
|
Loading…
Reference in New Issue
Block a user