diff options
author | John Reck <jreck@google.com> | 2014-06-23 13:13:08 -0700 |
---|---|---|
committer | John Reck <jreck@google.com> | 2014-06-23 15:26:49 -0700 |
commit | 3b20251a355c88193c439f928a84ae69483fb488 (patch) | |
tree | 33c878ebacf17cf03d089404474fa66ca041ffb9 | |
parent | 97a6c20a6a52c9429ed2c8837086f3003e5da274 (diff) | |
download | frameworks_base-3b20251a355c88193c439f928a84ae69483fb488.zip frameworks_base-3b20251a355c88193c439f928a84ae69483fb488.tar.gz frameworks_base-3b20251a355c88193c439f928a84ae69483fb488.tar.bz2 |
No-fail invokeFunctor
Bug: 15513308
Bug: 15449247
Change-Id: I13a29f9c8d4975cdda6dcb33b6332c2555ff0f7c
35 files changed, 867 insertions, 645 deletions
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index c0e42a3..cfb4af2 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -387,17 +387,6 @@ public abstract class HardwareRenderer { abstract boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap); /** - * Schedules the functor for execution in either kModeProcess or - * kModeProcessNoContext, depending on whether or not there is an EGLContext. - * - * @param functor The native functor to invoke - * @param waitForCompletion If true, this will not return until the functor - * has invoked. If false, the functor may be invoked - * asynchronously. - */ - abstract void invokeFunctor(long functor, boolean waitForCompletion); - - /** * Initializes the hardware renderer for the specified surface and setup the * renderer for drawing, if needed. This is invoked when the ViewAncestor has * potentially lost the hardware renderer. The hardware renderer should be diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index a2ff0fb..5c67da9 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -80,13 +80,13 @@ public class ThreadedRenderer extends HardwareRenderer { private boolean mProfilingEnabled; ThreadedRenderer(Context context, boolean translucent) { - AtlasInitializer.sInstance.init(context); - long rootNodePtr = nCreateRootRenderNode(); mRootNode = RenderNode.adopt(rootNodePtr); mRootNode.setClipToBounds(false); mNativeProxy = nCreateProxy(translucent, rootNodePtr); + AtlasInitializer.sInstance.init(context, mNativeProxy); + // Setup timing mChoreographer = Choreographer.getInstance(); nSetFrameInterval(mNativeProxy, mChoreographer.getFrameIntervalNanos()); @@ -259,9 +259,8 @@ public class ThreadedRenderer extends HardwareRenderer { } } - @Override - void invokeFunctor(long functor, boolean waitForCompletion) { - nInvokeFunctor(mNativeProxy, functor, waitForCompletion); + static void invokeFunctor(long functor, boolean waitForCompletion) { + nInvokeFunctor(functor, waitForCompletion); } @Override @@ -342,7 +341,7 @@ public class ThreadedRenderer extends HardwareRenderer { private AtlasInitializer() {} - synchronized void init(Context context) { + synchronized void init(Context context, long renderProxy) { if (mInitialized) return; IBinder binder = ServiceManager.getService("assetatlas"); if (binder == null) return; @@ -356,7 +355,7 @@ public class ThreadedRenderer extends HardwareRenderer { if (map != null) { // TODO Remove after fixing b/15425820 validateMap(context, map); - nSetAtlas(buffer, map); + nSetAtlas(renderProxy, buffer, map); mInitialized = true; } // If IAssetAtlas is not the same class as the IBinder @@ -399,7 +398,7 @@ public class ThreadedRenderer extends HardwareRenderer { static native void setupShadersDiskCache(String cacheFile); - private static native void nSetAtlas(GraphicBuffer buffer, long[] map); + private static native void nSetAtlas(long nativeProxy, GraphicBuffer buffer, long[] map); private static native long nCreateRootRenderNode(); private static native long nCreateProxy(boolean translucent, long rootRenderNode); @@ -419,7 +418,7 @@ public class ThreadedRenderer extends HardwareRenderer { private static native void nRunWithGlContext(long nativeProxy, Runnable runnable); private static native void nDestroyCanvasAndSurface(long nativeProxy); - private static native void nInvokeFunctor(long nativeProxy, long functor, boolean waitForCompletion); + private static native void nInvokeFunctor(long functor, boolean waitForCompletion); private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height); private static native long nCreateTextureLayer(long nativeProxy); diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index f574042..329efcc 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -661,11 +661,19 @@ public final class ViewRootImpl implements ViewParent, } } + /** + * Schedules the functor for execution in either kModeProcess or + * kModeProcessNoContext, depending on whether or not there is an EGLContext. + * + * @param functor The native functor to invoke + * @param waitForCompletion If true, this will not return until the functor + * has invoked. If false, the functor may be invoked + * asynchronously. + */ public boolean invokeFunctor(long functor, boolean waitForCompletion) { - if (mAttachInfo.mHardwareRenderer == null) { - return false; - } - mAttachInfo.mHardwareRenderer.invokeFunctor(functor, waitForCompletion); + ThreadedRenderer.invokeFunctor(functor, waitForCompletion); + // TODO: Remove the return value. This is here for compatibility + // with current webview, which expects a boolean return true; } diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index 329e371..ca8fb30 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -20,15 +20,10 @@ #include "GraphicsJNI.h" #include <nativehelper/JNIHelp.h> -#include "android_view_GraphicBuffer.h" - #include <android_runtime/AndroidRuntime.h> -#include <android_runtime/android_graphics_SurfaceTexture.h> #include <androidfw/ResourceTypes.h> -#include <gui/GLConsumer.h> - #include <private/hwui/DrawGlInfo.h> #include <cutils/properties.h> @@ -43,9 +38,6 @@ #include <SkXfermode.h> #include <DisplayListRenderer.h> -#include <LayerRenderer.h> -#include <OpenGLRenderer.h> -#include <Stencil.h> #include <Rect.h> #include <RenderNode.h> #include <CanvasProperty.h> @@ -64,7 +56,7 @@ namespace android { using namespace uirenderer; /** - * Note: OpenGLRenderer JNI layer is generated and compiled only on supported + * Note: DisplayListRenderer JNI layer is generated and compiled only on supported * devices. This means all the logic must be compiled only when the * preprocessor variable USE_OPENGL_RENDERER is defined. */ @@ -96,8 +88,8 @@ static struct { static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz, jlong rendererPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); - RENDERER_LOGD("Destroy OpenGLRenderer"); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); + RENDERER_LOGD("Destroy DisplayListRenderer"); delete renderer; } @@ -107,26 +99,26 @@ static void android_view_GLES20Canvas_destroyRenderer(JNIEnv* env, jobject clazz static void android_view_GLES20Canvas_setViewport(JNIEnv* env, jobject clazz, jlong rendererPtr, jint width, jint height) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); renderer->setViewport(width, height); } static int android_view_GLES20Canvas_prepare(JNIEnv* env, jobject clazz, jlong rendererPtr, jboolean opaque) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); return renderer->prepare(opaque); } static int android_view_GLES20Canvas_prepareDirty(JNIEnv* env, jobject clazz, jlong rendererPtr, jint left, jint top, jint right, jint bottom, jboolean opaque) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); return renderer->prepareDirty(left, top, right, bottom, opaque); } static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz, jlong rendererPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); renderer->finish(); } @@ -154,7 +146,7 @@ static void android_view_GLES20Canvas_setProperty(JNIEnv* env, static jint android_view_GLES20Canvas_callDrawGLFunction(JNIEnv* env, jobject clazz, jlong rendererPtr, jlong functorPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); Functor* functor = reinterpret_cast<Functor*>(functorPtr); android::uirenderer::Rect dirty; return renderer->callDrawGLFunction(functor, dirty); @@ -178,25 +170,25 @@ static jint android_view_GLES20Canvas_getMaxTextureHeight(JNIEnv* env, jobject c static jint android_view_GLES20Canvas_save(JNIEnv* env, jobject clazz, jlong rendererPtr, jint flags) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); return renderer->save(flags); } static jint android_view_GLES20Canvas_getSaveCount(JNIEnv* env, jobject clazz, jlong rendererPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); return renderer->getSaveCount(); } static void android_view_GLES20Canvas_restore(JNIEnv* env, jobject clazz, jlong rendererPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); renderer->restore(); } static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz, jlong rendererPtr, jint saveCount) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); renderer->restoreToCount(saveCount); } @@ -207,14 +199,14 @@ static void android_view_GLES20Canvas_restoreToCount(JNIEnv* env, jobject clazz, static jint android_view_GLES20Canvas_saveLayer(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom, jlong paintPtr, jint saveFlags) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); return renderer->saveLayer(left, top, right, bottom, paint, saveFlags); } static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz, jlong rendererPtr, jlong paintPtr, jint saveFlags) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds()); return renderer->saveLayer(bounds.left, bounds.top, bounds.right, bounds.bottom, @@ -224,13 +216,13 @@ static jint android_view_GLES20Canvas_saveLayerClip(JNIEnv* env, jobject clazz, static jint android_view_GLES20Canvas_saveLayerAlpha(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom, jint alpha, jint saveFlags) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); return renderer->saveLayerAlpha(left, top, right, bottom, alpha, saveFlags); } static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject clazz, jlong rendererPtr, jint alpha, jint saveFlags) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds()); return renderer->saveLayerAlpha(bounds.left, bounds.top, bounds.right, bounds.bottom, alpha, saveFlags); @@ -242,7 +234,7 @@ static jint android_view_GLES20Canvas_saveLayerAlphaClip(JNIEnv* env, jobject cl static jboolean android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); const bool result = renderer->quickRejectConservative(left, top, right, bottom); return result ? JNI_TRUE : JNI_FALSE; } @@ -250,7 +242,7 @@ static jboolean android_view_GLES20Canvas_quickReject(JNIEnv* env, jobject clazz static jboolean android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom, jint op) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); const bool result = renderer->clipRect(left, top, right, bottom, static_cast<SkRegion::Op>(op)); return result ? JNI_TRUE : JNI_FALSE; @@ -259,7 +251,7 @@ static jboolean android_view_GLES20Canvas_clipRectF(JNIEnv* env, jobject clazz, static jboolean android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz, jlong rendererPtr, jint left, jint top, jint right, jint bottom, jint op) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); const bool result = renderer->clipRect(float(left), float(top), float(right), float(bottom), static_cast<SkRegion::Op>(op)); @@ -268,7 +260,7 @@ static jboolean android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz, static jboolean android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz, jlong rendererPtr, jlong pathPtr, jint op) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkPath* path = reinterpret_cast<SkPath*>(pathPtr); const bool result = renderer->clipPath(path, static_cast<SkRegion::Op>(op)); return result ? JNI_TRUE : JNI_FALSE; @@ -276,7 +268,7 @@ static jboolean android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz, static jboolean android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz, jlong rendererPtr, jlong regionPtr, jint op) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr); const bool result = renderer->clipRegion(region, static_cast<SkRegion::Op>(op)); return result ? JNI_TRUE : JNI_FALSE; @@ -284,7 +276,7 @@ static jboolean android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz, static jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz, jlong rendererPtr, jobject rect) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); const android::uirenderer::Rect& bounds(renderer->getLocalClipBounds()); env->CallVoidMethod(rect, gRectClassInfo.set, @@ -299,45 +291,45 @@ static jboolean android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject cla static void android_view_GLES20Canvas_translate(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloat dx, jfloat dy) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); renderer->translate(dx, dy); } static void android_view_GLES20Canvas_rotate(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloat degrees) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); renderer->rotate(degrees); } static void android_view_GLES20Canvas_scale(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloat sx, jfloat sy) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); renderer->scale(sx, sy); } static void android_view_GLES20Canvas_skew(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloat sx, jfloat sy) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); renderer->skew(sx, sy); } static void android_view_GLES20Canvas_setMatrix(JNIEnv* env, jobject clazz, jlong rendererPtr, jlong matrixPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr); renderer->setMatrix(matrix ? *matrix : SkMatrix::I()); } static void android_view_GLES20Canvas_getMatrix(JNIEnv* env, jobject clazz, jlong rendererPtr, jlong matrixPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr); renderer->getMatrix(matrix); } static void android_view_GLES20Canvas_concatMatrix(JNIEnv* env, jobject clazz, jlong rendererPtr, jlong matrixPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr); renderer->concatMatrix(*matrix); } @@ -353,7 +345,7 @@ static void android_view_GLES20Canvas_drawBitmap(JNIEnv* env, jobject clazz, // This object allows the renderer to allocate a global JNI ref to the buffer object. JavaHeapBitmapRef bitmapRef(env, bitmap, buffer); - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawBitmap(bitmap, left, top, paint); } @@ -366,7 +358,7 @@ static void android_view_GLES20Canvas_drawBitmapRect(JNIEnv* env, jobject clazz, // This object allows the renderer to allocate a global JNI ref to the buffer object. JavaHeapBitmapRef bitmapRef(env, bitmap, buffer); - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom, dstLeft, dstTop, dstRight, dstBottom, paint); @@ -379,7 +371,7 @@ static void android_view_GLES20Canvas_drawBitmapMatrix(JNIEnv* env, jobject claz // This object allows the renderer to allocate a global JNI ref to the buffer object. JavaHeapBitmapRef bitmapRef(env, bitmap, buffer); - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkMatrix* matrix = reinterpret_cast<SkMatrix*>(matrixPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawBitmap(bitmap, *matrix, paint); @@ -402,7 +394,7 @@ static void android_view_GLES20Canvas_drawBitmapData(JNIEnv* env, jobject clazz, return; } - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawBitmapData(bitmap, left, top, paint); @@ -423,7 +415,7 @@ static void android_view_GLES20Canvas_drawBitmapMesh(JNIEnv* env, jobject clazz, jfloat* verticesArray = vertices ? env->GetFloatArrayElements(vertices, NULL) + offset : NULL; jint* colorsArray = colors ? env->GetIntArrayElements(colors, NULL) + colorOffset : NULL; - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawBitmapMesh(bitmap, meshWidth, meshHeight, verticesArray, colorsArray, paint); @@ -438,7 +430,7 @@ static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz, // This object allows the renderer to allocate a global JNI ref to the buffer object. JavaHeapBitmapRef bitmapRef(env, bitmap, buffer); - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); Res_png_9patch* patch = reinterpret_cast<Res_png_9patch*>(patchPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawPatch(bitmap, patch, left, top, right, bottom, paint); @@ -446,14 +438,14 @@ static void android_view_GLES20Canvas_drawPatch(JNIEnv* env, jobject clazz, static void android_view_GLES20Canvas_drawColor(JNIEnv* env, jobject clazz, jlong rendererPtr, jint color, jint mode) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); renderer->drawColor(color, static_cast<SkXfermode::Mode>(mode)); } static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom, jlong paintPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawRect(left, top, right, bottom, paint); } @@ -461,21 +453,21 @@ static void android_view_GLES20Canvas_drawRect(JNIEnv* env, jobject clazz, static void android_view_GLES20Canvas_drawRoundRect(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom, jfloat rx, jfloat ry, jlong paintPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawRoundRect(left, top, right, bottom, rx, ry, paint); } static void android_view_GLES20Canvas_drawCircle(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloat x, jfloat y, jfloat radius, jlong paintPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawCircle(x, y, radius, paint); } static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz, jlong rendererPtr, jlong xPropPtr, jlong yPropPtr, jlong radiusPropPtr, jlong paintPropPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); CanvasPropertyPrimitive* xProp = reinterpret_cast<CanvasPropertyPrimitive*>(xPropPtr); CanvasPropertyPrimitive* yProp = reinterpret_cast<CanvasPropertyPrimitive*>(yPropPtr); CanvasPropertyPrimitive* radiusProp = reinterpret_cast<CanvasPropertyPrimitive*>(radiusPropPtr); @@ -486,7 +478,7 @@ static void android_view_GLES20Canvas_drawCircleProps(JNIEnv* env, jobject clazz static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom, jlong paintPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawOval(left, top, right, bottom, paint); } @@ -494,14 +486,14 @@ static void android_view_GLES20Canvas_drawOval(JNIEnv* env, jobject clazz, static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloat left, jfloat top, jfloat right, jfloat bottom, jfloat startAngle, jfloat sweepAngle, jboolean useCenter, jlong paintPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint); } static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject clazz, jlong rendererPtr, jlong regionPtr, jlong paintPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkRegion* region = reinterpret_cast<SkRegion*>(regionPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); if (paint->getStyle() != SkPaint::kFill_Style || @@ -531,7 +523,7 @@ static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject cla static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); jfloat* storage = env->GetFloatArrayElements(points, NULL); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawPoints(storage + offset, count, paint); @@ -540,7 +532,7 @@ static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz, static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject clazz, jlong rendererPtr, jlong pathPtr, jlong paintPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); SkPath* path = reinterpret_cast<SkPath*>(pathPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawPath(path, paint); @@ -548,7 +540,7 @@ static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject clazz, static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz, jlong rendererPtr, jfloatArray points, jint offset, jint count, jlong paintPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); jfloat* storage = env->GetFloatArrayElements(points, NULL); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); renderer->drawLines(storage + offset, count, paint); @@ -561,13 +553,13 @@ static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject clazz, static void android_view_GLES20Canvas_setupPaintFilter(JNIEnv* env, jobject clazz, jlong rendererPtr, jint clearBits, jint setBits) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); renderer->setupPaintFilter(clearBits, setBits); } static void android_view_GLES20Canvas_resetPaintFilter(JNIEnv* env, jobject clazz, jlong rendererPtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); renderer->resetPaintFilter(); } @@ -594,7 +586,7 @@ static float xOffsetForTextAlign(SkPaint* paint, float totalAdvance) { class RenderTextFunctor { public: - RenderTextFunctor(const Layout& layout, OpenGLRenderer* renderer, jfloat x, jfloat y, + RenderTextFunctor(const Layout& layout, DisplayListRenderer* renderer, jfloat x, jfloat y, SkPaint* paint, uint16_t* glyphs, float* pos, float totalAdvance, uirenderer::Rect& bounds) : layout(layout), renderer(renderer), x(x), y(y), paint(paint), glyphs(glyphs), @@ -612,7 +604,7 @@ public: } private: const Layout& layout; - OpenGLRenderer* renderer; + DisplayListRenderer* renderer; jfloat x; jfloat y; SkPaint* paint; @@ -622,7 +614,7 @@ private: uirenderer::Rect& bounds; }; -static void renderTextLayout(OpenGLRenderer* renderer, Layout* layout, +static void renderTextLayout(DisplayListRenderer* renderer, Layout* layout, jfloat x, jfloat y, SkPaint* paint) { size_t nGlyphs = layout->nGlyphs(); float* pos = new float[nGlyphs * 2]; @@ -640,7 +632,7 @@ static void renderTextLayout(OpenGLRenderer* renderer, Layout* layout, } #endif -static void renderText(OpenGLRenderer* renderer, const jchar* text, int count, +static void renderText(DisplayListRenderer* renderer, const jchar* text, int count, jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) { #ifdef USE_MINIKIN Layout layout; @@ -672,7 +664,7 @@ static void renderText(OpenGLRenderer* renderer, const jchar* text, int count, #ifdef USE_MINIKIN class RenderTextOnPathFunctor { public: - RenderTextOnPathFunctor(const Layout& layout, OpenGLRenderer* renderer, float hOffset, + RenderTextOnPathFunctor(const Layout& layout, DisplayListRenderer* renderer, float hOffset, float vOffset, SkPaint* paint, SkPath* path) : layout(layout), renderer(renderer), hOffset(hOffset), vOffset(vOffset), paint(paint), path(path) { @@ -688,7 +680,7 @@ public: } private: const Layout& layout; - OpenGLRenderer* renderer; + DisplayListRenderer* renderer; float hOffset; float vOffset; SkPaint* paint; @@ -696,7 +688,7 @@ private: }; #endif -static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int count, +static void renderTextOnPath(DisplayListRenderer* renderer, const jchar* text, int count, SkPath* path, jfloat hOffset, jfloat vOffset, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) { #ifdef USE_MINIKIN @@ -724,7 +716,7 @@ static void renderTextOnPath(OpenGLRenderer* renderer, const jchar* text, int co #endif } -static void renderTextRun(OpenGLRenderer* renderer, const jchar* text, +static void renderTextRun(DisplayListRenderer* renderer, const jchar* text, jint start, jint count, jint contextCount, jfloat x, jfloat y, int bidiFlags, SkPaint* paint, TypefaceImpl* typeface) { #ifdef USE_MINIKIN @@ -757,7 +749,7 @@ static void renderTextRun(OpenGLRenderer* renderer, const jchar* text, static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz, jlong rendererPtr, jcharArray text, jint index, jint count, jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); jchar* textArray = env->GetCharArrayElements(text, NULL); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr); @@ -769,7 +761,7 @@ static void android_view_GLES20Canvas_drawTextArray(JNIEnv* env, jobject clazz, static void android_view_GLES20Canvas_drawText(JNIEnv* env, jobject clazz, jlong rendererPtr, jstring text, jint start, jint end, jfloat x, jfloat y, jint bidiFlags, jlong paintPtr, jlong typefacePtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); const jchar* textArray = env->GetStringChars(text, NULL); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr); @@ -782,7 +774,7 @@ static void android_view_GLES20Canvas_drawTextArrayOnPath(JNIEnv* env, jobject c jlong rendererPtr, jcharArray text, jint index, jint count, jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr, jlong typefacePtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); jchar* textArray = env->GetCharArrayElements(text, NULL); SkPath* path = reinterpret_cast<SkPath*>(pathPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); @@ -797,7 +789,7 @@ static void android_view_GLES20Canvas_drawTextOnPath(JNIEnv* env, jobject clazz, jlong rendererPtr, jstring text, jint start, jint end, jlong pathPtr, jfloat hOffset, jfloat vOffset, jint bidiFlags, jlong paintPtr, jlong typefacePtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); const jchar* textArray = env->GetStringChars(text, NULL); SkPath* path = reinterpret_cast<SkPath*>(pathPtr); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); @@ -812,7 +804,7 @@ static void android_view_GLES20Canvas_drawTextRunArray(JNIEnv* env, jobject claz jlong rendererPtr, jcharArray text, jint index, jint count, jint contextIndex, jint contextCount, jfloat x, jfloat y, jboolean isRtl, jlong paintPtr, jlong typefacePtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); jchar* textArray = env->GetCharArrayElements(text, NULL); SkPaint* paint = reinterpret_cast<SkPaint*>(paintPtr); TypefaceImpl* typeface = reinterpret_cast<TypefaceImpl*>(typefacePtr); @@ -827,7 +819,7 @@ static void android_view_GLES20Canvas_drawTextRun(JNIEnv* env, jobject clazz, jlong rendererPtr, jstring text, jint start, jint end, jint contextStart, int contextEnd, jfloat x, jfloat y, jboolean isRtl, jlong paintPtr, jlong typefacePtr) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); const jchar* textArray = env->GetStringChars(text, NULL); jint count = end - start; jint contextCount = contextEnd - contextStart; @@ -857,7 +849,7 @@ static jlong android_view_GLES20Canvas_createDisplayListRenderer(JNIEnv* env, jo static jint android_view_GLES20Canvas_drawRenderNode(JNIEnv* env, jobject clazz, jlong rendererPtr, jlong renderNodePtr, jobject dirty, jint flags) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); RenderNode* renderNode = reinterpret_cast<RenderNode*>(renderNodePtr); android::uirenderer::Rect bounds; status_t status = renderer->drawRenderNode(renderNode, bounds, flags); @@ -874,7 +866,7 @@ static jint android_view_GLES20Canvas_drawRenderNode(JNIEnv* env, static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz, jlong rendererPtr, jlong layerPtr, jfloat x, jfloat y) { - OpenGLRenderer* renderer = reinterpret_cast<OpenGLRenderer*>(rendererPtr); + DisplayListRenderer* renderer = reinterpret_cast<DisplayListRenderer*>(rendererPtr); Layer* layer = reinterpret_cast<Layer*>(layerPtr); renderer->drawLayer(layer, x, y); } diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index 2b94b65..3e62d0b 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -76,26 +76,6 @@ private: jobject mRunnable; }; -class SetAtlasTask : public RenderTask { -public: - SetAtlasTask(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) - : mBuffer(buffer) - , mMap(map) - , mMapSize(size) { - } - - virtual void run() { - CanvasContext::setTextureAtlas(mBuffer, mMap, mMapSize); - mMap = 0; - delete this; - } - -private: - sp<GraphicBuffer> mBuffer; - int64_t* mMap; - size_t mMapSize; -}; - class OnFinishedEvent { public: OnFinishedEvent(BaseRenderNodeAnimator* animator, AnimationListener* listener) @@ -193,7 +173,7 @@ private: }; static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz, - jobject graphicBuffer, jlongArray atlasMapArray) { + jlong proxyPtr, jobject graphicBuffer, jlongArray atlasMapArray) { sp<GraphicBuffer> buffer = graphicBufferForJavaObject(env, graphicBuffer); jsize len = env->GetArrayLength(atlasMapArray); if (len <= 0) { @@ -203,8 +183,8 @@ static void android_view_ThreadedRenderer_setAtlas(JNIEnv* env, jobject clazz, int64_t* map = new int64_t[len]; env->GetLongArrayRegion(atlasMapArray, 0, len, map); - SetAtlasTask* task = new SetAtlasTask(buffer, map, len); - RenderThread::getInstance().queue(task); + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + proxy->setTextureAtlas(buffer, map, len); } static jlong android_view_ThreadedRenderer_createRootRenderNode(JNIEnv* env, jobject clazz) { @@ -291,10 +271,9 @@ static void android_view_ThreadedRenderer_destroyCanvasAndSurface(JNIEnv* env, j } static void android_view_ThreadedRenderer_invokeFunctor(JNIEnv* env, jobject clazz, - jlong proxyPtr, jlong functorPtr, jboolean waitForCompletion) { - RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + jlong functorPtr, jboolean waitForCompletion) { Functor* functor = reinterpret_cast<Functor*>(functorPtr); - proxy->invokeFunctor(functor, waitForCompletion); + RenderProxy::invokeFunctor(functor, waitForCompletion); } static void android_view_ThreadedRenderer_runWithGlContext(JNIEnv* env, jobject clazz, @@ -387,7 +366,7 @@ const char* const kClassPathName = "android/view/ThreadedRenderer"; static JNINativeMethod gMethods[] = { #ifdef USE_OPENGL_RENDERER - { "nSetAtlas", "(Landroid/view/GraphicBuffer;[J)V", (void*) android_view_ThreadedRenderer_setAtlas }, + { "nSetAtlas", "(JLandroid/view/GraphicBuffer;[J)V", (void*) android_view_ThreadedRenderer_setAtlas }, { "nCreateRootRenderNode", "()J", (void*) android_view_ThreadedRenderer_createRootRenderNode }, { "nCreateProxy", "(ZJ)J", (void*) android_view_ThreadedRenderer_createProxy }, { "nDeleteProxy", "(J)V", (void*) android_view_ThreadedRenderer_deleteProxy }, @@ -400,7 +379,7 @@ static JNINativeMethod gMethods[] = { { "nSetOpaque", "(JZ)V", (void*) android_view_ThreadedRenderer_setOpaque }, { "nSyncAndDrawFrame", "(JJJF)I", (void*) android_view_ThreadedRenderer_syncAndDrawFrame }, { "nDestroyCanvasAndSurface", "(J)V", (void*) android_view_ThreadedRenderer_destroyCanvasAndSurface }, - { "nInvokeFunctor", "(JJZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, + { "nInvokeFunctor", "(JZ)V", (void*) android_view_ThreadedRenderer_invokeFunctor }, { "nRunWithGlContext", "(JLjava/lang/Runnable;)V", (void*) android_view_ThreadedRenderer_runWithGlContext }, { "nCreateDisplayListLayer", "(JII)J", (void*) android_view_ThreadedRenderer_createDisplayListLayer }, { "nCreateTextureLayer", "(J)J", (void*) android_view_ThreadedRenderer_createTextureLayer }, diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 02e85fe..95d8a97 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -45,6 +45,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) RenderBufferCache.cpp \ RenderNode.cpp \ RenderProperties.cpp \ + RenderState.cpp \ ResourceCache.cpp \ ShadowTessellator.cpp \ SkiaShader.cpp \ @@ -61,6 +62,7 @@ ifeq ($(USE_OPENGL_RENDERER),true) LOCAL_SRC_FILES += \ renderthread/CanvasContext.cpp \ renderthread/DrawFrameTask.cpp \ + renderthread/EglManager.cpp \ renderthread/RenderProxy.cpp \ renderthread/RenderTask.cpp \ renderthread/RenderThread.cpp \ diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp index 937bf8d..a998594 100644 --- a/libs/hwui/DeferredDisplayList.cpp +++ b/libs/hwui/DeferredDisplayList.cpp @@ -500,7 +500,7 @@ void DeferredDisplayList::addRestoreToCount(OpenGLRenderer& renderer, StateOp* o void DeferredDisplayList::addDrawOp(OpenGLRenderer& renderer, DrawOp* op) { /* 1: op calculates local bounds */ DeferredDisplayState* const state = createState(); - if (op->getLocalBounds(renderer.getDrawModifiers(), state->mBounds)) { + if (op->getLocalBounds(state->mBounds)) { if (state->mBounds.isEmpty()) { // valid empty bounds, don't bother deferring tryRecycleState(state); diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h index 48489c2..8a015b2 100644 --- a/libs/hwui/DeferredDisplayList.h +++ b/libs/hwui/DeferredDisplayList.h @@ -38,7 +38,6 @@ class SaveLayerOp; class StateOp; class DeferredDisplayState; -class OpenGLRenderer; class Batch; class DrawBatch; diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h index 5082271..c76bd5e 100644 --- a/libs/hwui/DeferredLayerUpdater.h +++ b/libs/hwui/DeferredLayerUpdater.h @@ -23,7 +23,6 @@ #include <utils/StrongPointer.h> #include "Layer.h" -#include "OpenGLRenderer.h" #include "Rect.h" #include "RenderNode.h" diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 811af39..5ed04a0 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -171,7 +171,7 @@ public: * * returns true if bounds exist */ - virtual bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) { + virtual bool getLocalBounds(Rect& localBounds) { return false; } @@ -253,7 +253,7 @@ public: // default empty constructor for bounds, to be overridden in child constructor body DrawBoundedOp(const SkPaint* paint): DrawOp(paint) { } - bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) { + bool getLocalBounds(Rect& localBounds) { localBounds.set(mLocalBounds); OpenGLRenderer::TextShadow textShadow; if (OpenGLRenderer::getTextShadow(mPaint, &textShadow)) { @@ -1029,7 +1029,7 @@ public: DrawStrokableOp(float left, float top, float right, float bottom, const SkPaint* paint) : DrawBoundedOp(left, top, right, bottom, paint) {}; - bool getLocalBounds(const DrawModifiers& drawModifiers, Rect& localBounds) { + bool getLocalBounds(Rect& localBounds) { localBounds.set(mLocalBounds); if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) { localBounds.outset(strokeWidthOutset()); @@ -1399,7 +1399,7 @@ public: virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty) { Rect bounds; - getLocalBounds(renderer.getDrawModifiers(), bounds); + getLocalBounds(bounds); return renderer.drawText(mText, mBytesCount, mCount, mX, mY, mPositions, getPaint(renderer), mTotalAdvance, bounds); } diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index b6d3f4b..7789358 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -425,7 +425,7 @@ void DisplayListRenderer::addStateOp(StateOp* op) { void DisplayListRenderer::addDrawOp(DrawOp* op) { Rect localBounds; - if (op->getLocalBounds(mDrawModifiers, localBounds)) { + if (op->getLocalBounds(localBounds)) { bool rejected = quickRejectConservative(localBounds.left, localBounds.top, localBounds.right, localBounds.bottom); op->setQuickRejected(rejected); diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 1de656e..8ca9af1 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -23,7 +23,6 @@ #include <cutils/compiler.h> #include "DisplayListLogBuffer.h" -#include "OpenGLRenderer.h" #include "RenderNode.h" namespace android { @@ -53,12 +52,12 @@ class StateOp; /** * Records drawing commands in a display list for later playback into an OpenGLRenderer. */ -class DisplayListRenderer: public OpenGLRenderer { +class ANDROID_API DisplayListRenderer: public StatefulBaseRenderer { public: - ANDROID_API DisplayListRenderer(); + DisplayListRenderer(); virtual ~DisplayListRenderer(); - ANDROID_API DisplayListData* finishRecording(); + DisplayListData* finishRecording(); virtual bool isRecording() const { return true; } @@ -81,7 +80,7 @@ public: const SkPaint* paint, int flags); // Matrix - virtual void translate(float dx, float dy, float dz); + virtual void translate(float dx, float dy, float dz = 0.0f); virtual void rotate(float degrees); virtual void scale(float sx, float sy); virtual void skew(float sx, float sy); @@ -98,6 +97,10 @@ public: virtual void resetPaintFilter(); virtual void setupPaintFilter(int clearBits, int setBits); + bool isCurrentTransformSimple() { + return currentTransform()->isSimple(); + } + // ---------------------------------------------------------------------------- // Canvas draw operations // ---------------------------------------------------------------------------- @@ -152,11 +155,6 @@ public: // TODO: rename for consistency virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty); -protected: - // NOTE: must override these to avoid calling into super class, which calls GL. These may be - // removed once DisplayListRenderer no longer inherits from OpenGLRenderer - virtual void onViewportInitialized() {}; - virtual void onSnapshotRestored() {}; private: void insertRestoreToCount(); diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index b6414e5..73a4da5 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -20,6 +20,7 @@ #include "Caches.h" #include "DeferredDisplayList.h" +#include "RenderState.h" #include "Layer.h" #include "LayerRenderer.h" #include "OpenGLRenderer.h" @@ -28,8 +29,10 @@ namespace android { namespace uirenderer { -Layer::Layer(const uint32_t layerWidth, const uint32_t layerHeight): - caches(Caches::getInstance()), texture(caches) { +Layer::Layer(RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight) + : caches(Caches::getInstance()) + , renderState(renderState) + , texture(caches) { mesh = NULL; meshElementCount = 0; cacheable = true; @@ -72,7 +75,7 @@ uint32_t Layer::computeIdealHeight(uint32_t layerHeight) { void Layer::requireRenderer() { if (!renderer) { - renderer = new LayerRenderer(this); + renderer = new LayerRenderer(renderState, this); renderer->initProperties(); } } @@ -123,18 +126,17 @@ bool Layer::resize(const uint32_t width, const uint32_t height) { void Layer::removeFbo(bool flush) { if (stencil) { - GLuint previousFbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); - if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo); + GLuint previousFbo = renderState.getFramebuffer(); + renderState.bindFramebuffer(fbo); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0); - if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); + renderState.bindFramebuffer(previousFbo); caches.renderBufferCache.put(stencil); stencil = NULL; } if (fbo) { - if (flush) LayerRenderer::flushLayer(this); + if (flush) LayerRenderer::flushLayer(renderState, this); // If put fails the cache will delete the FBO caches.fboCache.put(fbo); fbo = 0; diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 741f4c3..0bf05d0 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -43,6 +43,7 @@ namespace uirenderer { // Forward declarations class Caches; +class RenderState; class OpenGLRenderer; class RenderNode; class DeferredDisplayList; @@ -53,7 +54,7 @@ class DeferStateStruct; */ class Layer { public: - Layer(const uint32_t layerWidth, const uint32_t layerHeight); + Layer(RenderState& renderState, const uint32_t layerWidth, const uint32_t layerHeight); ~Layer(); static uint32_t computeIdealWidth(uint32_t layerWidth); @@ -306,6 +307,8 @@ private: Caches& caches; + RenderState& renderState; + /** * Name of the FBO used to render the layer. If the name is 0 * this layer is not backed by an FBO, but a simple texture. diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index 6be0146..13869aa 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -91,7 +91,7 @@ void LayerCache::clear() { mCache.clear(); } -Layer* LayerCache::get(const uint32_t width, const uint32_t height) { +Layer* LayerCache::get(RenderState& renderState, const uint32_t width, const uint32_t height) { Layer* layer = NULL; LayerEntry entry(width, height); @@ -108,7 +108,7 @@ Layer* LayerCache::get(const uint32_t width, const uint32_t height) { } else { LAYER_LOGD("Creating new layer %dx%d", entry.mWidth, entry.mHeight); - layer = new Layer(entry.mWidth, entry.mHeight); + layer = new Layer(renderState, entry.mWidth, entry.mHeight); layer->setBlend(true); layer->setEmpty(true); layer->setFbo(0); diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h index 221bfe0..1b0fc2c 100644 --- a/libs/hwui/LayerCache.h +++ b/libs/hwui/LayerCache.h @@ -24,6 +24,8 @@ namespace android { namespace uirenderer { +class RenderState; + /////////////////////////////////////////////////////////////////////////////// // Defines /////////////////////////////////////////////////////////////////////////////// @@ -55,7 +57,7 @@ public: * @param width The desired width of the layer * @param height The desired height of the layer */ - Layer* get(const uint32_t width, const uint32_t height); + Layer* get(RenderState& renderState, const uint32_t width, const uint32_t height); /** * Adds the layer to the cache. The layer will not be added if there is diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index a5fd375..873baf5 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -20,6 +20,7 @@ #include <private/hwui/DrawGlInfo.h> +#include "RenderState.h" #include "LayerCache.h" #include "LayerRenderer.h" #include "Matrix.h" @@ -33,7 +34,9 @@ namespace uirenderer { // Rendering /////////////////////////////////////////////////////////////////////////////// -LayerRenderer::LayerRenderer(Layer* layer): mLayer(layer) { +LayerRenderer::LayerRenderer(RenderState& renderState, Layer* layer) + : OpenGLRenderer(renderState) + , mLayer(layer) { } LayerRenderer::~LayerRenderer() { @@ -43,7 +46,7 @@ status_t LayerRenderer::prepareDirty(float left, float top, float right, float b bool opaque) { LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo()); - glBindFramebuffer(GL_FRAMEBUFFER, mLayer->getFbo()); + renderState().bindFramebuffer(mLayer->getFbo()); const float width = mLayer->layer.getWidth(); const float height = mLayer->layer.getHeight(); @@ -180,7 +183,7 @@ void LayerRenderer::generateMesh() { // Layers management /////////////////////////////////////////////////////////////////////////////// -Layer* LayerRenderer::createRenderLayer(uint32_t width, uint32_t height) { +Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width, uint32_t height) { LAYER_RENDERER_LOGD("Requesting new render layer %dx%d", width, height); Caches& caches = Caches::getInstance(); @@ -191,7 +194,7 @@ Layer* LayerRenderer::createRenderLayer(uint32_t width, uint32_t height) { } caches.activeTexture(0); - Layer* layer = caches.layerCache.get(width, height); + Layer* layer = caches.layerCache.get(renderState, width, height); if (!layer) { ALOGW("Could not obtain a layer"); return NULL; @@ -221,10 +224,9 @@ Layer* LayerRenderer::createRenderLayer(uint32_t width, uint32_t height) { layer->setDirty(true); layer->region.clear(); - GLuint previousFbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); + GLuint previousFbo = renderState.getFramebuffer(); - glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo()); + renderState.bindFramebuffer(layer->getFbo()); layer->bindTexture(); // Initialize the texture if needed @@ -235,7 +237,7 @@ Layer* LayerRenderer::createRenderLayer(uint32_t width, uint32_t height) { // This should only happen if we run out of memory if (glGetError() != GL_NO_ERROR) { ALOGE("Could not allocate texture for layer (fbo=%d %dx%d)", fbo, width, height); - glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); + renderState.bindFramebuffer(previousFbo); caches.resourceCache.decrementRefcount(layer); return NULL; } @@ -244,7 +246,7 @@ Layer* LayerRenderer::createRenderLayer(uint32_t width, uint32_t height) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, layer->getTexture(), 0); - glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); + renderState.bindFramebuffer(previousFbo); return layer; } @@ -265,10 +267,10 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) { return true; } -Layer* LayerRenderer::createTextureLayer() { +Layer* LayerRenderer::createTextureLayer(RenderState& renderState) { LAYER_RENDERER_LOGD("Creating new texture layer"); - Layer* layer = new Layer(0, 0); + Layer* layer = new Layer(renderState, 0, 0); layer->setCacheable(false); layer->setTextureLayer(true); layer->setEmpty(true); @@ -332,7 +334,7 @@ void LayerRenderer::destroyLayerDeferred(Layer* layer) { } } -void LayerRenderer::flushLayer(Layer* layer) { +void LayerRenderer::flushLayer(RenderState& renderState, Layer* layer) { #ifdef GL_EXT_discard_framebuffer if (!layer) return; @@ -341,20 +343,23 @@ void LayerRenderer::flushLayer(Layer* layer) { // If possible, discard any enqueud operations on deferred // rendering architectures if (Extensions::getInstance().hasDiscardFramebuffer()) { - GLuint previousFbo; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); - if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, fbo); + GLuint previousFbo = renderState.getFramebuffer(); + if (fbo != previousFbo) { + renderState.bindFramebuffer(fbo); + } const GLenum attachments[] = { GL_COLOR_ATTACHMENT0 }; glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, attachments); - if (fbo != previousFbo) glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); + if (fbo != previousFbo) { + renderState.bindFramebuffer(previousFbo); + } } } #endif } -bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { +bool LayerRenderer::copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap) { Caches& caches = Caches::getInstance(); if (layer && bitmap->width() <= caches.maxTextureSize && bitmap->height() <= caches.maxTextureSize) { @@ -369,7 +374,8 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { GLuint texture; GLuint previousFbo; - GLuint previousViewport[4]; + GLsizei previousViewportWidth; + GLsizei previousViewportHeight; GLenum format; GLenum type; @@ -404,9 +410,9 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { layer->setAlpha(255, SkXfermode::kSrc_Mode); layer->setFbo(fbo); - glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo); - glGetIntegerv(GL_VIEWPORT, (GLint*) &previousViewport); - glBindFramebuffer(GL_FRAMEBUFFER, fbo); + previousFbo = renderState.getFramebuffer(); + renderState.getViewport(&previousViewportWidth, &previousViewportHeight); + renderState.bindFramebuffer(fbo); glGenTextures(1, &texture); if ((error = glGetError()) != GL_NO_ERROR) goto error; @@ -431,7 +437,7 @@ bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) { if ((error = glGetError()) != GL_NO_ERROR) goto error; { - LayerRenderer renderer(layer); + LayerRenderer renderer(renderState, layer); renderer.setViewport(bitmap->width(), bitmap->height()); renderer.OpenGLRenderer::prepareDirty(0.0f, 0.0f, bitmap->width(), bitmap->height(), !layer->isBlend()); @@ -471,13 +477,12 @@ error: } #endif - glBindFramebuffer(GL_FRAMEBUFFER, previousFbo); + renderState.bindFramebuffer(previousFbo); layer->setAlpha(alpha, mode); layer->setFbo(previousLayerFbo); caches.deleteTexture(texture); caches.fboCache.put(fbo); - glViewport(previousViewport[0], previousViewport[1], - previousViewport[2], previousViewport[3]); + renderState.setViewport(previousViewportWidth, previousViewportHeight); return status; } diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index e79e7b8..9202e49 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -27,6 +27,8 @@ namespace android { namespace uirenderer { +class RenderState; + /////////////////////////////////////////////////////////////////////////////// // Defines /////////////////////////////////////////////////////////////////////////////// @@ -44,7 +46,7 @@ namespace uirenderer { class LayerRenderer: public OpenGLRenderer { public: - ANDROID_API LayerRenderer(Layer* layer); + LayerRenderer(RenderState& renderState, Layer* layer); virtual ~LayerRenderer(); virtual void onViewportInitialized(int width, int height) { /* do nothing */ } @@ -52,16 +54,16 @@ public: virtual status_t clear(float left, float top, float right, float bottom, bool opaque); virtual void finish(); - ANDROID_API static Layer* createTextureLayer(); - ANDROID_API static Layer* createRenderLayer(uint32_t width, uint32_t height); - ANDROID_API static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height); - ANDROID_API static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, + static Layer* createTextureLayer(RenderState& renderState); + static Layer* createRenderLayer(RenderState& renderState, uint32_t width, uint32_t height); + static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height); + static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform); - ANDROID_API static void destroyLayer(Layer* layer); + static void destroyLayer(Layer* layer); ANDROID_API static void destroyLayerDeferred(Layer* layer); - ANDROID_API static bool copyLayer(Layer* layer, SkBitmap* bitmap); + static bool copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap); - static void flushLayer(Layer* layer); + static void flushLayer(RenderState& renderState, Layer* layer); protected: virtual void ensureStencilBuffer(); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index afb65a6..ede89d7 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -35,6 +35,7 @@ #include "DeferredDisplayList.h" #include "DisplayListRenderer.h" #include "Fence.h" +#include "RenderState.h" #include "PathTessellator.h" #include "Properties.h" #include "ShadowTessellator.h" @@ -129,8 +130,10 @@ static inline T min(T a, T b) { // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// -OpenGLRenderer::OpenGLRenderer(): - mCaches(Caches::getInstance()), mExtensions(Extensions::getInstance()) { +OpenGLRenderer::OpenGLRenderer(RenderState& renderState) + : mCaches(Caches::getInstance()) + , mExtensions(Extensions::getInstance()) + , mRenderState(renderState) { // *set* draw modifiers to be 0 memset(&mDrawModifiers, 0, sizeof(mDrawModifiers)); mDrawModifiers.mOverrideLayerAlpha = 1.0f; @@ -187,7 +190,7 @@ status_t OpenGLRenderer::startFrame() { discardFramebuffer(mTilingClip.left, mTilingClip.top, mTilingClip.right, mTilingClip.bottom); - glViewport(0, 0, getWidth(), getHeight()); + mRenderState.setViewport(getWidth(), getHeight()); // Functors break the tiling extension in pretty spectacular ways // This ensures we don't use tiling when a functor is going to be @@ -311,46 +314,9 @@ void OpenGLRenderer::finish() { mFrameStarted = false; } -void OpenGLRenderer::interrupt() { - if (mCaches.currentProgram) { - if (mCaches.currentProgram->isInUse()) { - mCaches.currentProgram->remove(); - mCaches.currentProgram = NULL; - } - } - mCaches.resetActiveTexture(); - mCaches.unbindMeshBuffer(); - mCaches.unbindIndicesBuffer(); - mCaches.resetVertexPointers(); - mCaches.disableTexCoordsVertexArray(); - debugOverdraw(false, false); -} - -void OpenGLRenderer::resume() { - const Snapshot* snapshot = currentSnapshot(); - glViewport(0, 0, getViewportWidth(), getViewportHeight()); - glBindFramebuffer(GL_FRAMEBUFFER, snapshot->fbo); - debugOverdraw(true, false); - - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - - mCaches.scissorEnabled = glIsEnabled(GL_SCISSOR_TEST); - mCaches.enableScissor(); - mCaches.resetScissor(); - dirtyClip(); - - mCaches.activeTexture(0); - mCaches.resetBoundTextures(); - - mCaches.blend = true; - glEnable(GL_BLEND); - glBlendFunc(mCaches.lastSrcMode, mCaches.lastDstMode); - glBlendEquation(GL_FUNC_ADD); -} - void OpenGLRenderer::resumeAfterLayer() { - glViewport(0, 0, getViewportWidth(), getViewportHeight()); - glBindFramebuffer(GL_FRAMEBUFFER, currentSnapshot()->fbo); + mRenderState.setViewport(getViewportWidth(), getViewportHeight()); + mRenderState.bindFramebuffer(currentSnapshot()->fbo); debugOverdraw(true, false); mCaches.resetScissor(); @@ -379,20 +345,19 @@ status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) { info.height = getViewportHeight(); currentTransform()->copyTo(&info.transform[0]); - bool dirtyClip = mDirtyClip; + bool prevDirtyClip = mDirtyClip; // setup GL state for functor if (mDirtyClip) { setStencilFromClip(); // can issue draws, so must precede enableScissor()/interrupt() } - if (mCaches.enableScissor() || dirtyClip) { + if (mCaches.enableScissor() || prevDirtyClip) { setScissorFromClip(); } - interrupt(); - // call functor immediately after GL state setup - (*functor)(DrawGlInfo::kModeDraw, &info); + mRenderState.invokeFunctor(functor, DrawGlInfo::kModeDraw, &info); + // Scissor may have been modified, reset dirty clip + dirtyClip(); - resume(); return DrawGlInfo::kStatusDrew; } @@ -413,17 +378,7 @@ void OpenGLRenderer::endMark() const { } void OpenGLRenderer::debugOverdraw(bool enable, bool clear) { - if (mCaches.debugOverdraw && getTargetFbo() == 0) { - if (clear) { - mCaches.disableScissor(); - mCaches.stencil.clear(); - } - if (enable) { - mCaches.stencil.enableDebugWrite(); - } else { - mCaches.stencil.disable(); - } - } + mRenderState.debugOverdraw(enable, clear); } void OpenGLRenderer::renderOverdraw() { @@ -528,7 +483,7 @@ void OpenGLRenderer::updateLayers() { if (CC_UNLIKELY(mCaches.drawDeferDisabled)) { mLayerUpdates.clear(); - glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo()); + mRenderState.bindFramebuffer(getTargetFbo()); } endMark(); } @@ -556,7 +511,7 @@ void OpenGLRenderer::flushLayers() { } mLayerUpdates.clear(); - glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo()); + mRenderState.bindFramebuffer(getTargetFbo()); endMark(); } @@ -620,7 +575,7 @@ void OpenGLRenderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& bool restoreLayer = removed.flags & Snapshot::kFlagIsLayer; if (restoreViewport) { - glViewport(0, 0, getViewportWidth(), getViewportHeight()); + mRenderState.setViewport(getViewportWidth(), getViewportHeight()); } if (restoreClip) { @@ -791,7 +746,7 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto } mCaches.activeTexture(0); - Layer* layer = mCaches.layerCache.get(bounds.getWidth(), bounds.getHeight()); + Layer* layer = mCaches.layerCache.get(mRenderState, bounds.getWidth(), bounds.getHeight()); if (!layer) { return false; } @@ -853,7 +808,7 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip) { endTiling(); debugOverdraw(false, false); // Bind texture to FBO - glBindFramebuffer(GL_FRAMEBUFFER, layer->getFbo()); + mRenderState.bindFramebuffer(layer->getFbo()); layer->bindTexture(); // Initialize the texture if needed @@ -876,7 +831,7 @@ bool OpenGLRenderer::createFboLayer(Layer* layer, Rect& bounds, Rect& clip) { dirtyClip(); // Change the ortho projection - glViewport(0, 0, bounds.getWidth(), bounds.getHeight()); + mRenderState.setViewport(bounds.getWidth(), bounds.getHeight()); return true; } @@ -907,7 +862,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto layer->removeFbo(false); // Unbind current FBO and restore previous one - glBindFramebuffer(GL_FRAMEBUFFER, restored.fbo); + mRenderState.bindFramebuffer(restored.fbo); debugOverdraw(true, false); startTilingCurrentClip(); diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 066b267..4ff5780 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -57,6 +57,7 @@ namespace android { namespace uirenderer { class DeferredDisplayState; +class RenderState; class RenderNode; class TextSetupFunctor; class VertexBuffer; @@ -119,33 +120,31 @@ enum ModelViewMode { */ class OpenGLRenderer : public StatefulBaseRenderer { public: - ANDROID_API OpenGLRenderer(); + OpenGLRenderer(RenderState& renderState); virtual ~OpenGLRenderer(); - ANDROID_API void initProperties(); + void initProperties(); virtual void onViewportInitialized(); virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque); virtual void finish(); - virtual void interrupt(); - virtual void resume(); - ANDROID_API void setCountOverdrawEnabled(bool enabled) { + void setCountOverdrawEnabled(bool enabled) { mCountOverdraw = enabled; } - ANDROID_API float getOverdraw() { + float getOverdraw() { return mCountOverdraw ? mOverdraw : 0.0f; } virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty); - ANDROID_API void pushLayerUpdate(Layer* layer); - ANDROID_API void cancelLayerUpdate(Layer* layer); - ANDROID_API void clearLayerUpdates(); - ANDROID_API void flushLayerUpdates(); + void pushLayerUpdate(Layer* layer); + void cancelLayerUpdate(Layer* layer); + void clearLayerUpdates(); + void flushLayerUpdates(); - ANDROID_API virtual int saveLayer(float left, float top, float right, float bottom, + virtual int saveLayer(float left, float top, float right, float bottom, const SkPaint* paint, int flags) { return saveLayer(left, top, right, bottom, paint, flags, NULL); } @@ -231,7 +230,7 @@ public: const DrawModifiers& getDrawModifiers() { return mDrawModifiers; } void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; } - ANDROID_API bool isCurrentTransformSimple() { + bool isCurrentTransformSimple() { return currentTransform()->isSimple(); } @@ -474,6 +473,8 @@ protected: return false; } + inline RenderState& renderState() { return mRenderState; } + private: /** * Discards the content of the framebuffer if supported by the driver. @@ -977,6 +978,7 @@ private: // Various caches Caches& mCaches; Extensions& mExtensions; + RenderState& mRenderState; // List of rectangles to clear after saveLayer() is invoked Vector<Rect*> mLayers; @@ -1012,7 +1014,6 @@ private: bool mSkipOutlineClip; - friend class DisplayListRenderer; friend class Layer; friend class TextSetupFunctor; friend class DrawBitmapOp; diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index e8f2dd2..131384a 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -155,7 +155,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { } if (!mLayer) { - mLayer = LayerRenderer::createRenderLayer(getWidth(), getHeight()); + mLayer = LayerRenderer::createRenderLayer(info.renderState, getWidth(), getHeight()); applyLayerPropertiesToLayer(info); damageSelf(info); } else if (mLayer->layer.getWidth() != getWidth() || mLayer->layer.getHeight() != getHeight()) { @@ -267,7 +267,7 @@ void RenderNode::pushStagingDisplayListChanges(TreeInfo& info) { mNeedsDisplayListDataSync = false; // Do a push pass on the old tree to handle freeing DisplayListData // that are no longer used - TreeInfo oldTreeInfo(TreeInfo::MODE_MAYBE_DETACHING); + TreeInfo oldTreeInfo(TreeInfo::MODE_MAYBE_DETACHING, info.renderState); oldTreeInfo.damageAccumulator = info.damageAccumulator; prepareSubTree(oldTreeInfo, mDisplayListData); delete mDisplayListData; diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index 2fa6078..3980dad 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -55,7 +55,6 @@ class SkRegion; namespace android { namespace uirenderer { -class DeferredDisplayList; class DisplayListOp; class DisplayListRenderer; class OpenGLRenderer; diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp new file mode 100644 index 0000000..97f379d --- /dev/null +++ b/libs/hwui/RenderState.cpp @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "RenderState.h" + +namespace android { +namespace uirenderer { + +RenderState::RenderState() + : mCaches(NULL) + , mViewportWidth(0) + , mViewportHeight(0) + , mFramebuffer(0) { +} + +RenderState::~RenderState() { +} + +void RenderState::onGLContextCreated() { + // This is delayed because the first access of Caches makes GL calls + mCaches = &Caches::getInstance(); + mCaches->init(); +} + +void RenderState::setViewport(GLsizei width, GLsizei height) { + mViewportWidth = width; + mViewportHeight = height; + glViewport(0, 0, mViewportWidth, mViewportHeight); +} + + +void RenderState::getViewport(GLsizei* outWidth, GLsizei* outHeight) { + *outWidth = mViewportWidth; + *outHeight = mViewportHeight; +} + +void RenderState::bindFramebuffer(GLuint fbo) { + if (mFramebuffer != fbo) { + mFramebuffer = fbo; + glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); + } +} + +void RenderState::invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info) { + interruptForFunctorInvoke(); + (*functor)(mode, info); + resumeFromFunctorInvoke(); +} + +void RenderState::interruptForFunctorInvoke() { + if (mCaches->currentProgram) { + if (mCaches->currentProgram->isInUse()) { + mCaches->currentProgram->remove(); + mCaches->currentProgram = NULL; + } + } + mCaches->resetActiveTexture(); + mCaches->unbindMeshBuffer(); + mCaches->unbindIndicesBuffer(); + mCaches->resetVertexPointers(); + mCaches->disableTexCoordsVertexArray(); + debugOverdraw(false, false); +} + +void RenderState::resumeFromFunctorInvoke() { + glViewport(0, 0, mViewportWidth, mViewportHeight); + glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); + debugOverdraw(false, false); + + glClearColor(0.0f, 0.0f, 0.0f, 0.0f); + + mCaches->scissorEnabled = glIsEnabled(GL_SCISSOR_TEST); + mCaches->enableScissor(); + mCaches->resetScissor(); + + mCaches->activeTexture(0); + mCaches->resetBoundTextures(); + + mCaches->blend = true; + glEnable(GL_BLEND); + glBlendFunc(mCaches->lastSrcMode, mCaches->lastDstMode); + glBlendEquation(GL_FUNC_ADD); +} + +void RenderState::debugOverdraw(bool enable, bool clear) { + if (mCaches->debugOverdraw && mFramebuffer == 0) { + if (clear) { + mCaches->disableScissor(); + mCaches->stencil.clear(); + } + if (enable) { + mCaches->stencil.enableDebugWrite(); + } else { + mCaches->stencil.disable(); + } + } +} + +} /* namespace uirenderer */ +} /* namespace android */ diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h new file mode 100644 index 0000000..f7116e2 --- /dev/null +++ b/libs/hwui/RenderState.h @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef RENDERSTATE_H +#define RENDERSTATE_H + +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include <private/hwui/DrawGlInfo.h> + +#include "Caches.h" +#include "utils/Macros.h" + +namespace android { +namespace uirenderer { + +namespace renderthread { +class RenderThread; +} + +// TODO: Replace Cache's GL state tracking with this. For now it's more a thin +// wrapper of Caches for users to migrate to. +class RenderState { + PREVENT_COPY_AND_ASSIGN(RenderState); +public: + void onGLContextCreated(); + + void setViewport(GLsizei width, GLsizei height); + void getViewport(GLsizei* outWidth, GLsizei* outHeight); + + void bindFramebuffer(GLuint fbo); + GLint getFramebuffer() { return mFramebuffer; } + + void invokeFunctor(Functor* functor, DrawGlInfo::Mode mode, DrawGlInfo* info); + + void debugOverdraw(bool enable, bool clear); + +private: + friend class renderthread::RenderThread; + + void interruptForFunctorInvoke(); + void resumeFromFunctorInvoke(); + + RenderState(); + ~RenderState(); + + Caches* mCaches; + + GLsizei mViewportWidth; + GLsizei mViewportHeight; + GLuint mFramebuffer; +}; + +} /* namespace uirenderer */ +} /* namespace android */ + +#endif /* RENDERSTATE_H */ diff --git a/libs/hwui/Renderer.h b/libs/hwui/Renderer.h index d68b932..2ec99c9 100644 --- a/libs/hwui/Renderer.h +++ b/libs/hwui/Renderer.h @@ -129,21 +129,6 @@ public: */ virtual void finish() = 0; - /** - * This method must be invoked before handing control over to a draw functor. - * See callDrawGLFunction() for instance. - * - * This command must not be recorded inside display lists. - */ - virtual void interrupt() = 0; - - /** - * This method must be invoked after getting control back from a draw functor. - * - * This command must not be recorded inside display lists. - */ - virtual void resume() = 0; - // ---------------------------------------------------------------------------- // Canvas state operations // ---------------------------------------------------------------------------- diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h index f67e434..249e525 100644 --- a/libs/hwui/TreeInfo.h +++ b/libs/hwui/TreeInfo.h @@ -29,6 +29,7 @@ namespace uirenderer { class BaseRenderNodeAnimator; class AnimationListener; class OpenGLRenderer; +class RenderState; class AnimationHook { public: @@ -67,14 +68,15 @@ public: // TODO: TRIM_MEMORY? }; - explicit TreeInfo(TraversalMode mode) + explicit TreeInfo(TraversalMode mode, RenderState& renderState) : mode(mode) , frameTimeMs(0) , animationHook(NULL) , prepareTextures(mode == MODE_FULL) , damageAccumulator(NullDamageAccumulator::instance()) - , renderer(0) - , errorHandler(0) + , renderState(renderState) + , renderer(NULL) + , errorHandler(NULL) {} const TraversalMode mode; @@ -85,6 +87,7 @@ public: bool prepareTextures; // Must not be null IDamageAccumulator* damageAccumulator; + RenderState& renderState; // The renderer that will be drawing the next frame. Use this to push any // layer updates or similar. May be NULL. OpenGLRenderer* renderer; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index eab9810..fe4edf8 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -18,332 +18,31 @@ #include "CanvasContext.h" -#include <cutils/properties.h> #include <private/hwui/DrawGlInfo.h> #include <strings.h> +#include "EglManager.h" #include "RenderThread.h" #include "../Caches.h" #include "../DeferredLayerUpdater.h" +#include "../RenderState.h" #include "../LayerRenderer.h" #include "../OpenGLRenderer.h" #include "../Stencil.h" -#define PROPERTY_RENDER_DIRTY_REGIONS "debug.hwui.render_dirty_regions" -#define GLES_VERSION 2 - -// Android-specific addition that is used to show when frames began in systrace -EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface); - namespace android { namespace uirenderer { namespace renderthread { -#define ERROR_CASE(x) case x: return #x; -static const char* egl_error_str(EGLint error) { - switch (error) { - ERROR_CASE(EGL_SUCCESS) - ERROR_CASE(EGL_NOT_INITIALIZED) - ERROR_CASE(EGL_BAD_ACCESS) - ERROR_CASE(EGL_BAD_ALLOC) - ERROR_CASE(EGL_BAD_ATTRIBUTE) - ERROR_CASE(EGL_BAD_CONFIG) - ERROR_CASE(EGL_BAD_CONTEXT) - ERROR_CASE(EGL_BAD_CURRENT_SURFACE) - ERROR_CASE(EGL_BAD_DISPLAY) - ERROR_CASE(EGL_BAD_MATCH) - ERROR_CASE(EGL_BAD_NATIVE_PIXMAP) - ERROR_CASE(EGL_BAD_NATIVE_WINDOW) - ERROR_CASE(EGL_BAD_PARAMETER) - ERROR_CASE(EGL_BAD_SURFACE) - ERROR_CASE(EGL_CONTEXT_LOST) - default: - return "Unknown error"; - } -} -static const char* egl_error_str() { - return egl_error_str(eglGetError()); -} - -static bool load_dirty_regions_property() { - char buf[PROPERTY_VALUE_MAX]; - int len = property_get(PROPERTY_RENDER_DIRTY_REGIONS, buf, "true"); - return !strncasecmp("true", buf, len); -} - -// This class contains the shared global EGL objects, such as EGLDisplay -// and EGLConfig, which are re-used by CanvasContext -class GlobalContext { -public: - static GlobalContext* get(); - - // Returns true on success, false on failure - void initialize(); - - bool hasContext(); - - void usePBufferSurface(); - EGLSurface createSurface(EGLNativeWindowType window); - void destroySurface(EGLSurface surface); - - void destroy(); - - bool isCurrent(EGLSurface surface) { return mCurrentSurface == surface; } - // Returns true if the current surface changed, false if it was already current - bool makeCurrent(EGLSurface surface); - void beginFrame(EGLSurface surface, EGLint* width, EGLint* height); - void swapBuffers(EGLSurface surface); - - bool enableDirtyRegions(EGLSurface surface); - - void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize); - -private: - GlobalContext(); - // GlobalContext is never destroyed, method is purposely not implemented - ~GlobalContext(); - - void loadConfig(); - void createContext(); - void initAtlas(); - - static GlobalContext* sContext; - - EGLDisplay mEglDisplay; - EGLConfig mEglConfig; - EGLContext mEglContext; - EGLSurface mPBufferSurface; - - const bool mRequestDirtyRegions; - bool mCanSetDirtyRegions; - - EGLSurface mCurrentSurface; - - sp<GraphicBuffer> mAtlasBuffer; - int64_t* mAtlasMap; - size_t mAtlasMapSize; -}; - -GlobalContext* GlobalContext::sContext = 0; - -GlobalContext* GlobalContext::get() { - if (!sContext) { - sContext = new GlobalContext(); - } - return sContext; -} - -GlobalContext::GlobalContext() - : mEglDisplay(EGL_NO_DISPLAY) - , mEglConfig(0) - , mEglContext(EGL_NO_CONTEXT) - , mPBufferSurface(EGL_NO_SURFACE) - , mRequestDirtyRegions(load_dirty_regions_property()) - , mCurrentSurface(EGL_NO_SURFACE) - , mAtlasMap(NULL) - , mAtlasMapSize(0) { - mCanSetDirtyRegions = mRequestDirtyRegions; - ALOGD("Render dirty regions requested: %s", mRequestDirtyRegions ? "true" : "false"); -} - -void GlobalContext::initialize() { - if (hasContext()) return; - - mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); - LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, - "Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str()); - - EGLint major, minor; - LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE, - "Failed to initialize display %p! err=%s", mEglDisplay, egl_error_str()); - - ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor); - - loadConfig(); - createContext(); - usePBufferSurface(); - Caches::getInstance().init(); - initAtlas(); -} - -bool GlobalContext::hasContext() { - return mEglDisplay != EGL_NO_DISPLAY; -} - -void GlobalContext::loadConfig() { - EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0; - EGLint attribs[] = { - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, - EGL_RED_SIZE, 8, - EGL_GREEN_SIZE, 8, - EGL_BLUE_SIZE, 8, - EGL_ALPHA_SIZE, 8, - EGL_DEPTH_SIZE, 0, - EGL_CONFIG_CAVEAT, EGL_NONE, - EGL_STENCIL_SIZE, Stencil::getStencilSize(), - EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior, - EGL_NONE - }; - - EGLint num_configs = 1; - if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs) - || num_configs != 1) { - // Failed to get a valid config - if (mCanSetDirtyRegions) { - ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without..."); - // Try again without dirty regions enabled - mCanSetDirtyRegions = false; - loadConfig(); - } else { - LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str()); - } - } -} - -void GlobalContext::createContext() { - EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE }; - mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs); - LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT, - "Failed to create context, error = %s", egl_error_str()); -} - -void GlobalContext::setTextureAtlas(const sp<GraphicBuffer>& buffer, - int64_t* map, size_t mapSize) { - - // Already initialized - if (mAtlasBuffer.get()) { - ALOGW("Multiple calls to setTextureAtlas!"); - delete map; - return; - } - - mAtlasBuffer = buffer; - mAtlasMap = map; - mAtlasMapSize = mapSize; - - if (hasContext()) { - usePBufferSurface(); - initAtlas(); - } -} - -void GlobalContext::initAtlas() { - if (mAtlasBuffer.get()) { - Caches::getInstance().assetAtlas.init(mAtlasBuffer, mAtlasMap, mAtlasMapSize); - } -} - -void GlobalContext::usePBufferSurface() { - LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, - "usePBufferSurface() called on uninitialized GlobalContext!"); - - if (mPBufferSurface == EGL_NO_SURFACE) { - EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; - mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs); - } - makeCurrent(mPBufferSurface); -} - -EGLSurface GlobalContext::createSurface(EGLNativeWindowType window) { - initialize(); - return eglCreateWindowSurface(mEglDisplay, mEglConfig, window, NULL); -} - -void GlobalContext::destroySurface(EGLSurface surface) { - if (isCurrent(surface)) { - makeCurrent(EGL_NO_SURFACE); - } - if (!eglDestroySurface(mEglDisplay, surface)) { - ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str()); - } -} - -void GlobalContext::destroy() { - if (mEglDisplay == EGL_NO_DISPLAY) return; - - usePBufferSurface(); - if (Caches::hasInstance()) { - Caches::getInstance().terminate(); - } - - eglDestroyContext(mEglDisplay, mEglContext); - eglDestroySurface(mEglDisplay, mPBufferSurface); - eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglTerminate(mEglDisplay); - eglReleaseThread(); - - mEglDisplay = EGL_NO_DISPLAY; - mEglContext = EGL_NO_CONTEXT; - mPBufferSurface = EGL_NO_SURFACE; - mCurrentSurface = EGL_NO_SURFACE; -} - -bool GlobalContext::makeCurrent(EGLSurface surface) { - if (isCurrent(surface)) return false; - - if (surface == EGL_NO_SURFACE) { - // If we are setting EGL_NO_SURFACE we don't care about any of the potential - // return errors, which would only happen if mEglDisplay had already been - // destroyed in which case the current context is already NO_CONTEXT - eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - } else if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) { - LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s", - (void*)surface, egl_error_str()); - } - mCurrentSurface = surface; - return true; -} - -void GlobalContext::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) { - LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE, - "Tried to beginFrame on EGL_NO_SURFACE!"); - makeCurrent(surface); - if (width) { - eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width); - } - if (height) { - eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height); - } - eglBeginFrame(mEglDisplay, surface); -} - -void GlobalContext::swapBuffers(EGLSurface surface) { - eglSwapBuffers(mEglDisplay, surface); - EGLint err = eglGetError(); - LOG_ALWAYS_FATAL_IF(err != EGL_SUCCESS, - "Encountered EGL error %d %s during rendering", err, egl_error_str(err)); -} - -bool GlobalContext::enableDirtyRegions(EGLSurface surface) { - if (!mRequestDirtyRegions) return false; - - if (mCanSetDirtyRegions) { - if (!eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) { - ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s", - (void*) surface, egl_error_str()); - return false; - } - return true; - } - // Perhaps it is already enabled? - EGLint value; - if (!eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &value)) { - ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p", - (void*) surface, egl_error_str()); - return false; - } - return value == EGL_BUFFER_PRESERVED; -} - -CanvasContext::CanvasContext(bool translucent, RenderNode* rootRenderNode) - : mRenderThread(RenderThread::getInstance()) +CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode) + : mRenderThread(thread) + , mEglManager(thread.eglManager()) , mEglSurface(EGL_NO_SURFACE) , mDirtyRegionsEnabled(false) , mOpaque(!translucent) - , mCanvas(0) + , mCanvas(NULL) , mHaveNewSurface(false) , mRootRenderNode(rootRenderNode) { - mGlobalContext = GlobalContext::get(); } CanvasContext::~CanvasContext() { @@ -363,19 +62,16 @@ void CanvasContext::setSurface(ANativeWindow* window) { mNativeWindow = window; if (mEglSurface != EGL_NO_SURFACE) { - mGlobalContext->destroySurface(mEglSurface); + mEglManager.destroySurface(mEglSurface); mEglSurface = EGL_NO_SURFACE; } if (window) { - mEglSurface = mGlobalContext->createSurface(window); - LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE, - "Failed to create EGLSurface for window %p, eglErr = %s", - (void*) window, egl_error_str()); + mEglSurface = mEglManager.createSurface(window); } if (mEglSurface != EGL_NO_SURFACE) { - mDirtyRegionsEnabled = mGlobalContext->enableDirtyRegions(mEglSurface); + mDirtyRegionsEnabled = mEglManager.enableDirtyRegions(mEglSurface); mHaveNewSurface = true; makeCurrent(); } else { @@ -384,7 +80,7 @@ void CanvasContext::setSurface(ANativeWindow* window) { } void CanvasContext::swapBuffers() { - mGlobalContext->swapBuffers(mEglSurface); + mEglManager.swapBuffers(mEglSurface); mHaveNewSurface = false; } @@ -397,7 +93,7 @@ void CanvasContext::requireSurface() { bool CanvasContext::initialize(ANativeWindow* window) { if (mCanvas) return false; setSurface(window); - mCanvas = new OpenGLRenderer(); + mCanvas = new OpenGLRenderer(mRenderThread.renderState()); mCanvas->initProperties(); return true; } @@ -424,7 +120,7 @@ void CanvasContext::setOpaque(bool opaque) { void CanvasContext::makeCurrent() { // TODO: Figure out why this workaround is needed, see b/13913604 // In the meantime this matches the behavior of GLRenderer, so it is not a regression - mHaveNewSurface |= mGlobalContext->makeCurrent(mEglSurface); + mHaveNewSurface |= mEglManager.makeCurrent(mEglSurface); } void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater, TreeInfo& info) { @@ -477,7 +173,7 @@ void CanvasContext::draw() { mDamageAccumulator.finish(&dirty); EGLint width, height; - mGlobalContext->beginFrame(mEglSurface, &width, &height); + mEglManager.beginFrame(mEglSurface, &width, &height); if (width != mCanvas->getViewportWidth() || height != mCanvas->getViewportHeight()) { mCanvas->setViewport(width, height); dirty.setEmpty(); @@ -521,7 +217,7 @@ void CanvasContext::doFrame() { profiler().startFrame(); - TreeInfo info(TreeInfo::MODE_RT_ONLY); + TreeInfo info(TreeInfo::MODE_RT_ONLY, mRenderThread.renderState()); info.prepareTextures = false; prepareTree(info); @@ -530,32 +226,26 @@ void CanvasContext::doFrame() { } } -void CanvasContext::invokeFunctor(Functor* functor) { +void CanvasContext::invokeFunctor(RenderThread& thread, Functor* functor) { ATRACE_CALL(); DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext; - if (mGlobalContext->hasContext()) { - requireGlContext(); + if (thread.eglManager().hasEglContext()) { + thread.eglManager().requireGlContext(); mode = DrawGlInfo::kModeProcess; } - if (mCanvas) { - mCanvas->interrupt(); - } - (*functor)(mode, NULL); - if (mCanvas) { - mCanvas->resume(); - } + thread.renderState().invokeFunctor(functor, mode, NULL); } bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { requireGlContext(); - TreeInfo info(TreeInfo::MODE_FULL); + TreeInfo info(TreeInfo::MODE_FULL, mRenderThread.renderState()); layer->apply(info); - return LayerRenderer::copyLayer(layer->backingLayer(), bitmap); + return LayerRenderer::copyLayer(mRenderThread.renderState(), layer->backingLayer(), bitmap); } void CanvasContext::flushCaches(Caches::FlushMode flushMode) { - if (mGlobalContext->hasContext()) { + if (mEglManager.hasEglContext()) { requireGlContext(); Caches::getInstance().flush(flushMode); } @@ -568,25 +258,25 @@ void CanvasContext::runWithGlContext(RenderTask* task) { Layer* CanvasContext::createRenderLayer(int width, int height) { requireSurface(); - return LayerRenderer::createRenderLayer(width, height); + return LayerRenderer::createRenderLayer(mRenderThread.renderState(), width, height); } Layer* CanvasContext::createTextureLayer() { requireSurface(); - return LayerRenderer::createTextureLayer(); + return LayerRenderer::createTextureLayer(mRenderThread.renderState()); } void CanvasContext::requireGlContext() { if (mEglSurface != EGL_NO_SURFACE) { makeCurrent(); } else { - mGlobalContext->usePBufferSurface(); + mEglManager.usePBufferSurface(); } } -void CanvasContext::setTextureAtlas(const sp<GraphicBuffer>& buffer, - int64_t* map, size_t mapSize) { - GlobalContext::get()->setTextureAtlas(buffer, map, mapSize); +void CanvasContext::setTextureAtlas(RenderThread& thread, + const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize) { + thread.eglManager().setTextureAtlas(buffer, map, mapSize); } } /* namespace renderthread */ diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index d926b38..d2ce1a6 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -41,13 +41,13 @@ class Layer; namespace renderthread { -class GlobalContext; +class EglManager; // This per-renderer class manages the bridge between the global EGL context // and the render surface. class CanvasContext : public IFrameCallback { public: - CanvasContext(bool translucent, RenderNode* rootRenderNode); + CanvasContext(RenderThread& thread, bool translucent, RenderNode* rootRenderNode); virtual ~CanvasContext(); bool initialize(ANativeWindow* window); @@ -68,15 +68,15 @@ public: void flushCaches(Caches::FlushMode flushMode); - void invokeFunctor(Functor* functor); + static void invokeFunctor(RenderThread& thread, Functor* functor); void runWithGlContext(RenderTask* task); Layer* createRenderLayer(int width, int height); Layer* createTextureLayer(); - ANDROID_API static void setTextureAtlas(const sp<GraphicBuffer>& buffer, - int64_t* map, size_t mapSize); + ANDROID_API static void setTextureAtlas(RenderThread& thread, + const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize); void notifyFramePending(); @@ -91,8 +91,8 @@ private: void requireGlContext(); - GlobalContext* mGlobalContext; RenderThread& mRenderThread; + EglManager& mEglManager; sp<ANativeWindow> mNativeWindow; EGLSurface mEglSurface; bool mDirtyRegionsEnabled; diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp index 797566f..7d75e0f 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -98,7 +98,7 @@ void DrawFrameTask::run() { bool canUnblockUiThread; bool canDrawThisFrame; { - TreeInfo info(TreeInfo::MODE_FULL); + TreeInfo info(TreeInfo::MODE_FULL, mRenderThread->renderState()); canUnblockUiThread = syncFrameState(info); canDrawThisFrame = info.out.canDrawThisFrame; } diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp new file mode 100644 index 0000000..05ca34d --- /dev/null +++ b/libs/hwui/renderthread/EglManager.cpp @@ -0,0 +1,288 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define LOG_TAG "EglContext" + +#include "EglManager.h" + +#include <cutils/log.h> +#include <cutils/properties.h> + +#include "../RenderState.h" +#include "RenderThread.h" + +#define PROPERTY_RENDER_DIRTY_REGIONS "debug.hwui.render_dirty_regions" +#define GLES_VERSION 2 + +// Android-specific addition that is used to show when frames began in systrace +EGLAPI void EGLAPIENTRY eglBeginFrame(EGLDisplay dpy, EGLSurface surface); + +namespace android { +namespace uirenderer { +namespace renderthread { + +#define ERROR_CASE(x) case x: return #x; +static const char* egl_error_str(EGLint error) { + switch (error) { + ERROR_CASE(EGL_SUCCESS) + ERROR_CASE(EGL_NOT_INITIALIZED) + ERROR_CASE(EGL_BAD_ACCESS) + ERROR_CASE(EGL_BAD_ALLOC) + ERROR_CASE(EGL_BAD_ATTRIBUTE) + ERROR_CASE(EGL_BAD_CONFIG) + ERROR_CASE(EGL_BAD_CONTEXT) + ERROR_CASE(EGL_BAD_CURRENT_SURFACE) + ERROR_CASE(EGL_BAD_DISPLAY) + ERROR_CASE(EGL_BAD_MATCH) + ERROR_CASE(EGL_BAD_NATIVE_PIXMAP) + ERROR_CASE(EGL_BAD_NATIVE_WINDOW) + ERROR_CASE(EGL_BAD_PARAMETER) + ERROR_CASE(EGL_BAD_SURFACE) + ERROR_CASE(EGL_CONTEXT_LOST) + default: + return "Unknown error"; + } +} +static const char* egl_error_str() { + return egl_error_str(eglGetError()); +} + +static bool load_dirty_regions_property() { + char buf[PROPERTY_VALUE_MAX]; + int len = property_get(PROPERTY_RENDER_DIRTY_REGIONS, buf, "true"); + return !strncasecmp("true", buf, len); +} + +EglManager::EglManager(RenderThread& thread) + : mRenderThread(thread) + , mEglDisplay(EGL_NO_DISPLAY) + , mEglConfig(0) + , mEglContext(EGL_NO_CONTEXT) + , mPBufferSurface(EGL_NO_SURFACE) + , mRequestDirtyRegions(load_dirty_regions_property()) + , mCurrentSurface(EGL_NO_SURFACE) + , mAtlasMap(NULL) + , mAtlasMapSize(0) { + mCanSetDirtyRegions = mRequestDirtyRegions; + ALOGD("Render dirty regions requested: %s", mRequestDirtyRegions ? "true" : "false"); +} + +void EglManager::initialize() { + if (hasEglContext()) return; + + mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, + "Failed to get EGL_DEFAULT_DISPLAY! err=%s", egl_error_str()); + + EGLint major, minor; + LOG_ALWAYS_FATAL_IF(eglInitialize(mEglDisplay, &major, &minor) == EGL_FALSE, + "Failed to initialize display %p! err=%s", mEglDisplay, egl_error_str()); + + ALOGI("Initialized EGL, version %d.%d", (int)major, (int)minor); + + loadConfig(); + createContext(); + usePBufferSurface(); + mRenderThread.renderState().onGLContextCreated(); + initAtlas(); +} + +bool EglManager::hasEglContext() { + return mEglDisplay != EGL_NO_DISPLAY; +} + +void EglManager::requireGlContext() { + LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, "No EGL context"); + + // We don't care *WHAT* surface is active, just that one is active to give + // us access to the GL context + if (mCurrentSurface == EGL_NO_SURFACE) { + usePBufferSurface(); + } +} + +void EglManager::loadConfig() { + EGLint swapBehavior = mCanSetDirtyRegions ? EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0; + EGLint attribs[] = { + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_DEPTH_SIZE, 0, + EGL_CONFIG_CAVEAT, EGL_NONE, + EGL_STENCIL_SIZE, Stencil::getStencilSize(), + EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior, + EGL_NONE + }; + + EGLint num_configs = 1; + if (!eglChooseConfig(mEglDisplay, attribs, &mEglConfig, num_configs, &num_configs) + || num_configs != 1) { + // Failed to get a valid config + if (mCanSetDirtyRegions) { + ALOGW("Failed to choose config with EGL_SWAP_BEHAVIOR_PRESERVED, retrying without..."); + // Try again without dirty regions enabled + mCanSetDirtyRegions = false; + loadConfig(); + } else { + LOG_ALWAYS_FATAL("Failed to choose config, error = %s", egl_error_str()); + } + } +} + +void EglManager::createContext() { + EGLint attribs[] = { EGL_CONTEXT_CLIENT_VERSION, GLES_VERSION, EGL_NONE }; + mEglContext = eglCreateContext(mEglDisplay, mEglConfig, EGL_NO_CONTEXT, attribs); + LOG_ALWAYS_FATAL_IF(mEglContext == EGL_NO_CONTEXT, + "Failed to create context, error = %s", egl_error_str()); +} + +void EglManager::setTextureAtlas(const sp<GraphicBuffer>& buffer, + int64_t* map, size_t mapSize) { + + // Already initialized + if (mAtlasBuffer.get()) { + ALOGW("Multiple calls to setTextureAtlas!"); + delete map; + return; + } + + mAtlasBuffer = buffer; + mAtlasMap = map; + mAtlasMapSize = mapSize; + + if (hasEglContext()) { + usePBufferSurface(); + initAtlas(); + } +} + +void EglManager::initAtlas() { + if (mAtlasBuffer.get()) { + Caches::getInstance().assetAtlas.init(mAtlasBuffer, mAtlasMap, mAtlasMapSize); + } +} + +void EglManager::usePBufferSurface() { + LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, + "usePBufferSurface() called on uninitialized GlobalContext!"); + + if (mPBufferSurface == EGL_NO_SURFACE) { + EGLint attribs[] = { EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE }; + mPBufferSurface = eglCreatePbufferSurface(mEglDisplay, mEglConfig, attribs); + } + makeCurrent(mPBufferSurface); +} + +EGLSurface EglManager::createSurface(EGLNativeWindowType window) { + initialize(); + EGLSurface surface = eglCreateWindowSurface(mEglDisplay, mEglConfig, window, NULL); + LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE, + "Failed to create EGLSurface for window %p, eglErr = %s", + (void*) window, egl_error_str()); + return surface; +} + +void EglManager::destroySurface(EGLSurface surface) { + if (isCurrent(surface)) { + makeCurrent(EGL_NO_SURFACE); + } + if (!eglDestroySurface(mEglDisplay, surface)) { + ALOGW("Failed to destroy surface %p, error=%s", (void*)surface, egl_error_str()); + } +} + +void EglManager::destroy() { + if (mEglDisplay == EGL_NO_DISPLAY) return; + + usePBufferSurface(); + if (Caches::hasInstance()) { + Caches::getInstance().terminate(); + } + + eglDestroyContext(mEglDisplay, mEglContext); + eglDestroySurface(mEglDisplay, mPBufferSurface); + eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglTerminate(mEglDisplay); + eglReleaseThread(); + + mEglDisplay = EGL_NO_DISPLAY; + mEglContext = EGL_NO_CONTEXT; + mPBufferSurface = EGL_NO_SURFACE; + mCurrentSurface = EGL_NO_SURFACE; +} + +bool EglManager::makeCurrent(EGLSurface surface) { + if (isCurrent(surface)) return false; + + if (surface == EGL_NO_SURFACE) { + // If we are setting EGL_NO_SURFACE we don't care about any of the potential + // return errors, which would only happen if mEglDisplay had already been + // destroyed in which case the current context is already NO_CONTEXT + eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + } else if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) { + LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s", + (void*)surface, egl_error_str()); + } + mCurrentSurface = surface; + return true; +} + +void EglManager::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) { + LOG_ALWAYS_FATAL_IF(surface == EGL_NO_SURFACE, + "Tried to beginFrame on EGL_NO_SURFACE!"); + makeCurrent(surface); + if (width) { + eglQuerySurface(mEglDisplay, surface, EGL_WIDTH, width); + } + if (height) { + eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height); + } + eglBeginFrame(mEglDisplay, surface); +} + +void EglManager::swapBuffers(EGLSurface surface) { + eglSwapBuffers(mEglDisplay, surface); + EGLint err = eglGetError(); + LOG_ALWAYS_FATAL_IF(err != EGL_SUCCESS, + "Encountered EGL error %d %s during rendering", err, egl_error_str(err)); +} + +bool EglManager::enableDirtyRegions(EGLSurface surface) { + if (!mRequestDirtyRegions) return false; + + if (mCanSetDirtyRegions) { + if (!eglSurfaceAttrib(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED)) { + ALOGW("Failed to set EGL_SWAP_BEHAVIOR on surface %p, error=%s", + (void*) surface, egl_error_str()); + return false; + } + return true; + } + // Perhaps it is already enabled? + EGLint value; + if (!eglQuerySurface(mEglDisplay, surface, EGL_SWAP_BEHAVIOR, &value)) { + ALOGW("Failed to query EGL_SWAP_BEHAVIOR on surface %p, error=%p", + (void*) surface, egl_error_str()); + return false; + } + return value == EGL_BUFFER_PRESERVED; +} + +} /* namespace renderthread */ +} /* namespace uirenderer */ +} /* namespace android */ diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h new file mode 100644 index 0000000..a844cfc --- /dev/null +++ b/libs/hwui/renderthread/EglManager.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef EGLMANAGER_H +#define EGLMANAGER_H + +#include <cutils/compiler.h> +#include <EGL/egl.h> +#include <ui/GraphicBuffer.h> +#include <utils/StrongPointer.h> + +namespace android { +namespace uirenderer { +namespace renderthread { + +class RenderThread; + +// This class contains the shared global EGL objects, such as EGLDisplay +// and EGLConfig, which are re-used by CanvasContext +class EglManager { +public: + // Returns true on success, false on failure + void initialize(); + + bool hasEglContext(); + void requireGlContext(); + + void usePBufferSurface(); + EGLSurface createSurface(EGLNativeWindowType window); + void destroySurface(EGLSurface surface); + + void destroy(); + + bool isCurrent(EGLSurface surface) { return mCurrentSurface == surface; } + // Returns true if the current surface changed, false if it was already current + bool makeCurrent(EGLSurface surface); + void beginFrame(EGLSurface surface, EGLint* width, EGLint* height); + void swapBuffers(EGLSurface surface); + + bool enableDirtyRegions(EGLSurface surface); + + void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t mapSize); + +private: + friend class RenderThread; + + EglManager(RenderThread& thread); + // EglContext is never destroyed, method is purposely not implemented + ~EglManager(); + + void loadConfig(); + void createContext(); + void initAtlas(); + + RenderThread& mRenderThread; + + EGLDisplay mEglDisplay; + EGLConfig mEglConfig; + EGLContext mEglContext; + EGLSurface mPBufferSurface; + + const bool mRequestDirtyRegions; + bool mCanSetDirtyRegions; + + EGLSurface mCurrentSurface; + + sp<GraphicBuffer> mAtlasBuffer; + int64_t* mAtlasMap; + size_t mAtlasMapSize; +}; + +} /* namespace renderthread */ +} /* namespace uirenderer */ +} /* namespace android */ + +#endif /* EGLMANAGER_H */ diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 4988f19..f90a26a 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -52,8 +52,8 @@ namespace renderthread { MethodInvokeRenderTask* task = new MethodInvokeRenderTask((RunnableMethod) Bridge_ ## method); \ ARGS(method) *args = (ARGS(method) *) task->payload() -CREATE_BRIDGE2(createContext, bool translucent, RenderNode* rootRenderNode) { - return new CanvasContext(args->translucent, args->rootRenderNode); +CREATE_BRIDGE3(createContext, RenderThread* thread, bool translucent, RenderNode* rootRenderNode) { + return new CanvasContext(*args->thread, args->translucent, args->rootRenderNode); } RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode) @@ -62,6 +62,7 @@ RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode) SETUP_TASK(createContext); args->translucent = translucent; args->rootRenderNode = rootRenderNode; + args->thread = &mRenderThread; mContext = (CanvasContext*) postAndWait(task); mDrawFrameTask.setContext(&mRenderThread, mContext); } @@ -199,20 +200,29 @@ void RenderProxy::destroyCanvasAndSurface() { postAndWait(task); } -CREATE_BRIDGE2(invokeFunctor, CanvasContext* context, Functor* functor) { - args->context->invokeFunctor(args->functor); +CREATE_BRIDGE2(invokeFunctor, RenderThread* thread, Functor* functor) { + CanvasContext::invokeFunctor(*args->thread, args->functor); return NULL; } void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { ATRACE_CALL(); + RenderThread& thread = RenderThread::getInstance(); SETUP_TASK(invokeFunctor); - args->context = mContext; + args->thread = &thread; args->functor = functor; if (waitForCompletion) { - postAndWait(task); + // waitForCompletion = true is expected to be fairly rare and only + // happen in destruction. Thus it should be fine to temporarily + // create a Mutex + Mutex mutex; + Condition condition; + SignalingRenderTask syncTask(task, &mutex, &condition); + AutoMutex _lock(mutex); + thread.queue(&syncTask); + condition.wait(mutex); } else { - post(task); + thread.queue(task); } } @@ -233,7 +243,7 @@ CREATE_BRIDGE1(destroyLayer, Layer* layer) { return NULL; } -static void enqueueDestroyLayer(Layer* layer) { +void RenderProxy::enqueueDestroyLayer(Layer* layer) { SETUP_TASK(destroyLayer); args->layer = layer; RenderThread::getInstance().queue(task); @@ -242,7 +252,7 @@ static void enqueueDestroyLayer(Layer* layer) { CREATE_BRIDGE3(createDisplayListLayer, CanvasContext* context, int width, int height) { Layer* layer = args->context->createRenderLayer(args->width, args->height); if (!layer) return 0; - return new DeferredLayerUpdater(layer, enqueueDestroyLayer); + return new DeferredLayerUpdater(layer, RenderProxy::enqueueDestroyLayer); } DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) { @@ -258,7 +268,7 @@ DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) CREATE_BRIDGE1(createTextureLayer, CanvasContext* context) { Layer* layer = args->context->createTextureLayer(); if (!layer) return 0; - return new DeferredLayerUpdater(layer, enqueueDestroyLayer); + return new DeferredLayerUpdater(layer, RenderProxy::enqueueDestroyLayer); } DeferredLayerUpdater* RenderProxy::createTextureLayer() { @@ -336,6 +346,22 @@ void RenderProxy::dumpProfileInfo(int fd) { postAndWait(task); } +CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, size_t size) { + CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size); + args->buffer->decStrong(0); + return NULL; +} + +void RenderProxy::setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size) { + SETUP_TASK(setTextureAtlas); + args->thread = &mRenderThread; + args->buffer = buffer.get(); + args->buffer->incStrong(0); + args->map = map; + args->size = size; + post(task); +} + void RenderProxy::post(RenderTask* task) { mRenderThread.queue(task); } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index a95f8f0..df0aff0 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -73,10 +73,11 @@ public: float density); ANDROID_API void destroyCanvasAndSurface(); - ANDROID_API void invokeFunctor(Functor* functor, bool waitForCompletion); + ANDROID_API static void invokeFunctor(Functor* functor, bool waitForCompletion); ANDROID_API void runWithGlContext(RenderTask* task); + static void enqueueDestroyLayer(Layer* layer); ANDROID_API DeferredLayerUpdater* createDisplayListLayer(int width, int height); ANDROID_API DeferredLayerUpdater* createTextureLayer(); ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap); @@ -90,6 +91,8 @@ public: ANDROID_API void dumpProfileInfo(int fd); + ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size); + private: RenderThread& mRenderThread; CanvasContext* mContext; diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 4a4e254..03e98d5 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -21,7 +21,9 @@ #include <gui/DisplayEventReceiver.h> #include <utils/Log.h> +#include "../RenderState.h" #include "CanvasContext.h" +#include "EglManager.h" #include "RenderProxy.h" namespace android { @@ -138,13 +140,16 @@ RenderThread::RenderThread() : Thread(true), Singleton<RenderThread>() , mDisplayEventReceiver(0) , mVsyncRequested(false) , mFrameCallbackTaskPending(false) - , mFrameCallbackTask(0) { + , mFrameCallbackTask(0) + , mRenderState(NULL) + , mEglManager(NULL) { mFrameCallbackTask = new DispatchFrameCallbacks(this); mLooper = new Looper(false); run("RenderThread"); } RenderThread::~RenderThread() { + LOG_ALWAYS_FATAL("Can't destroy the render thread"); } void RenderThread::initializeDisplayEventReceiver() { @@ -159,6 +164,12 @@ void RenderThread::initializeDisplayEventReceiver() { Looper::EVENT_INPUT, RenderThread::displayEventReceiverCallback, this); } +void RenderThread::initThreadLocals() { + initializeDisplayEventReceiver(); + mEglManager = new EglManager(*this); + mRenderState = new RenderState(); +} + int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) { if (events & (Looper::EVENT_ERROR | Looper::EVENT_HANGUP)) { ALOGE("Display event receiver pipe was closed or an error occurred. " @@ -233,7 +244,7 @@ void RenderThread::requestVsync() { } bool RenderThread::threadLoop() { - initializeDisplayEventReceiver(); + initThreadLocals(); int timeoutMillis = -1; for (;;) { diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index 4412584..0b91e9d 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -31,12 +31,18 @@ #include "TimeLord.h" namespace android { + class DisplayEventReceiver; namespace uirenderer { + +class RenderState; + namespace renderthread { class DispatchFrameCallbacks; +class EglManager; +class RenderProxy; class TaskQueue { public: @@ -62,7 +68,7 @@ protected: ~IFrameCallback() {} }; -class ANDROID_API RenderThread : public Thread, public Singleton<RenderThread> { +class ANDROID_API RenderThread : public Thread, protected Singleton<RenderThread> { public: // RenderThread takes complete ownership of tasks that are queued // and will delete them after they are run @@ -79,6 +85,8 @@ public: void pushBackFrameCallback(IFrameCallback* callback); TimeLord& timeLord() { return mTimeLord; } + RenderState& renderState() { return *mRenderState; } + EglManager& eglManager() { return *mEglManager; } protected: virtual bool threadLoop(); @@ -86,10 +94,12 @@ protected: private: friend class Singleton<RenderThread>; friend class DispatchFrameCallbacks; + friend class RenderProxy; RenderThread(); virtual ~RenderThread(); + void initThreadLocals(); void initializeDisplayEventReceiver(); static int displayEventReceiverCallback(int fd, int events, void* data); void drainDisplayEventQueue(bool skipCallbacks = false); @@ -119,6 +129,8 @@ private: DispatchFrameCallbacks* mFrameCallbackTask; TimeLord mTimeLord; + RenderState* mRenderState; + EglManager* mEglManager; }; } /* namespace renderthread */ |