backing out bug 755070 for potential talos panning regression

This commit is contained in:
Brad Lassey
2012-06-05 22:55:18 -04:00
parent d25e21af92
commit a7fbcda140
17 changed files with 120 additions and 336 deletions

View File

@@ -573,10 +573,8 @@ public class GeckoAppShell
// these 2 stubs are never called in XUL Fennec, but we need them so that
// the JNI code shared between XUL and Native Fennec doesn't die.
public static void notifyScreenShot(final ByteBuffer data, final int tabId,
final int left, final int top,
final int right, final int bottom,
final int bufferWidth, final int bufferHeight, final int token) {
public static void notifyScreenShot(final ByteBuffer data, final int tabId, final int x, final int y,
final int width, final int height, final int token) {
}
public static void notifyPaintedRect(float top, float left, float bottom, float right) {

View File

@@ -15,7 +15,6 @@ import android.hardware.*;
import android.location.*;
import android.util.FloatMath;
import android.util.DisplayMetrics;
import java.nio.ByteBuffer;
import android.util.Log;
@@ -101,8 +100,6 @@ public class GeckoEvent {
public int mNativeWindow;
public ByteBuffer mBuffer;
public GeckoEvent() {
mType = NATIVE_POKE;
}

View File

@@ -256,14 +256,6 @@ void MessageLoop::PostNonNestableDelayedTask(
PostTask_Helper(from_here, task, delay_ms, false);
}
void MessageLoop::PostIdleTask(
const tracked_objects::Location& from_here, Task* task) {
DCHECK(current() == this);
task->SetBirthPlace(from_here);
PendingTask pending_task(task, false);
deferred_non_nestable_work_queue_.push(pending_task);
}
// Possibly called on a background thread!
void MessageLoop::PostTask_Helper(
const tracked_objects::Location& from_here, Task* task, int delay_ms,

View File

@@ -121,10 +121,6 @@ public:
void PostNonNestableDelayedTask(
const tracked_objects::Location& from_here, Task* task, int delay_ms);
// PostIdleTask is not thread safe and should be called on this thread
void PostIdleTask(
const tracked_objects::Location& from_here, Task* task);
// A variant on PostTask that deletes the given object. This is useful
// if the object needs to live until the next run of the MessageLoop (for
// example, deleting a RenderProcessHost from within an IPC callback is not

View File

@@ -738,7 +738,7 @@ abstract public class GeckoApp
int dw = tab.getThumbnailWidth();
int dh = tab.getThumbnailHeight();
GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, dw, dh, GeckoAppShell.SCREENSHOT_THUMBNAIL, tab.getThumbnailBuffer()));
GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(), 0, 0, 0, 0, 0, 0, dw, dh, GeckoAppShell.SCREENSHOT_THUMBNAIL));
}
}

View File

