Bug 803299 - Enable 32-bit colour on Android. r=kats
This commit is contained in:
@@ -38,6 +38,7 @@ import android.graphics.Canvas;
|
|||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.ImageFormat;
|
import android.graphics.ImageFormat;
|
||||||
import android.graphics.Paint;
|
import android.graphics.Paint;
|
||||||
|
import android.graphics.PixelFormat;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.graphics.SurfaceTexture;
|
import android.graphics.SurfaceTexture;
|
||||||
@@ -135,6 +136,7 @@ public class GeckoAppShell
|
|||||||
static private final boolean LOGGING = false;
|
static private final boolean LOGGING = false;
|
||||||
|
|
||||||
static private int sDensityDpi = 0;
|
static private int sDensityDpi = 0;
|
||||||
|
static private int sScreenDepth = 0;
|
||||||
|
|
||||||
private static final EventDispatcher sEventDispatcher = new EventDispatcher();
|
private static final EventDispatcher sEventDispatcher = new EventDispatcher();
|
||||||
|
|
||||||
@@ -1379,6 +1381,27 @@ public class GeckoAppShell
|
|||||||
return sDensityDpi;
|
return sDensityDpi;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the colour depth of the default screen. This will either be
|
||||||
|
* 24 or 16.
|
||||||
|
*/
|
||||||
|
public static int getScreenDepth() {
|
||||||
|
if (sScreenDepth == 0 && getGeckoInterface() != null) {
|
||||||
|
switch (getGeckoInterface().getActivity().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) {
|
public static void setFullScreen(boolean fullscreen) {
|
||||||
if (getGeckoInterface() != null)
|
if (getGeckoInterface() != null)
|
||||||
getGeckoInterface().setFullScreen(fullscreen);
|
getGeckoInterface().setFullScreen(fullscreen);
|
||||||
|
|||||||
@@ -182,7 +182,9 @@ public class Tab {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (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;
|
return mThumbnailBitmap;
|
||||||
|
|||||||
@@ -105,7 +105,8 @@ public final class ThumbnailHelper {
|
|||||||
mWidth &= ~0x1; // Ensure the width is always an even number (bug 776906)
|
mWidth &= ~0x1; // Ensure the width is always an even number (bug 776906)
|
||||||
mHeight = Math.round(mWidth * THUMBNAIL_ASPECT_RATIO);
|
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.capacity() != capacity) {
|
||||||
if (mBuffer != null) {
|
if (mBuffer != null) {
|
||||||
mBuffer = DirectBufferAllocator.free(mBuffer);
|
mBuffer = DirectBufferAllocator.free(mBuffer);
|
||||||
@@ -182,7 +183,23 @@ public final class ThumbnailHelper {
|
|||||||
private void processThumbnailData(Tab tab, ByteBuffer data) {
|
private void processThumbnailData(Tab tab, ByteBuffer data) {
|
||||||
Bitmap b = tab.getThumbnailBitmap(mWidth, mHeight);
|
Bitmap b = tab.getThumbnailBitmap(mWidth, mHeight);
|
||||||
data.position(0);
|
data.position(0);
|
||||||
|
if (b.getConfig() == Bitmap.Config.RGB_565) {
|
||||||
b.copyPixelsFromBuffer(data);
|
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);
|
setTabThumbnail(tab, b, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public class GLController {
|
|||||||
|
|
||||||
private static final int LOCAL_EGL_OPENGL_ES2_BIT = 4;
|
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_RED_SIZE, 5,
|
||||||
EGL10.EGL_GREEN_SIZE, 6,
|
EGL10.EGL_GREEN_SIZE, 6,
|
||||||
EGL10.EGL_BLUE_SIZE, 5,
|
EGL10.EGL_BLUE_SIZE, 5,
|
||||||
@@ -58,6 +58,15 @@ public class GLController {
|
|||||||
EGL10.EGL_NONE
|
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() {
|
private GLController() {
|
||||||
// Here we start the GfxInfo thread, which will query OpenGL
|
// 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
|
// system information for Gecko. This must be done early enough that the data will be
|
||||||
@@ -202,26 +211,41 @@ public class GLController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private EGLConfig chooseConfig() {
|
private EGLConfig chooseConfig() {
|
||||||
|
int[] desiredConfig;
|
||||||
|
int rSize, gSize, bSize;
|
||||||
int[] numConfigs = new int[1];
|
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) {
|
numConfigs[0] <= 0) {
|
||||||
throw new GLControllerException("No available EGL configurations " +
|
throw new GLControllerException("No available EGL configurations " +
|
||||||
getEGLError());
|
getEGLError());
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLConfig[] configs = new EGLConfig[numConfigs[0]];
|
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 " +
|
throw new GLControllerException("No EGL configuration for that specification " +
|
||||||
getEGLError());
|
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];
|
int[] red = new int[1], green = new int[1], blue = new int[1];
|
||||||
for (EGLConfig config : configs) {
|
for (EGLConfig config : configs) {
|
||||||
mEGL.eglGetConfigAttrib(mEGLDisplay, config, EGL10.EGL_RED_SIZE, red);
|
mEGL.eglGetConfigAttrib(mEGLDisplay, config, EGL10.EGL_RED_SIZE, red);
|
||||||
mEGL.eglGetConfigAttrib(mEGLDisplay, config, EGL10.EGL_GREEN_SIZE, green);
|
mEGL.eglGetConfigAttrib(mEGLDisplay, config, EGL10.EGL_GREEN_SIZE, green);
|
||||||
mEGL.eglGetConfigAttrib(mEGLDisplay, config, EGL10.EGL_BLUE_SIZE, blue);
|
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;
|
return config;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -316,7 +316,12 @@ public class TopSitesView extends GridView {
|
|||||||
if (b == null)
|
if (b == null)
|
||||||
continue;
|
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)
|
if (thumbnail == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -131,6 +131,7 @@ AndroidBridge::Init(JNIEnv *jEnv,
|
|||||||
jAlertsProgressListener_OnProgress = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "alertsProgressListener_OnProgress", "(Ljava/lang/String;JJLjava/lang/String;)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");
|
jCloseNotification = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "closeNotification", "(Ljava/lang/String;)V");
|
||||||
jGetDpi = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getDpi", "()I");
|
jGetDpi = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getDpi", "()I");
|
||||||
|
jGetScreenDepth = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "getScreenDepth", "()I");
|
||||||
jSetFullScreen = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setFullScreen", "(Z)V");
|
jSetFullScreen = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "setFullScreen", "(Z)V");
|
||||||
jShowInputMethodPicker = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showInputMethodPicker", "()V");
|
jShowInputMethodPicker = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "showInputMethodPicker", "()V");
|
||||||
jNotifyDefaultPrevented = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyDefaultPrevented", "(Z)V");
|
jNotifyDefaultPrevented = (jmethodID) jEnv->GetStaticMethodID(jGeckoAppShellClass, "notifyDefaultPrevented", "(Z)V");
|
||||||
@@ -772,6 +773,29 @@ AndroidBridge::GetDPI()
|
|||||||
return sDPI;
|
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
|
void
|
||||||
AndroidBridge::ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions)
|
AndroidBridge::ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions)
|
||||||
{
|
{
|
||||||
@@ -2641,13 +2665,17 @@ nsresult AndroidBridge::CaptureThumbnail(nsIDOMWindow *window, int32_t bufW, int
|
|||||||
nsPresContext::CSSPixelsToAppUnits(srcW / scale),
|
nsPresContext::CSSPixelsToAppUnits(srcW / scale),
|
||||||
nsPresContext::CSSPixelsToAppUnits(srcH / 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);
|
void* data = env->GetDirectBufferAddress(buffer);
|
||||||
if (!data)
|
if (!data)
|
||||||
return NS_ERROR_FAILURE;
|
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) {
|
if (surf->CairoStatus() != 0) {
|
||||||
ALOG_BRIDGE("Error creating gfxImageSurface");
|
ALOG_BRIDGE("Error creating gfxImageSurface");
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
|||||||
@@ -254,6 +254,7 @@ public:
|
|||||||
void CloseNotification(const nsAString& aAlertName);
|
void CloseNotification(const nsAString& aAlertName);
|
||||||
|
|
||||||
int GetDPI();
|
int GetDPI();
|
||||||
|
int GetScreenDepth();
|
||||||
|
|
||||||
void ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions);
|
void ShowFilePickerForExtensions(nsAString& aFilePath, const nsAString& aExtensions);
|
||||||
void ShowFilePickerForMimeType(nsAString& aFilePath, const nsAString& aMimeType);
|
void ShowFilePickerForMimeType(nsAString& aFilePath, const nsAString& aMimeType);
|
||||||
@@ -479,6 +480,7 @@ protected:
|
|||||||
jmethodID jAlertsProgressListener_OnProgress;
|
jmethodID jAlertsProgressListener_OnProgress;
|
||||||
jmethodID jCloseNotification;
|
jmethodID jCloseNotification;
|
||||||
jmethodID jGetDpi;
|
jmethodID jGetDpi;
|
||||||
|
jmethodID jGetScreenDepth;
|
||||||
jmethodID jSetFullScreen;
|
jmethodID jSetFullScreen;
|
||||||
jmethodID jShowInputMethodPicker;
|
jmethodID jShowInputMethodPicker;
|
||||||
jmethodID jNotifyDefaultPrevented;
|
jmethodID jNotifyDefaultPrevented;
|
||||||
|
|||||||
@@ -45,9 +45,7 @@ nsScreenAndroid::GetAvailRect(int32_t *outLeft, int32_t *outTop, int32_t *outWid
|
|||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsScreenAndroid::GetPixelDepth(int32_t *aPixelDepth)
|
nsScreenAndroid::GetPixelDepth(int32_t *aPixelDepth)
|
||||||
{
|
{
|
||||||
// XXX do we need to lie here about 16bpp? Or
|
*aPixelDepth = AndroidBridge::Bridge()->GetScreenDepth();
|
||||||
// should we actually check and return the right thing?
|
|
||||||
*aPixelDepth = 16;
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1066,11 +1066,17 @@ nsWindow::OnDraw(AndroidGeckoEvent *ae)
|
|||||||
return;
|
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");
|
layers::renderTraceEventStart("Get surface", "424545");
|
||||||
static unsigned char bits2[32 * 32 * 2];
|
static unsigned char bits2[32 * 32 * 4];
|
||||||
nsRefPtr<gfxImageSurface> targetSurface =
|
nsRefPtr<gfxImageSurface> targetSurface =
|
||||||
new gfxImageSurface(bits2, gfxIntSize(32, 32), 32 * 2,
|
new gfxImageSurface(bits2, gfxIntSize(32, 32), 32 * bytesPerPixel, format);
|
||||||
gfxASurface::ImageFormatRGB16_565);
|
|
||||||
layers::renderTraceEventEnd("Get surface", "424545");
|
layers::renderTraceEventEnd("Get surface", "424545");
|
||||||
|
|
||||||
layers::renderTraceEventStart("Widget draw to", "434646");
|
layers::renderTraceEventStart("Widget draw to", "434646");
|
||||||
|
|||||||
Reference in New Issue
Block a user