summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Romain Guy <romainguy@google.com> 2010-07-01 11:05:42 -0700
committer Romain Guy <romainguy@google.com> 2010-07-01 15:27:21 -0700
commitf86ef57f8bcd8ba43ce222ec6a8b4f67d3600640 (patch)
tree1ce9f59ca3dab7579b6548861b21dcf2df159815
parent1a3e1056db1deafcc8cdfae3aa36581c70b16cf0 (diff)
Don't use full screen FBOs, this dramatically increase performance.
The next step will be to add an FBO cache to avoid churning memory on every frame we draw. This change also adds support for drawBitmap(Bitmap, Matrix, Paint). Change-Id: I7825cdcf0cad9bffe6219e05d8328a53d4a6e583
-rw-r--r--core/java/android/view/GLES20Canvas.java14
-rw-r--r--core/java/android/view/HardwareRenderer.java39
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp18
-rw-r--r--libs/hwui/OpenGLRenderer.cpp78
-rw-r--r--libs/hwui/OpenGLRenderer.h4
-rw-r--r--libs/hwui/Snapshot.h15
-rw-r--r--tests/HwAccelerationTest/res/drawable/sunset1.jpgbin0 -> 25019 bytes
-rw-r--r--tests/HwAccelerationTest/res/drawable/sunset2.pngbin0 -> 55763 bytes
8 files changed, 108 insertions, 60 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index ccf122120ee8..b46091081c96 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -368,19 +368,19 @@ class GLES20Canvas extends Canvas {
@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 @@ class GLES20Canvas extends Canvas {
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 @@ class GLES20Canvas extends Canvas {
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 a1ee3d3dfba8..d30bce9bb89a 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -413,33 +413,30 @@ abstract class HardwareRenderer {
}
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 @@ abstract class HardwareRenderer {
*/
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 @@ abstract class HardwareRenderer {
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 @@ abstract class HardwareRenderer {
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 cba6ed15e553..89ad53418a24 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -195,13 +195,22 @@ static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject canvas
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 @@ static JNINativeMethod gMethods[] = {
{ "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 091abb058c9e..8b4fb9bca24a 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -111,6 +111,7 @@ void OpenGLRenderer::setViewport(int width, int height) {
mWidth = width;
mHeight = height;
+ mFirstSnapshot.height = height;
}
void OpenGLRenderer::prepare() {
@@ -170,10 +171,15 @@ int OpenGLRenderer::saveSnapshot() {
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 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
// 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, &current->fbo);
glDeleteTextures(1, &current->texture);
}
@@ -268,14 +264,10 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
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 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
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 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top,
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::concatMatrix(SkMatrix* matrix) {
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 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom)
///////////////////////////////////////////////////////////////////////////////
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 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap, float left, float top, const S
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 @@ void OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
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 a698e7979d93..bd5f84fbf83b 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -103,9 +103,9 @@ public:
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 ca91b3437af6..d1809f35e1e0 100644
--- a/libs/hwui/Snapshot.h
+++ b/libs/hwui/Snapshot.h
@@ -51,6 +51,7 @@ public:
* snapshot.
*/
Snapshot(const sp<Snapshot> s):
+ height(s->height),
transform(s->transform),
clipRect(s->clipRect),
flags(kFlagDirtyTransform),
@@ -80,6 +81,10 @@ public:
* a new layer.
*/
kFlagIsLayer = 0x4,
+ /**
+ * Indicates that this snapshot has changed the ortho matrix.
+ */
+ kFlagDirtyOrtho = 0x8,
};
/**
@@ -95,6 +100,11 @@ public:
}
/**
+ * 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 @@ public:
*/
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 000000000000..92851f3df924
--- /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 000000000000..3258ee745389
--- /dev/null
+++ b/tests/HwAccelerationTest/res/drawable/sunset2.png
Binary files differ