@@ -15,7 +15,6 @@ import org.mozilla.gecko.gfx.ScreenshotLayer;
import org.mozilla.gecko.FloatUtils;
import org.mozilla.gecko.gfx.ImmutableViewportMetrics;
import org.mozilla.gecko.gfx.ViewportMetrics;
import org.mozilla.gecko.gfx.RectUtils;
import java.io.*;
import java.lang.reflect.*;
@@ -84,7 +83,8 @@ public class GeckoAppShell
public static final String SHORTCUT_TYPE_BOOKMARK = "bookmark";
static public final int SCREENSHOT_THUMBNAIL = 0;
static public final int SCREENSHOT_CHECKERBOARD = 1;
static public final int SCREENSHOT_WHOLE_PAGE = 1;
static public final int SCREENSHOT_UPDATE = 2;
static public final int RESTORE_NONE = 0;
static public final int RESTORE_OOM = 1;
@@ -98,6 +98,11 @@ public class GeckoAppShell
private static Boolean sNSSLibsLoaded = false;
private static Boolean sLibsSetup = false;
private static File sGREDir = null;
private static RectF sCheckerboardPageRect;
private static float sLastCheckerboardWidthRatio, sLastCheckerboardHeightRatio;
private static RepaintRunnable sRepaintRunnable = new RepaintRunnable();
static private int sMaxTextureSize = 0;
private static Map<String, CopyOnWriteArrayList<GeckoEventListener>> mEventListeners
= new HashMap<String, CopyOnWriteArrayList<GeckoEventListener>>();
@@ -123,6 +128,8 @@ public class GeckoAppShell
private static Handler sGeckoHandler;
private static boolean sDisableScreenshot = false;
/* The Android-side API: API methods that Android calls */
// Initialization methods
@@ -526,11 +533,44 @@ public class GeckoAppShell
}
// Called by AndroidBridge using JNI
public static void notifyScreenShot(final ByteBuffer data, final int tabId,
final int left, final int top,
final int right, final int bottom,
final int bufferWidth, final int bufferHeight, final int token) {
ScreenshotHandler.notifyScreenShot(data, tabId, left, top, right, bottom, bufferWidth, bufferHeight, token);
public static void notifyScreenShot(final ByteBuffer data, final int tabId, final int x, final int y,
final int width, final int height, final int token) {
getHandler().post(new Runnable() {
public void run() {
try {
final Tab tab = Tabs.getInstance().getTab(tabId);
if (tab == null)
return;
if (!Tabs.getInstance().isSelectedTab(tab) && SCREENSHOT_THUMBNAIL != token)
return;
Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
b.copyPixelsFromBuffer(data);
switch (token) {
case SCREENSHOT_WHOLE_PAGE:
GeckoApp.mAppContext.getLayerController()
.getView().getRenderer()
.setCheckerboardBitmap(b, sCheckerboardPageRect);
break;
case SCREENSHOT_UPDATE:
GeckoApp.mAppContext.getLayerController().getView().getRenderer().
updateCheckerboardBitmap(
b, sLastCheckerboardWidthRatio * x,
sLastCheckerboardHeightRatio * y,
sLastCheckerboardWidthRatio * width,
sLastCheckerboardHeightRatio * height,
sCheckerboardPageRect);
break;
case SCREENSHOT_THUMBNAIL:
GeckoApp.mAppContext.processThumbnail(tab, b, null);
break;
}
} finally {
freeDirectBuffer(data);
}
}
});
}
private static CountDownLatch sGeckoPendingAcks = null;
@@ -2096,26 +2136,6 @@ public class GeckoAppShell
if (!GeckoApp.mAppContext.showFilePicker(aMimeType, new AsyncResultHandler(id)))
GeckoAppShell.notifyFilePickerResult("", id);
}
public static void screenshotWholePage(Tab tab) {
ScreenshotHandler.screenshotWholePage(tab);
}
// Called by AndroidBridge using JNI
public static void notifyPaintedRect(float top, float left, float bottom, float right) {
ScreenshotHandler.notifyPaintedRect(top, left, bottom, right);
}
}
class ScreenshotHandler {
private static Queue<PendingScreenshot> sPendingScreenshots = new LinkedList<PendingScreenshot>();
private static RectF sCheckerboardPageRect;
private static float sLastCheckerboardWidthRatio, sLastCheckerboardHeightRatio;
private static RepaintRunnable sRepaintRunnable = new RepaintRunnable();
private static int sMaxTextureSize = 0;
private static final String LOGTAG = "GeckoScreenshot";
private static boolean sDisableScreenshot = false;
private static ByteBuffer sWholePageScreenshotBuffer;
private static int sCheckerboardBufferWidth, sCheckerboardBufferHeight;
static class RepaintRunnable implements Runnable {
private boolean mIsRepaintRunnablePosted = false;
@@ -2138,40 +2158,25 @@ class ScreenshotHandler {
mIsRepaintRunnablePosted = false;
}
Tab tab = Tabs.getInstance().getSelectedTab();
ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics();
if (RectUtils.fuzzyEquals(sCheckerboardPageRect, viewport.getCssPageRect())) {
float width = right - left;
float height = bottom - top;
scheduleCheckerboardScreenshotEvent(tab.getId(),
(int)left, (int)top, (int)width, (int)height,
(int)(sLastCheckerboardWidthRatio * left),
(int)(sLastCheckerboardHeightRatio * top),
(int)(sLastCheckerboardWidthRatio * width),
(int)(sLastCheckerboardHeightRatio * height),
sCheckerboardBufferWidth, sCheckerboardBufferHeight);
} else {
GeckoAppShell.screenshotWholePage(tab);
}
GeckoAppShell.screenshotWholePage(tab);
}
void addRectToRepaint(float top, float left, float bottom, float right) {
synchronized(this) {
ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics();
mDirtyTop = Math.max(sCheckerboardPageRect.top, Math.min(top, mDirtyTop));
mDirtyLeft = Math.max(sCheckerboardPageRect.left, Math.min(left, mDirtyLeft));
mDirtyBottom = Math.min(sCheckerboardPageRect.bottom, Math.max(bottom, mDirtyBottom));
mDirtyRight = Math.min(sCheckerboardPageRect.right, Math.max(right, mDirtyRight));
mDirtyTop = Math.min(top, mDirtyTop);
mDirtyLeft = Math.min(left, mDirtyLeft);
mDirtyBottom = Math.max(bottom, mDirtyBottom);
mDirtyRight = Math.max(right, mDirtyRight);
if (!mIsRepaintRunnablePosted) {
GeckoAppShell.getHandler().postDelayed(this, 5000);
getHandler().postDelayed(this, 5000);
mIsRepaintRunnablePosted = true;
}
}
}
}
// Called by AndroidBridge using JNI
public static void notifyPaintedRect(float top, float left, float bottom, float right) {
sRepaintRunnable.addRectToRepaint(top, left, bottom, right);
}
@@ -2198,9 +2203,7 @@ class ScreenshotHandler {
sMaxTextureSize = maxTextureSize[0];
if (sMaxTextureSize == 0)
return;
sWholePageScreenshotBuffer = GeckoAppShell.allocateDirectBuffer(ScreenshotLayer.getMaxNumPixels() * 2 /* 16 bpp */);
}
ImmutableViewportMetrics viewport = GeckoApp.mAppContext.getLayerController().getViewportMetrics();
Log.i(LOGTAG, "Taking whole-screen screenshot, viewport: " + viewport);
// source width and height to screenshot
@@ -2208,8 +2211,6 @@ class ScreenshotHandler {
float sy = viewport.cssPageRectTop;
float sw = viewport.cssPageRectRight - viewport.cssPageRectLeft;
float sh = viewport.cssPageRectBottom - viewport.cssPageRectTop;
if (sw == 0 || sh == 0)
return;
int maxPixels = Math.min(ScreenshotLayer.getMaxNumPixels(), sMaxTextureSize * sMaxTextureSize);
// 2Mb of 16bit image data
// may be bumped by up to 4x for power of 2 alignment
@@ -2223,100 +2224,14 @@ class ScreenshotHandler {
int dy = 0;
int dw = clamp(minTextureSize, idealDstWidth, sMaxTextureSize);
int dh = maxPixels / dw;
sCheckerboardBufferWidth = dw;
sCheckerboardBufferHeight = dh;
sLastCheckerboardWidthRatio = dw / sw;
sLastCheckerboardHeightRatio = dh / sh;
sCheckerboardPageRect = viewport.getCssPageRect();
scheduleCheckerboardScreenshotEvent(tab.getId(), (int)sx, (int)sy, (int)sw, (int)sh, dx, dy, dw, dh, dw, dh);
}
static void scheduleCheckerboardScreenshotEvent(int tabId, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int bw, int bh) {
float totalSize = sw * sh;
int numSlices = (int) Math.ceil(totalSize / 100000);
if (numSlices == 0)
return;
int srcSliceSize = (int) Math.ceil(sh / numSlices);
int dstSliceSize = (int) Math.ceil(dh / numSlices);
for (int i = 0; i < numSlices; i++) {
GeckoEvent event =
GeckoEvent.createScreenshotEvent(tabId,
sx, sy + srcSliceSize * i, sw, srcSliceSize,
dx, dy + dstSliceSize * i, dw, dstSliceSize, bw, bh,
GeckoAppShell.SCREENSHOT_CHECKERBOARD,
sWholePageScreenshotBuffer);
synchronized(sPendingScreenshots) {
sPendingScreenshots.add(new PendingScreenshot(tabId, event));
if (sPendingScreenshots.size() == 1)
sendNextEventToGecko();
}
}
}
static void sendNextEventToGecko() {
synchronized(sPendingScreenshots) {
if (sPendingScreenshots.isEmpty())
return;
GeckoAppShell.sendEventToGecko(sPendingScreenshots.element().getEvent());
}
}
static class PendingScreenshot {
private final GeckoEvent mEvent;
private final int mTabId;
PendingScreenshot(int tabId, GeckoEvent event) {
mTabId = tabId;
mEvent = event;
}
GeckoEvent getEvent() {
return mEvent;
}
}
public static void notifyScreenShot(final ByteBuffer data, final int tabId,
final int left, final int top,
final int right, final int bottom,
final int bufferWidth, final int bufferHeight, final int token) {
GeckoAppShell.getHandler().post(new Runnable() {
public void run() {
final Tab tab = Tabs.getInstance().getTab(tabId);
if (tab == null) {
if (token == GeckoAppShell.SCREENSHOT_CHECKERBOARD) {
synchronized(sPendingScreenshots) {
sPendingScreenshots.remove();
sendNextEventToGecko();
}
}
return;
}
switch (token) {
case GeckoAppShell.SCREENSHOT_CHECKERBOARD:
{
GeckoApp.mAppContext.getLayerController()
.getView().getRenderer()
.setCheckerboardBitmap(data, bufferWidth, bufferHeight, sCheckerboardPageRect, new Rect(left, top, right, bottom));
synchronized(sPendingScreenshots) {
sPendingScreenshots.remove();
sendNextEventToGecko();
}
break;
}
case GeckoAppShell.SCREENSHOT_THUMBNAIL:
{
if (Tabs.getInstance().isSelectedTab(tab)) {
Bitmap b = tab.getThumbnailBitmap();
b.copyPixelsFromBuffer(data);
GeckoApp.mAppContext.processThumbnail(tab, b, null);
}
break;
}
}
}
});
GeckoAppShell.sendEventToGecko(GeckoEvent.createScreenshotEvent(tab.getId(),
(int)FloatMath.ceil(sx), (int)FloatMath.ceil(sy),
(int)FloatMath.floor(sw), (int)FloatMath.floor(sh),
dx, dy, dw, dh, GeckoAppShell.SCREENSHOT_WHOLE_PAGE));
}
}

