☠☠ backed out by a2193ebecd1d ☠ ☠ | |
author | Chris Lord <chrislord.net@gmail.com> |
Thu, 02 May 2013 18:25:16 +0100 | |
changeset 141608 | 3c366c865e73b91d1a0a56f711d0c81c6dda6bad |
parent 141607 | 9a10069d27ba729f2332d3c9495e7d5b07d4ca9a |
child 141609 | 0cb5418906cfd4ecbbe9c3e15d4e6c0124f8dd9c |
push id | 2579 |
push user | akeybl@mozilla.com |
push date | Mon, 24 Jun 2013 18:52:47 +0000 |
treeherder | mozilla-beta@b69b7de8a05a [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | kats |
bugs | 803299 |
milestone | 23.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/mobile/android/base/GeckoAppShell.java +++ b/mobile/android/base/GeckoAppShell.java @@ -28,16 +28,17 @@ import android.content.pm.PackageManager import android.content.pm.ResolveInfo; import android.content.res.TypedArray; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.ImageFormat; import android.graphics.Paint; +import android.graphics.PixelFormat; import android.graphics.Rect; import android.graphics.RectF; import android.graphics.SurfaceTexture; import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.hardware.Sensor; import android.hardware.SensorManager; import android.location.Criteria; @@ -120,16 +121,17 @@ public class GeckoAppShell static public final int WPL_STATE_IS_NETWORK = 0x00040000; public static final String SHORTCUT_TYPE_WEBAPP = "webapp"; public static final String SHORTCUT_TYPE_BOOKMARK = "bookmark"; static private final boolean LOGGING = false; static private int sDensityDpi = 0; + static private int sScreenDepth = 0; private static final EventDispatcher sEventDispatcher = new EventDispatcher(); /* Default colors. */ private static final float[] DEFAULT_LAUNCHER_ICON_HSV = { 32.0f, 1.0f, 1.0f }; /* Is the value in sVibrationEndTime valid? */ private static boolean sVibrationMaybePlaying = false; @@ -1280,16 +1282,37 @@ public class GeckoAppShell public static int getDpi() { if (sDensityDpi == 0) { sDensityDpi = GeckoApp.mAppContext.getResources().getDisplayMetrics().densityDpi; } return sDensityDpi; } + /** + * Returns the colour depth of the default screen. This will either be + * 24 or 16. + */ + public static int getScreenDepth() { + if (sScreenDepth == 0) { + switch (GeckoApp.mAppContext.getWindowManager().getDefaultDisplay().getPixelFormat()) { + case PixelFormat.RGBA_8888 : + case PixelFormat.RGBX_8888 : + case PixelFormat.RGB_888 : + sScreenDepth = 24; + break; + default: + sScreenDepth = 16; + break; + } + } + + return sScreenDepth; + } + public static void setFullScreen(boolean fullscreen) { GeckoApp.mAppContext.setFullScreen(fullscreen); } public static String showFilePickerForExtensions(String aExtensions) { return sActivityHelper.showFilePicker(GeckoApp.mAppContext, getMimeTypeFromExtensions(aExtensions)); }
--- a/mobile/android/base/Tab.java +++ b/mobile/android/base/Tab.java @@ -177,17 +177,19 @@ public class Tab { boolean sizeChange = mThumbnailBitmap.getWidth() != width || mThumbnailBitmap.getHeight() != height; if (honeycomb || sizeChange) { mThumbnailBitmap = null; } } if (mThumbnailBitmap == null) { - mThumbnailBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565); + Bitmap.Config config = (GeckoAppShell.getScreenDepth() == 24) ? + Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; + mThumbnailBitmap = Bitmap.createBitmap(width, height, config); } return mThumbnailBitmap; } public void updateThumbnail(final Bitmap b) { ThreadUtils.postToBackgroundThread(new Runnable() { @Override
--- a/mobile/android/base/ThumbnailHelper.java +++ b/mobile/android/base/ThumbnailHelper.java @@ -100,17 +100,18 @@ public final class ThumbnailHelper { private void updateThumbnailSize() { // Apply any pending width updates mWidth = mPendingWidth.get(); mWidth &= ~0x1; // Ensure the width is always an even number (bug 776906) mHeight = Math.round(mWidth * THUMBNAIL_ASPECT_RATIO); - int capacity = mWidth * mHeight * 2; // Multiply by 2 for 16bpp + int pixelSize = (GeckoAppShell.getScreenDepth() == 24) ? 4 : 2; + int capacity = mWidth * mHeight * pixelSize; if (mBuffer == null || mBuffer.capacity() != capacity) { if (mBuffer != null) { mBuffer = DirectBufferAllocator.free(mBuffer); } try { mBuffer = DirectBufferAllocator.allocate(capacity); } catch (IllegalArgumentException iae) { Log.w(LOGTAG, iae.toString()); @@ -177,17 +178,33 @@ public final class ThumbnailHelper { if (shouldUpdateThumbnail(tab)) { processThumbnailData(tab, data); } } private void processThumbnailData(Tab tab, ByteBuffer data) { Bitmap b = tab.getThumbnailBitmap(mWidth, mHeight); data.position(0); - b.copyPixelsFromBuffer(data); + if (b.getConfig() == Bitmap.Config.RGB_565) { + b.copyPixelsFromBuffer(data); + } else { + // Unfortunately, Gecko's 32-bit format is BGRA and Android's is + // ARGB, so we need to manually swizzle. + for (int y = 0; y < mHeight; y++) { + for (int x = 0; x < mWidth; x++) { + int index = (y * mWidth + x) * 4; + int bgra = data.getInt(index); + int argb = ((bgra << 24) & 0xFF000000) + | ((bgra << 8) & 0x00FF0000) + | ((bgra >> 8) & 0x0000FF00) + | ((bgra >> 24) & 0x000000FF); + b.setPixel(x, y, argb); + } + } + } setTabThumbnail(tab, b, null); } private void setTabThumbnail(Tab tab, Bitmap bitmap, byte[] compressed) { if (bitmap == null) { if (compressed == null) { Log.w(LOGTAG, "setTabThumbnail: one of bitmap or compressed must be non-null!"); return;
--- a/mobile/android/base/gfx/GLController.java +++ b/mobile/android/base/gfx/GLController.java @@ -44,25 +44,34 @@ public class GLController { private EGL10 mEGL; private EGLDisplay mEGLDisplay; private EGLConfig mEGLConfig; private EGLSurface mEGLSurface; private static final int LOCAL_EGL_OPENGL_ES2_BIT = 4; - private static final int[] CONFIG_SPEC = { + private static final int[] CONFIG_SPEC_16BPP = { EGL10.EGL_RED_SIZE, 5, EGL10.EGL_GREEN_SIZE, 6, EGL10.EGL_BLUE_SIZE, 5, EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT, EGL10.EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT, EGL10.EGL_NONE }; + private static final int[] CONFIG_SPEC_24BPP = { + EGL10.EGL_RED_SIZE, 8, + EGL10.EGL_GREEN_SIZE, 8, + EGL10.EGL_BLUE_SIZE, 8, + EGL10.EGL_SURFACE_TYPE, EGL10.EGL_WINDOW_BIT, + EGL10.EGL_RENDERABLE_TYPE, LOCAL_EGL_OPENGL_ES2_BIT, + EGL10.EGL_NONE + }; + private GLController() { // Here we start the GfxInfo thread, which will query OpenGL // system information for Gecko. This must be done early enough that the data will be // ready by the time it's needed to initialize the compositor (it takes about 100 ms // to obtain). GfxInfoThread.startThread(); } @@ -197,36 +206,51 @@ public class GLController { if (mEGLDisplay == EGL10.EGL_NO_DISPLAY) { throw new GLControllerException("eglGetDisplay() failed"); } mEGLConfig = chooseConfig(); } private EGLConfig chooseConfig() { + int[] desiredConfig; + int rSize, gSize, bSize; int[] numConfigs = new int[1]; - if (!mEGL.eglChooseConfig(mEGLDisplay, CONFIG_SPEC, null, 0, numConfigs) || + + switch (GeckoAppShell.getScreenDepth()) { + case 24: + desiredConfig = CONFIG_SPEC_24BPP; + rSize = gSize = bSize = 8; + break; + case 16: + default: + desiredConfig = CONFIG_SPEC_16BPP; + rSize = 5; gSize = 6; bSize = 5; + break; + } + + if (!mEGL.eglChooseConfig(mEGLDisplay, desiredConfig, null, 0, numConfigs) || numConfigs[0] <= 0) { throw new GLControllerException("No available EGL configurations " + getEGLError()); } EGLConfig[] configs = new EGLConfig[numConfigs[0]]; - if (!mEGL.eglChooseConfig(mEGLDisplay, CONFIG_SPEC, configs, numConfigs[0], numConfigs)) { + if (!mEGL.eglChooseConfig(mEGLDisplay, desiredConfig, configs, numConfigs[0], numConfigs)) { throw new GLControllerException("No EGL configuration for that specification " + getEGLError()); } - // Select the first 565 RGB configuration. + // Select the first configuration that matches the screen depth. int[] red = new int[1], green = new int[1], blue = new int[1]; for (EGLConfig config : configs) { mEGL.eglGetConfigAttrib(mEGLDisplay, config, EGL10.EGL_RED_SIZE, red); mEGL.eglGetConfigAttrib(mEGLDisplay, config, EGL10.EGL_GREEN_SIZE, green); mEGL.eglGetConfigAttrib(mEGLDisplay, config, EGL10.EGL_BLUE_SIZE, blue); - if (red[0] == 5 && green[0] == 6 && blue[0] == 5) { + if (red[0] == rSize && green[0] == gSize && blue[0] == bSize) { return config; } } throw new GLControllerException("No suitable EGL configuration found"); } /* This function is invoked by JNI on the compositor thread */
--- a/mobile/android/base/widget/TopSitesView.java +++ b/mobile/android/base/widget/TopSitesView.java @@ -311,17 +311,22 @@ public class TopSitesView extends GridVi return thumbnails; do { final String url = c.getString(c.getColumnIndexOrThrow(Thumbnails.URL)); final byte[] b = c.getBlob(c.getColumnIndexOrThrow(Thumbnails.DATA)); if (b == null) continue; - Bitmap thumbnail = BitmapUtils.decodeByteArray(b); + Bitmap thumbnail = null; + try { + thumbnail = BitmapUtils.decodeByteArray(b); + } catch (IllegalArgumentException e) { + Log.e(LOGTAG, "Error decoding thumbnail", e); + } if (thumbnail == null) continue; thumbnails.put(url, thumbnail); } while (c.moveToNext()); } finally { if (c != null) c.close();
--- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -126,16 +126,17 @@ AndroidBridge::Init(JNIEnv *jEnv, jShowFilePickerForExtensions = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showFilePickerForExtensions", "(Ljava/lang/String;)Ljava/lang/String;"); jShowFilePickerForMimeType = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showFilePickerForMimeType", "(Ljava/lang/String;)Ljava/lang/String;"); jShowFilePickerAsync = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showFilePickerAsync", "(Ljava/lang/String;J)V"); jUnlockProfile = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "unlockProfile", "()Z"); jKillAnyZombies = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "killAnyZombies", "()V"); jAlertsProgressListener_OnProgress = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "alertsProgressListener_OnProgress", "(Ljava/lang/String;JJLjava/lang/String;)V"); jCloseNotification = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "closeNotification", "(Ljava/lang/String;)V"); jGetDpi = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getDpi", "()I"); + jGetScreenDepth = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getScreenDepth", "()I"); jSetFullScreen = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setFullScreen", "(Z)V"); jShowInputMethodPicker = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showInputMethodPicker", "()V"); jNotifyDefaultPrevented = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyDefaultPrevented", "(Z)V"); jHideProgressDialog = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "hideProgressDialog", "()V"); jPerformHapticFeedback = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "performHapticFeedback", "(Z)V"); jVibrate1 = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "vibrate", "(J)V"); jVibrateA = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "vibrate", "([JI)V"); jCancelVibrate = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "cancelVibrate", "()V"); @@ -767,16 +768,39 @@ AndroidBridge::GetDPI() if (jniFrame.CheckForException()) { sDPI = 0; return DEFAULT_DPI; } return sDPI; } +int +AndroidBridge::GetScreenDepth() +{ + static int sDepth = 0; + if (sDepth) + return sDepth; + + ALOG_BRIDGE("AndroidBridge::GetScreenDepth"); + const int DEFAULT_DEPTH = 16; + JNIEnv *env = GetJNIEnv(); + if (!env) + return DEFAULT_DEPTH; + AutoLocalJNIFrame jniFrame(env); + + sDepth = (int)env->CallStaticIntMethod(mGeckoAppShellClass, jGetScreenDepth); + if (jniFrame.CheckForException()) { + sDepth = 0; + return DEFAULT_DEPTH; + } + + return sDepth; +} + void AndroidBridge::ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions) { ALOG_BRIDGE("AndroidBridge::ShowFilePickerForExtensions"); JNIEnv *env = GetJNIEnv(); if (!env) return; @@ -2636,23 +2660,27 @@ nsresult AndroidBridge::CaptureThumbnail nsCOMPtr<nsIPresShell> presShell = presContext->PresShell(); uint32_t renderDocFlags = (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING | nsIPresShell::RENDER_DOCUMENT_RELATIVE); nsRect r(nsPresContext::CSSPixelsToAppUnits(srcX / scale), nsPresContext::CSSPixelsToAppUnits(srcY / scale), nsPresContext::CSSPixelsToAppUnits(srcW / scale), nsPresContext::CSSPixelsToAppUnits(srcH / scale)); - uint32_t stride = bufW * 2 /* 16 bpp */; + bool is24bit = (GetScreenDepth() == 24); + uint32_t stride = bufW * (is24bit ? 4 : 2); void* data = env->GetDirectBufferAddress(buffer); if (!data) return NS_ERROR_FAILURE; - nsRefPtr<gfxImageSurface> surf = new gfxImageSurface(static_cast<unsigned char*>(data), nsIntSize(bufW, bufH), stride, gfxASurface::ImageFormatRGB16_565); + nsRefPtr<gfxImageSurface> surf = + new gfxImageSurface(static_cast<unsigned char*>(data), nsIntSize(bufW, bufH), stride, + is24bit ? gfxASurface::ImageFormatRGB24 : + gfxASurface::ImageFormatRGB16_565); if (surf->CairoStatus() != 0) { ALOG_BRIDGE("Error creating gfxImageSurface"); return NS_ERROR_FAILURE; } nsRefPtr<gfxContext> context = new gfxContext(surf); gfxPoint pt(0, 0); context->Translate(pt); context->Scale(scale * bufW / srcW, scale * bufH / srcH);
--- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -249,16 +249,17 @@ public: void AlertsProgressListener_OnProgress(const nsAString& aAlertName, int64_t aProgress, int64_t aProgressMax, const nsAString& aAlertText); void CloseNotification(const nsAString& aAlertName); int GetDPI(); + int GetScreenDepth(); void ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions); void ShowFilePickerForMimeType(nsAString& aFilePath, const nsAString& aMimeType); void ShowFilePickerAsync(const nsAString& aMimeType, nsFilePickerCallback* callback); void PerformHapticFeedback(bool aIsLongPress); void Vibrate(const nsTArray<uint32_t>& aPattern); @@ -474,16 +475,17 @@ protected: jmethodID jShowFilePickerForExtensions; jmethodID jShowFilePickerForMimeType; jmethodID jShowFilePickerAsync; jmethodID jUnlockProfile; jmethodID jKillAnyZombies; jmethodID jAlertsProgressListener_OnProgress; jmethodID jCloseNotification; jmethodID jGetDpi; + jmethodID jGetScreenDepth; jmethodID jSetFullScreen; jmethodID jShowInputMethodPicker; jmethodID jNotifyDefaultPrevented; jmethodID jHideProgressDialog; jmethodID jPerformHapticFeedback; jmethodID jVibrate1; jmethodID jVibrateA; jmethodID jCancelVibrate;
--- a/widget/android/nsScreenManagerAndroid.cpp +++ b/widget/android/nsScreenManagerAndroid.cpp @@ -40,19 +40,17 @@ nsScreenAndroid::GetAvailRect(int32_t *o return GetRect(outLeft, outTop, outWidth, outHeight); } NS_IMETHODIMP nsScreenAndroid::GetPixelDepth(int32_t *aPixelDepth) { - // XXX do we need to lie here about 16bpp? Or - // should we actually check and return the right thing? - *aPixelDepth = 16; + *aPixelDepth = AndroidBridge::Bridge()->GetScreenDepth(); return NS_OK; } NS_IMETHODIMP nsScreenAndroid::GetColorDepth(int32_t *aColorDepth) { return GetPixelDepth(aColorDepth);
--- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -1056,21 +1056,27 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae) return; AutoLocalJNIFrame jniFrame; // We're paused, or we haven't been given a window-size yet, so do nothing if (sCompositorPaused || gAndroidBounds.width <= 0 || gAndroidBounds.height <= 0) { return; } + int bytesPerPixel = 2; + gfxASurface::gfxImageFormat format = gfxASurface::ImageFormatRGB16_565; + if (AndroidBridge::Bridge()->GetScreenDepth() == 24) { + bytesPerPixel = 4; + format = gfxASurface::ImageFormatRGB24; + } + layers::renderTraceEventStart("Get surface", "424545"); - static unsigned char bits2[32 * 32 * 2]; + static unsigned char bits2[32 * 32 * 4]; nsRefPtr<gfxImageSurface> targetSurface = - new gfxImageSurface(bits2, gfxIntSize(32, 32), 32 * 2, - gfxASurface::ImageFormatRGB16_565); + new gfxImageSurface(bits2, gfxIntSize(32, 32), 32 * bytesPerPixel, format); layers::renderTraceEventEnd("Get surface", "424545"); layers::renderTraceEventStart("Widget draw to", "434646"); if (targetSurface->CairoStatus()) { ALOG("### Failed to create a valid surface from the bitmap"); } else { DrawTo(targetSurface, ae->Rect()); }