Merge "Don't use full screen FBOs, this dramatically increase performance."
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index ccf1221..b460910 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -368,19 +368,19 @@
@Override
public void drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint) {
- final float width = bitmap.getWidth();
- final float height = bitmap.getHeight();
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
- nDrawBitmap(mRenderer, bitmap.mNativeBitmap, 0.0f, 0.0f, width, height,
- 0.0f, 0.0f, width, height, matrix.native_instance, nativePaint,
+ nDrawBitmap(mRenderer, bitmap.mNativeBitmap, matrix.native_instance, nativePaint,
bitmap.getDensity(), mDensity, mScreenDensity);
}
+ private native void nDrawBitmap(int renderer, int bitmap, int matrix, int paint,
+ int bitmapDensity, int canvasDensity, int screenDensity);
+
@Override
public void drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) {
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
nDrawBitmap(mRenderer, bitmap.mNativeBitmap, src.left, src.top, src.right, src.bottom,
- dst.left, dst.top, dst.right, dst.bottom, 0, nativePaint,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint,
bitmap.getDensity(), mDensity, mScreenDensity);
}
@@ -388,7 +388,7 @@
public void drawBitmap(Bitmap bitmap, Rect src, RectF dst, Paint paint) {
final int nativePaint = paint == null ? 0 : paint.mNativePaint;
nDrawBitmap(mRenderer, bitmap.mNativeBitmap, src.left, src.top, src.right, src.bottom,
- dst.left, dst.top, dst.right, dst.bottom, 0, nativePaint,
+ dst.left, dst.top, dst.right, dst.bottom, nativePaint,
bitmap.getDensity(), mDensity, mScreenDensity);
}
@@ -397,7 +397,7 @@
private native void nDrawBitmap(int renderer, int bitmap,
float srcLeft, float srcTop, float srcRight, float srcBottom,
- float left, float top, float right, float bottom, int matrix, int paint,
+ float left, float top, float right, float bottom, int paint,
int bitmapDensity, int canvasDensity, int screenDensity);
@Override
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index a1ee3d3..d30bce9 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -413,33 +413,30 @@
}
EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
- int[] num_config = new int[1];
- if (!egl.eglChooseConfig(display, mConfigSpec, null, 0,
- num_config)) {
+ int[] index = new int[1];
+ if (!egl.eglChooseConfig(display, mConfigSpec, null, 0, index)) {
throw new IllegalArgumentException("eglChooseConfig failed");
}
- int numConfigs = num_config[0];
-
+ int numConfigs = index[0];
if (numConfigs <= 0) {
- throw new IllegalArgumentException(
- "No configs match configSpec");
+ throw new IllegalArgumentException("No configs match configSpec");
}
EGLConfig[] configs = new EGLConfig[numConfigs];
- if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs,
- num_config)) {
- throw new IllegalArgumentException("eglChooseConfig#2 failed");
+ if (!egl.eglChooseConfig(display, mConfigSpec, configs, numConfigs, index)) {
+ throw new IllegalArgumentException("eglChooseConfig failed");
}
+
EGLConfig config = chooseConfig(egl, display, configs);
if (config == null) {
throw new IllegalArgumentException("No config chosen");
}
+
return config;
}
- abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,
- EGLConfig[] configs);
+ abstract EGLConfig chooseConfig(EGL10 egl, EGLDisplay display, EGLConfig[] configs);
private int[] filterConfigSpec(int[] configSpec) {
if (mGlVersion != 2) {
@@ -450,10 +447,10 @@
*/
int len = configSpec.length;
int[] newConfigSpec = new int[len + 2];
- System.arraycopy(configSpec, 0, newConfigSpec, 0, len-1);
- newConfigSpec[len-1] = EGL10.EGL_RENDERABLE_TYPE;
+ System.arraycopy(configSpec, 0, newConfigSpec, 0, len - 1);
+ newConfigSpec[len - 1] = EGL10.EGL_RENDERABLE_TYPE;
newConfigSpec[len] = 4; /* EGL_OPENGL_ES2_BIT */
- newConfigSpec[len+1] = EGL10.EGL_NONE;
+ newConfigSpec[len + 1] = EGL10.EGL_NONE;
return newConfigSpec;
}
}
@@ -496,13 +493,12 @@
for (EGLConfig config : configs) {
int d = findConfigAttrib(egl, display, config, EGL10.EGL_DEPTH_SIZE, 0);
int s = findConfigAttrib(egl, display, config, EGL10.EGL_STENCIL_SIZE, 0);
- if ((d >= mDepthSize) && (s >= mStencilSize)) {
+ if (d >= mDepthSize && s >= mStencilSize) {
int r = findConfigAttrib(egl, display, config, EGL10.EGL_RED_SIZE, 0);
int g = findConfigAttrib(egl, display, config, EGL10.EGL_GREEN_SIZE, 0);
int b = findConfigAttrib(egl, display, config, EGL10.EGL_BLUE_SIZE, 0);
int a = findConfigAttrib(egl, display, config, EGL10.EGL_ALPHA_SIZE, 0);
- if ((r == mRedSize) && (g == mGreenSize) && (b == mBlueSize) &&
- (a == mAlphaSize)) {
+ if (r == mRedSize && g == mGreenSize && b == mBlueSize && a >= mAlphaSize) {
return config;
}
}
@@ -510,16 +506,15 @@
return null;
}
- private int findConfigAttrib(EGL10 egl, EGLDisplay display,
- EGLConfig config, int attribute, int defaultValue) {
-
+ private int findConfigAttrib(EGL10 egl, EGLDisplay display, EGLConfig config,
+ int attribute, int defaultValue) {
if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {
return mValue[0];
}
return defaultValue;
}
- }
+ }
}
/**
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index cba6ed1..89ad534 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -195,13 +195,22 @@
OpenGLRenderer* renderer, SkBitmap* bitmap,
float srcLeft, float srcTop, float srcRight, float srcBottom,
float dstLeft, float dstTop, float dstRight, float dstBottom,
- SkMatrix* matrix, SkPaint* paint,
- jint bitmapDensity, jint canvasDensity, jint screenDensity) {
+ SkPaint* paint, jint bitmapDensity, jint canvasDensity, jint screenDensity) {
if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
- dstLeft, dstTop, dstRight, dstBottom, matrix, paint);
+ dstLeft, dstTop, dstRight, dstBottom, paint);
} else {
+ // TODO: implement
+ }
+}
+static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject canvas,
+ OpenGLRenderer* renderer, SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint,
+ jint bitmapDensity, jint canvasDensity,jint screenDensity) {
+ if (canvasDensity == bitmapDensity || canvasDensity == 0 || bitmapDensity == 0) {
+ renderer->drawBitmap(bitmap, matrix, paint);
+ } else {
+ // TODO: implement
}
}
@@ -249,7 +258,8 @@
{ "nConcatMatrix", "(II)V", (void*) android_view_GLES20Canvas_concatMatrix },
{ "nDrawBitmap", "(IIFFIIII)V", (void*) android_view_GLES20Canvas_drawBitmap },
- { "nDrawBitmap", "(IIFFFFFFFFIIIII)V", (void*) android_view_GLES20Canvas_drawBitmapRect },
+ { "nDrawBitmap", "(IIFFFFFFFFIIII)V", (void*) android_view_GLES20Canvas_drawBitmapRect },
+ { "nDrawBitmap", "(IIIIIII)V", (void*) android_view_GLES20Canvas_drawBitmapMatrix },
{ "nDrawColor", "(III)V", (void*) android_view_GLES20Canvas_drawColor },
{ "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect },
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 091abb0..8b4fb9b 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -111,6 +111,7 @@
mWidth = width;
mHeight = height;
+ mFirstSnapshot.height = height;
}
void OpenGLRenderer::prepare() {
@@ -170,10 +171,15 @@
bool OpenGLRenderer::restoreSnapshot() {
bool restoreClip = mSnapshot->flags & Snapshot::kFlagClipSet;
bool restoreLayer = mSnapshot->flags & Snapshot::kFlagIsLayer;
+ bool restoreOrtho = mSnapshot->flags & Snapshot::kFlagDirtyOrtho;
sp<Snapshot> current = mSnapshot;
sp<Snapshot> previous = mSnapshot->previous;
+ if (restoreOrtho) {
+ memcpy(mOrthoMatrix, current->orthoMatrix, sizeof(mOrthoMatrix));
+ }
+
if (restoreLayer) {
composeLayer(current, previous);
}
@@ -197,21 +203,11 @@
// The texture is currently as big as the window but drawn with
// a quad of the appropriate size
const Rect& layer = current->layer;
- Rect texCoords(current->layer);
- mSnapshot->transform.mapRect(texCoords);
-
- const float u1 = texCoords.left / float(mWidth);
- const float v1 = (mHeight - texCoords.top) / float(mHeight);
- const float u2 = texCoords.right / float(mWidth);
- const float v2 = (mHeight - texCoords.bottom) / float(mHeight);
-
- resetDrawTextureTexCoords(u1, v1, u2, v2);
drawTextureRect(layer.left, layer.top, layer.right, layer.bottom,
current->texture, current->alpha, current->mode, true, true);
- resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
-
+ // TODO Don't delete these things, but cache them
glDeleteFramebuffers(1, ¤t->fbo);
glDeleteTextures(1, ¤t->texture);
}
@@ -268,14 +264,10 @@
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// TODO VERY IMPORTANT: Fix TextView to not call saveLayer() all the time
- // TODO ***** IMPORTANT *****
- // Creating a texture-backed FBO works only if the texture is the same size
- // as the original rendering buffer (in this case, mWidth and mHeight.)
- // This is expensive and wasteful and must be fixed.
- // TODO Additionally we should use an FBO cache
+ // TODO Use an FBO cache
- const GLsizei width = mWidth; //right - left;
- const GLsizei height = mHeight; //bottom - right;
+ const GLsizei width = right - left;
+ const GLsizei height = bottom - top;
const GLint format = (flags & SkCanvas::kHasAlphaLayer_SaveFlag) ? GL_RGBA : GL_RGB;
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, NULL);
@@ -287,7 +279,7 @@
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE) {
- LOGD("Framebuffer incomplete %d", status);
+ LOGD("Framebuffer incomplete (GL error code 0x%x)", status);
glDeleteFramebuffers(1, &snapshot->fbo);
glDeleteTextures(1, &snapshot->texture);
@@ -295,11 +287,34 @@
return false;
}
+ // Clear the FBO
+ glDisable(GL_SCISSOR_TEST);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glEnable(GL_SCISSOR_TEST);
+
snapshot->flags |= Snapshot::kFlagIsLayer;
snapshot->mode = mode;
snapshot->alpha = alpha / 255.0f;
snapshot->layer.set(left, top, right, bottom);
+ // Creates a new snapshot to draw into the FBO
+ saveSnapshot();
+ // TODO: This doesn't preserve other transformations (check Skia first)
+ mSnapshot->transform.loadTranslate(-left, -top, 0.0f);
+ mSnapshot->clipRect.set(left, top, right, bottom);
+ mSnapshot->height = bottom - top;
+ setScissorFromClip();
+
+ mSnapshot->flags = Snapshot::kFlagDirtyTransform | Snapshot::kFlagDirtyOrtho |
+ Snapshot::kFlagClipSet;
+ memcpy(mSnapshot->orthoMatrix, mOrthoMatrix, sizeof(mOrthoMatrix));
+
+ // Change the ortho projection
+ mat4 ortho;
+ ortho.loadOrtho(0.0f, right - left, bottom - top, 0.0f, 0.0f, 1.0f);
+ ortho.copyTo(mOrthoMatrix);
+
return true;
}
@@ -343,7 +358,7 @@
void OpenGLRenderer::setScissorFromClip() {
const Rect& clip = mSnapshot->getMappedClip();
- glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight());
+ glScissor(clip.left, mSnapshot->height - clip.bottom, clip.getWidth(), clip.getHeight());
}
const Rect& OpenGLRenderer::getClipBounds() {
@@ -381,7 +396,7 @@
///////////////////////////////////////////////////////////////////////////////
void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint) {
- Texture* texture = mTextureCache.get(bitmap);
+ const Texture* texture = mTextureCache.get(bitmap);
int alpha;
SkXfermode::Mode mode;
@@ -391,11 +406,26 @@
alpha / 255.0f, mode, texture->blend, true);
}
+void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint) {
+ Rect r(0.0f, 0.0f, bitmap->width(), bitmap->height());
+ const mat4 transform(*matrix);
+ transform.mapRect(r);
+
+ const Texture* texture = mTextureCache.get(bitmap);
+
+ int alpha;
+ SkXfermode::Mode mode;
+ getAlphaAndMode(paint, &alpha, &mode);
+
+ drawTextureRect(r.left, r.top, r.right, r.bottom, texture->id,
+ alpha / 255.0f, mode, texture->blend, true);
+}
+
void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
float srcLeft, float srcTop, float srcRight, float srcBottom,
float dstLeft, float dstTop, float dstRight, float dstBottom,
- const SkMatrix* matrix, const SkPaint* paint) {
- Texture* texture = mTextureCache.get(bitmap);
+ const SkPaint* paint) {
+ const Texture* texture = mTextureCache.get(bitmap);
int alpha;
SkXfermode::Mode mode;
@@ -411,8 +441,6 @@
resetDrawTextureTexCoords(u1, v1, u2, v2);
- // TODO: implement Matrix
-
drawTextureRect(dstLeft, dstTop, dstRight, dstBottom, texture->id,
alpha / 255.0f, mode, texture->blend, true);
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index a698e79..bd5f84f 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -103,9 +103,9 @@
bool clipRect(float left, float top, float right, float bottom);
void drawBitmap(SkBitmap* bitmap, float left, float top, const SkPaint* paint);
+ void drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix, const SkPaint* paint);
void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop, float srcRight, float srcBottom,
- float dstLeft, float dstTop, float dstRight, float dstBottom,
- const SkMatrix* matrix, const SkPaint* paint);
+ float dstLeft, float dstTop, float dstRight, float dstBottom, const SkPaint* paint);
void drawColor(int color, SkXfermode::Mode mode);
void drawRect(float left, float top, float right, float bottom, const SkPaint* paint);
diff --git a/libs/hwui/Snapshot.h b/libs/hwui/Snapshot.h
index ca91b34..d1809f3 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -51,6 +51,7 @@
* snapshot.
*/
Snapshot(const sp<Snapshot> s):
+ height(s->height),
transform(s->transform),
clipRect(s->clipRect),
flags(kFlagDirtyTransform),
@@ -80,6 +81,10 @@
* a new layer.
*/
kFlagIsLayer = 0x4,
+ /**
+ * Indicates that this snapshot has changed the ortho matrix.
+ */
+ kFlagDirtyOrtho = 0x8,
};
/**
@@ -95,6 +100,11 @@
}
/**
+ * Height of the framebuffer the snapshot is rendering into.
+ */
+ int height;
+
+ /**
* Local transformation. Holds the current translation, scale and
* rotation values.
*/
@@ -141,6 +151,11 @@
*/
SkXfermode::Mode mode;
+ /**
+ * Contains the previous ortho matrix.
+ */
+ float orthoMatrix[16];
+
private:
// Clipping rectangle mapped with the transform
Rect mappedClip;
diff --git a/tests/HwAccelerationTest/res/drawable/sunset1.jpg b/tests/HwAccelerationTest/res/drawable/sunset1.jpg
new file mode 100644
index 0000000..92851f3
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable/sunset1.jpg
Binary files differ
diff --git a/tests/HwAccelerationTest/res/drawable/sunset2.png b/tests/HwAccelerationTest/res/drawable/sunset2.png
new file mode 100644
index 0000000..3258ee7
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable/sunset2.png
Binary files differ