View File

@@ -23,7 +23,6 @@ import android.text.format.Time;
import android.os.SystemClock;
import java.lang.Math;
import java.lang.System;
import java.nio.ByteBuffer;
import android.util.Log;
@@ -117,8 +116,6 @@ public class GeckoEvent {
public short mScreenOrientation;
public ByteBuffer mBuffer;
private GeckoEvent(int evType) {
mType = evType;
}
@@ -459,17 +456,15 @@ public class GeckoEvent {
return event;
}
public static GeckoEvent createScreenshotEvent(int tabId, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int bw, int bh, int token, ByteBuffer buffer) {
public static GeckoEvent createScreenshotEvent(int tabId, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh, int token) {
GeckoEvent event = new GeckoEvent(SCREENSHOT);
event.mPoints = new Point[5];
event.mPoints = new Point[4];
event.mPoints[0] = new Point(sx, sy);
event.mPoints[1] = new Point(sw, sh);
event.mPoints[2] = new Point(dx, dy);
event.mPoints[3] = new Point(dw, dh);
event.mPoints[4] = new Point(bw, bh);
event.mMetaState = tabId;
event.mFlags = token;
event.mBuffer = buffer;
return event;
}

View File

@@ -21,7 +21,6 @@ import org.json.JSONObject;
import org.mozilla.gecko.db.BrowserDB;
import org.mozilla.gecko.gfx.Layer;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -66,8 +65,6 @@ public final class Tab {
private ContentObserver mContentObserver;
private int mCheckerboardColor = Color.WHITE;
private int mState;
private ByteBuffer mThumbnailBuffer;
private Bitmap mThumbnailBitmap;
public static final int STATE_DELAYED = 0;
public static final int STATE_LOADING = 1;
@@ -143,31 +140,6 @@ public final class Tab {
return mThumbnail;
}
synchronized public ByteBuffer getThumbnailBuffer() {
int capacity = getThumbnailWidth() * getThumbnailHeight() * 2 /* 16 bpp */;
if (mThumbnailBuffer != null && mThumbnailBuffer.capacity() == capacity)
return mThumbnailBuffer;
if (mThumbnailBuffer != null)
GeckoAppShell.freeDirectBuffer(mThumbnailBuffer); // not calling freeBuffer() because it would deadlock
return mThumbnailBuffer = GeckoAppShell.allocateDirectBuffer(capacity);
}
public Bitmap getThumbnailBitmap() {
if (mThumbnailBitmap != null)
return mThumbnailBitmap;
return mThumbnailBitmap = Bitmap.createBitmap(getThumbnailWidth(), getThumbnailHeight(), Bitmap.Config.RGB_565);
}
public void finalize() {
freeBuffer();
}
synchronized void freeBuffer() {
if (mThumbnailBuffer != null)
GeckoAppShell.freeDirectBuffer(mThumbnailBuffer);
mThumbnailBuffer = null;
}
float getDensity() {
if (sDensity == 0.0f) {
sDensity = GeckoApp.mAppContext.getDisplayMetrics().density;
@@ -189,10 +161,13 @@ public final class Tab {
public void run() {
if (b != null) {
try {
if (mState == Tab.STATE_SUCCESS)
saveThumbnailToDB(new BitmapDrawable(b));
Bitmap bitmap = Bitmap.createScaledBitmap(b, getThumbnailWidth(), getThumbnailHeight(), false);
mThumbnail = new BitmapDrawable(b);
if (mState == Tab.STATE_SUCCESS)
saveThumbnailToDB(new BitmapDrawable(bitmap));
mThumbnail = new BitmapDrawable(bitmap);
b.recycle();
} catch (OutOfMemoryError oom) {
Log.e(LOGTAG, "Unable to create/scale bitmap", oom);
mThumbnail = null;

View File

@@ -76,10 +76,8 @@ public class Tabs implements GeckoEventListener {
public void removeTab(int id) {
if (tabs.containsKey(id)) {
Tab tab = getTab(id);
order.remove(tab);
order.remove(getTab(id));
tabs.remove(id);
tab.freeBuffer();
Log.i(LOGTAG, "Removed a tab with id: " + id);
}
}

View File

@@ -71,11 +71,5 @@ public class IntSize {
public IntSize nextPowerOfTwo() {
return new IntSize(nextPowerOfTwo(width), nextPowerOfTwo(height));
}
public static boolean isPowerOfTwo(int value) {
if (value == 0)
return false;
return (value & (value - 1)) == 0;
}
}

View File

@@ -134,8 +134,8 @@ public class LayerRenderer {
" gl_FragColor = texture2D(sTexture, vTexCoord);\n" +
"}\n";
public void setCheckerboardBitmap(ByteBuffer data, int width, int height, RectF pageRect, Rect copyRect) {
mCheckerboardLayer.setBitmap(data, width, height, copyRect);
public void setCheckerboardBitmap(Bitmap bitmap, RectF pageRect) {
mCheckerboardLayer.setBitmap(bitmap);
mCheckerboardLayer.beginTransaction();
try {
mCheckerboardLayer.setPosition(RectUtils.round(pageRect));

View File

@@ -35,7 +35,6 @@ public class ScreenshotLayer extends SingleTileLayer {
private IntSize mImageSize;
// Whether we have an up-to-date image to draw
private boolean mHasImage;
private static String LOGTAG = "GeckoScreenshot";
public static int getMaxNumPixels() {
return SCREENSHOT_SIZE_LIMIT;
@@ -45,19 +44,6 @@ public class ScreenshotLayer extends SingleTileLayer {
mHasImage = false;
}
void setBitmap(ByteBuffer data, int width, int height, Rect rect) {
mImageSize = new IntSize(width, height);
if (IntSize.isPowerOfTwo(width) && IntSize.isPowerOfTwo(height)) {
mBufferSize = mImageSize;
mHasImage = true;
mImage.setBitmap(data, width, height, CairoImage.FORMAT_RGB16_565, rect);
} else {
Bitmap b = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
b.copyPixelsFromBuffer(data);
setBitmap(b);
}
}
void setBitmap(Bitmap bitmap) {
mImageSize = new IntSize(bitmap.getWidth(), bitmap.getHeight());
int width = IntSize.nextPowerOfTwo(bitmap.getWidth());
@@ -130,21 +116,7 @@ public class ScreenshotLayer extends SingleTileLayer {
}
}
void copyBuffer(ByteBuffer src, ByteBuffer dst, Rect rect, int stride) {
int start = rect.left + rect.top * stride;
int end = Math.min(Math.min(rect.right + (rect.bottom - 1) * stride, src.capacity()), dst.limit());
dst.position(start);
src.position(start).limit(end);
dst.put(src);
}
synchronized void setBitmap(ByteBuffer data, int width, int height, int format, Rect rect) {
mSize = new IntSize(width, height);
mFormat = format;
copyBuffer(data.asReadOnlyBuffer(), mBuffer.duplicate(), rect, width * 2);
}
synchronized void setBitmap(Bitmap bitmap, int width, int height, int format) {
void setBitmap(Bitmap bitmap, int width, int height, int format) {
Bitmap tmp;
mSize = new IntSize(width, height);
mFormat = format;
@@ -166,10 +138,10 @@ public class ScreenshotLayer extends SingleTileLayer {
}
@Override
synchronized public ByteBuffer getBuffer() { return mBuffer; }
public ByteBuffer getBuffer() { return mBuffer; }
@Override
synchronized public IntSize getSize() { return mSize; }
public IntSize getSize() { return mSize; }
@Override
synchronized public int getFormat() { return mFormat; }
public int getFormat() { return mFormat; }
}
}

View File

@@ -88,7 +88,7 @@ AndroidBridge::Init(JNIEnv *jEnv,
jNotifyIME = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyIME", "(II)V");
jNotifyIMEEnabled = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyIMEEnabled", "(ILjava/lang/String;Ljava/lang/String;Z)V");
jNotifyIMEChange = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyIMEChange", "(Ljava/lang/String;III)V");
jNotifyScreenShot = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyScreenShot", "(Ljava/nio/ByteBuffer;IIIIIIII)V");
jNotifyScreenShot = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyScreenShot", "(Ljava/nio/ByteBuffer;IIIIII)V");
jAcknowledgeEventSync = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "acknowledgeEventSync", "()V");
jEnableLocation = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "enableLocation", "(Z)V");
@@ -2350,13 +2350,9 @@ jobject JNICALL
Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(JNIEnv *env, jclass, jlong size);
nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstX, PRInt32 dstY, PRInt32 dstW, PRInt32 dstH, PRInt32 bufW, PRInt32 bufH, PRInt32 tabId, PRInt32 token, jobject buffer)
nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstW, PRInt32 dstH, PRInt32 tabId, float scale, PRInt32 token)
{
nsresult rv;
float scale = 1.0;
if (!buffer)
return NS_OK;
// take a screenshot, as wide as possible, proportional to the destination size
if (!srcW && !srcH) {
@@ -2417,18 +2413,21 @@ nsresult AndroidBridge::TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt
nsPresContext::CSSPixelsToAppUnits(srcW / scale),
nsPresContext::CSSPixelsToAppUnits(srcH / scale));
PRUint32 stride = bufW * 2 /* 16 bpp */;
PRUint32 stride = dstW * 2;
PRUint32 bufferSize = dstH * stride;
jobject buffer = Java_org_mozilla_gecko_GeckoAppShell_allocateDirectBuffer(env, NULL, bufferSize);
if (!buffer)
return NS_OK;
void* data = env->GetDirectBufferAddress(buffer);
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(static_cast<unsigned char*>(data), nsIntSize(bufW, bufH), stride, gfxASurface::ImageFormatRGB16_565);
memset(data, 0, bufferSize);
nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(static_cast<unsigned char*>(data), nsIntSize(dstW, dstH), stride, gfxASurface::ImageFormatRGB16_565);
nsRefPtr<gfxContext> context = new gfxContext(surf);
gfxPoint pt(dstX, dstY);
context->Translate(pt);
context->Scale(scale * dstW / srcW, scale * dstH / srcH);
rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
NS_ENSURE_SUCCESS(rv, rv);
env->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyScreenShot,
buffer, tabId, dstX, dstY, dstX + dstW, dstY + dstH, bufW, bufH, token);
env->CallStaticVoidMethod(AndroidBridge::Bridge()->mGeckoAppShellClass, AndroidBridge::Bridge()->jNotifyScreenShot, buffer, tabId, srcX * dstW / srcW , srcY * dstH / srcH, dstW, dstH, token);
return NS_OK;
}

View File

@@ -155,7 +155,7 @@ public:
SCREENSHOT_UPDATE = 2
};
nsresult TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstY, PRInt32 dstX, PRInt32 dstW, PRInt32 dstH, PRInt32 bufW, PRInt32 bufH, PRInt32 tabId, PRInt32 token, jobject buffer);
nsresult TakeScreenshot(nsIDOMWindow *window, PRInt32 srcX, PRInt32 srcY, PRInt32 srcW, PRInt32 srcH, PRInt32 dstW, PRInt32 dstH, PRInt32 tabId, float scale, PRInt32 token);
static void NotifyPaintedRect(float top, float left, float bottom, float right);

View File

@@ -42,7 +42,6 @@ jfieldID AndroidGeckoEvent::jLocationField = 0;
jfieldID AndroidGeckoEvent::jBandwidthField = 0;
jfieldID AndroidGeckoEvent::jCanBeMeteredField = 0;
jfieldID AndroidGeckoEvent::jScreenOrientationField = 0;
jfieldID AndroidGeckoEvent::jByteBufferField = 0;
jclass AndroidPoint::jPointClass = 0;
jfieldID AndroidPoint::jXField = 0;
@@ -104,12 +103,6 @@ jmethodID AndroidGeckoSurfaceView::jGetHolderMethod = 0;
#define getMethod(fname, ftype) \
((jmethodID) jEnv->GetMethodID(jClass, fname, ftype))
RefCountedJavaObject::~RefCountedJavaObject() {
if (mObject)
GetJNIForThread()->DeleteGlobalRef(mObject);
mObject = NULL;
}
void
mozilla::InitAndroidJavaWrappers(JNIEnv *jEnv)
{
@@ -161,7 +154,6 @@ AndroidGeckoEvent::InitGeckoEventClass(JNIEnv *jEnv)
jBandwidthField = getField("mBandwidth", "D");
jCanBeMeteredField = getField("mCanBeMetered", "Z");
jScreenOrientationField = getField("mScreenOrientation", "S");
jByteBufferField = getField("mBuffer", "Ljava/nio/ByteBuffer;");
}
void
@@ -506,8 +498,7 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
case SCREENSHOT: {
mMetaState = jenv->GetIntField(jobj, jMetaStateField);
mFlags = jenv->GetIntField(jobj, jFlagsField);
ReadPointArray(mPoints, jenv, jPoints, 5);
mByteBuffer = new RefCountedJavaObject(jenv, jenv->GetObjectField(jobj, jByteBufferField));
ReadPointArray(mPoints, jenv, jPoints, 4);
break;
}

View File

@@ -41,27 +41,6 @@ void InitAndroidJavaWrappers(JNIEnv *jEnv);
* handle it.
*/
class RefCountedJavaObject {
public:
RefCountedJavaObject(JNIEnv* env, jobject obj) : mRefCnt(0), mObject(env->NewGlobalRef(obj)) {}
~RefCountedJavaObject();
PRInt32 AddRef() { return ++mRefCnt; }
PRInt32 Release() {
PRInt32 refcnt = --mRefCnt;
if (refcnt == 0)
delete this;
return refcnt;
}
jobject GetObject() { return mObject; }
private:
PRInt32 mRefCnt;
jobject mObject;
};
class WrappedJavaObject {
public:
WrappedJavaObject() :
@@ -597,7 +576,6 @@ public:
double Bandwidth() { return mBandwidth; }
bool CanBeMetered() { return mCanBeMetered; }
short ScreenOrientation() { return mScreenOrientation; }
RefCountedJavaObject* ByteBuffer() { return mByteBuffer; }
protected:
int mAction;
@@ -622,7 +600,6 @@ protected:
double mBandwidth;
bool mCanBeMetered;
short mScreenOrientation;
nsRefPtr<RefCountedJavaObject> mByteBuffer;
void ReadIntArray(nsTArray<int> &aVals,
JNIEnv *jenv,
@@ -676,7 +653,6 @@ protected:
static jfieldID jCanBeMeteredField;
static jfieldID jScreenOrientationField;
static jfieldID jByteBufferField;
public:
enum {

View File

@@ -6,8 +6,6 @@
// Make sure the order of included headers
#include "base/basictypes.h"
#include "nspr/prtypes.h"
#include "base/message_loop.h"
#include "base/task.h"
#include "mozilla/Hal.h"
#include "nsAppShell.h"
@@ -65,34 +63,6 @@ nsAppShell *nsAppShell::gAppShell = nsnull;
NS_IMPL_ISUPPORTS_INHERITED1(nsAppShell, nsBaseAppShell, nsIObserver)
class ScreenshotRunnable : public nsRunnable {
public:
ScreenshotRunnable(nsIAndroidBrowserApp* aBrowserApp, int aTabId, nsTArray<nsIntPoint>& aPoints, int aToken, RefCountedJavaObject* aBuffer):
mBrowserApp(aBrowserApp), mTabId(aTabId), mPoints(aPoints), mToken(aToken), mBuffer(aBuffer) {}
virtual nsresult Run() {
nsCOMPtr<nsIDOMWindow> domWindow;
nsCOMPtr<nsIBrowserTab> tab;
mBrowserApp->GetBrowserTab(mTabId, getter_AddRefs(tab));
if (!tab)
return NS_OK;
tab->GetWindow(getter_AddRefs(domWindow));
if (!domWindow)
return NS_OK;
NS_ASSERTION(mPoints.Length() == 5, "Screenshot event does not have enough coordinates");
AndroidBridge::Bridge()->TakeScreenshot(domWindow, mPoints[0].x, mPoints[0].y, mPoints[1].x, mPoints[1].y, mPoints[2].x, mPoints[2].y, mPoints[3].x, mPoints[3].y, mPoints[4].x, mPoints[4].y, mTabId, mToken, mBuffer->GetObject());
return NS_OK;
}
private:
nsCOMPtr<nsIAndroidBrowserApp> mBrowserApp;
nsTArray<nsIntPoint> mPoints;
int mTabId, mToken;
nsRefPtr<RefCountedJavaObject> mBuffer;
};
class AfterPaintListener : public nsIDOMEventListener {
public:
NS_DECL_ISUPPORTS
@@ -119,15 +89,23 @@ class AfterPaintListener : public nsIDOMEventListener {
if (!paintEvent)
return NS_OK;
nsCOMPtr<nsIDOMClientRect> rect;
paintEvent->GetBoundingClientRect(getter_AddRefs(rect));
float top, left, bottom, right;
rect->GetTop(&top);
rect->GetLeft(&left);
rect->GetRight(&right);
rect->GetBottom(&bottom);
__android_log_print(ANDROID_LOG_INFO, "GeckoScreenshot", "rect: %f, %f, %f, %f", top, left, right, bottom);
AndroidBridge::NotifyPaintedRect(top, left, bottom, right);
nsCOMPtr<nsIDOMClientRectList> rects;
paintEvent->GetClientRects(getter_AddRefs(rects));
if (!rects)
return NS_OK;
PRUint32 length;
rects->GetLength(&length);
for (PRUint32 i = 0; i < length; ++i) {
float top, left, bottom, right;
nsCOMPtr<nsIDOMClientRect> rect = rects->GetItemAt(i);
if (!rect)
continue;
rect->GetTop(&top);
rect->GetLeft(&left);
rect->GetRight(&right);
rect->GetBottom(&bottom);
AndroidBridge::NotifyPaintedRect(top, left, bottom, right);
}
return NS_OK;
}
@@ -447,13 +425,21 @@ nsAppShell::ProcessNextNativeEvent(bool mayWait)
break;
PRInt32 token = curEvent->Flags();
PRInt32 tabId = curEvent->MetaState();
nsCOMPtr<nsIDOMWindow> domWindow;
nsCOMPtr<nsIBrowserTab> tab;
mBrowserApp->GetBrowserTab(curEvent->MetaState(), getter_AddRefs(tab));
if (!tab)
break;
tab->GetWindow(getter_AddRefs(domWindow));
if (!domWindow)
break;
float scale = 1.0;
nsTArray<nsIntPoint> points = curEvent->Points();
RefCountedJavaObject* buffer = curEvent->ByteBuffer();
nsCOMPtr<ScreenshotRunnable> sr =
new ScreenshotRunnable(mBrowserApp, tabId, points, token, buffer);
MessageLoop::current()->PostIdleTask(
FROM_HERE, NewRunnableMethod(sr.get(), &ScreenshotRunnable::Run));
NS_ASSERTION(points.Length() == 4, "Screenshot event does not have enough coordinates");
bridge->TakeScreenshot(domWindow, points[0].x, points[0].y, points[1].x, points[1].y, points[3].x, points[3].y, curEvent->MetaState(), scale, curEvent->Flags());
break;
}