diff options
| -rw-r--r-- | core/java/android/view/GLES20Canvas.java | 14 | ||||
| -rw-r--r-- | core/java/android/view/HardwareRenderer.java | 39 | ||||
| -rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 18 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 78 | ||||
| -rw-r--r-- | libs/hwui/OpenGLRenderer.h | 4 | ||||
| -rw-r--r-- | libs/hwui/Snapshot.h | 15 | ||||
| -rw-r--r-- | tests/HwAccelerationTest/res/drawable/sunset1.jpg | bin | 0 -> 25019 bytes | |||
| -rw-r--r-- | tests/HwAccelerationTest/res/drawable/sunset2.png | bin | 0 -> 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, ¤t->fbo); glDeleteTextures(1, ¤t->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 Binary files differnew file mode 100644 index 000000000000..92851f3df924 --- /dev/null +++ b/tests/HwAccelerationTest/res/drawable/sunset1.jpg diff --git a/tests/HwAccelerationTest/res/drawable/sunset2.png b/tests/HwAccelerationTest/res/drawable/sunset2.png Binary files differnew file mode 100644 index 000000000000..3258ee745389 --- /dev/null +++ b/tests/HwAccelerationTest/res/drawable/sunset2.png |