diff options
-rw-r--r-- | core/java/android/app/ActivityThread.java | 1 | ||||
-rw-r--r-- | core/java/android/view/GLRenderer.java | 41 | ||||
-rw-r--r-- | core/java/android/view/HardwareLayer.java | 32 | ||||
-rw-r--r-- | core/java/android/view/HardwareRenderer.java | 16 | ||||
-rw-r--r-- | core/java/android/view/TextureView.java | 26 | ||||
-rw-r--r-- | core/java/android/view/ThreadedRenderer.java | 89 | ||||
-rw-r--r-- | core/java/android/view/View.java | 24 | ||||
-rw-r--r-- | core/java/android/view/ViewRootImpl.java | 23 | ||||
-rw-r--r-- | core/jni/android_view_ThreadedRenderer.cpp | 53 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.cpp | 22 | ||||
-rw-r--r-- | libs/hwui/DeferredLayerUpdater.h | 1 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 26 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.h | 8 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 73 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.h | 11 |
15 files changed, 264 insertions, 182 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 30c1e622d346..3258585ad583 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -3949,6 +3949,7 @@ public final class ActivityThread { ArrayList<ComponentCallbacks2> callbacks = collectComponentCallbacks(false, config); // Cleanup hardware accelerated stuff + // TODO: Do we actually want to do this in response to all config changes? WindowManagerGlobal.getInstance().trimLocalMemory(); freeTextLayoutCachesIfNeeded(configDiff); diff --git a/core/java/android/view/GLRenderer.java b/core/java/android/view/GLRenderer.java index c1eb6b771c09..859468aa44ef 100644 --- a/core/java/android/view/GLRenderer.java +++ b/core/java/android/view/GLRenderer.java @@ -477,17 +477,21 @@ public class GLRenderer extends HardwareRenderer { @Override void flushLayerUpdates() { - mGlCanvas.flushLayerUpdates(); + if (validate()) { + mGlCanvas.flushLayerUpdates(); + } } @Override HardwareLayer createTextureLayer() { + validate(); return HardwareLayer.createTextureLayer(this); } @Override public HardwareLayer createDisplayListLayer(int width, int height) { - return HardwareLayer.createRenderLayer(this, width, height); + validate(); + return HardwareLayer.createDisplayListLayer(this, width, height); } @Override @@ -510,6 +514,9 @@ public class GLRenderer extends HardwareRenderer { @Override boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap) { + if (!validate()) { + throw new IllegalStateException("Could not acquire hardware rendering context"); + } layer.flushChanges(); return GLES20Canvas.nCopyLayer(layer.getLayer(), bitmap.mNativeBitmap); } @@ -538,35 +545,6 @@ public class GLRenderer extends HardwareRenderer { } @Override - void destroyLayers(final View view) { - if (view != null) { - safelyRun(new Runnable() { - @Override - public void run() { - if (mCanvas != null) { - mCanvas.clearLayerUpdates(); - } - destroyHardwareLayer(view); - GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS); - } - }); - } - } - - private static void destroyHardwareLayer(View view) { - view.destroyLayer(true); - - if (view instanceof ViewGroup) { - ViewGroup group = (ViewGroup) view; - - int count = group.getChildCount(); - for (int i = 0; i < count; i++) { - destroyHardwareLayer(group.getChildAt(i)); - } - } - } - - @Override void destroyHardwareResources(final View view) { if (view != null) { safelyRun(new Runnable() { @@ -1069,7 +1047,6 @@ public class GLRenderer extends HardwareRenderer { return true; } - @Override boolean validate() { return checkRenderContext() != SURFACE_STATE_ERROR; } diff --git a/core/java/android/view/HardwareLayer.java b/core/java/android/view/HardwareLayer.java index 9bbcf7ce5963..958c0719543a 100644 --- a/core/java/android/view/HardwareLayer.java +++ b/core/java/android/view/HardwareLayer.java @@ -33,7 +33,7 @@ import android.graphics.SurfaceTexture; */ final class HardwareLayer { private static final int LAYER_TYPE_TEXTURE = 1; - private static final int LAYER_TYPE_RENDER = 2; + private static final int LAYER_TYPE_DISPLAY_LIST = 2; private HardwareRenderer mRenderer; private Finalizer mFinalizer; @@ -99,6 +99,10 @@ final class HardwareLayer { doDestroyLayerUpdater(); } + public long getDeferredLayerUpdater() { + return mFinalizer.mDeferredUpdater; + } + /** * Destroys the deferred layer updater but not the backing layer. The * backing layer is instead returned and is the caller's responsibility @@ -120,7 +124,7 @@ final class HardwareLayer { } public DisplayList startRecording() { - assertType(LAYER_TYPE_RENDER); + assertType(LAYER_TYPE_DISPLAY_LIST); if (mDisplayList == null) { mDisplayList = DisplayList.create("HardwareLayer"); @@ -172,9 +176,17 @@ final class HardwareLayer { /** * Indicates that this layer has lost its texture. */ - public void onTextureDestroyed() { + public void detachSurfaceTexture(final SurfaceTexture surface) { assertType(LAYER_TYPE_TEXTURE); - nOnTextureDestroyed(mFinalizer.mDeferredUpdater); + mRenderer.safelyRun(new Runnable() { + @Override + public void run() { + surface.detachFromGLContext(); + // SurfaceTexture owns the texture name and detachFromGLContext + // should have deleted it + nOnTextureDestroyed(mFinalizer.mDeferredUpdater); + } + }); } /** @@ -226,12 +238,20 @@ final class HardwareLayer { return new HardwareLayer(renderer, nCreateTextureLayer(), LAYER_TYPE_TEXTURE); } + static HardwareLayer adoptTextureLayer(HardwareRenderer renderer, long layer) { + return new HardwareLayer(renderer, layer, LAYER_TYPE_TEXTURE); + } + /** * This should only be used by HardwareRenderer! Do not call directly */ - static HardwareLayer createRenderLayer(HardwareRenderer renderer, + static HardwareLayer createDisplayListLayer(HardwareRenderer renderer, int width, int height) { - return new HardwareLayer(renderer, nCreateRenderLayer(width, height), LAYER_TYPE_RENDER); + return new HardwareLayer(renderer, nCreateRenderLayer(width, height), LAYER_TYPE_DISPLAY_LIST); + } + + static HardwareLayer adoptDisplayListLayer(HardwareRenderer renderer, long layer) { + return new HardwareLayer(renderer, layer, LAYER_TYPE_DISPLAY_LIST); } /** This also creates the underlying layer */ diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 93cc9d122ce4..7a943f0a136c 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -234,13 +234,6 @@ public abstract class HardwareRenderer { abstract void updateSurface(Surface surface) throws OutOfResourcesException; /** - * Destroys the layers used by the specified view hierarchy. - * - * @param view The root of the view hierarchy - */ - abstract void destroyLayers(View view); - - /** * Destroys all hardware rendering resources associated with the specified * view hierarchy. * @@ -257,15 +250,6 @@ public abstract class HardwareRenderer { abstract void invalidate(Surface surface); /** - * This method should be invoked to ensure the hardware renderer is in - * valid state (for instance, to ensure the correct EGL context is bound - * to the current thread.) - * - * @return true if the renderer is now valid, false otherwise - */ - abstract boolean validate(); - - /** * This method ensures the hardware renderer is in a valid state * before executing the specified action. * diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java index e78940779fd3..ef0d80d73cde 100644 --- a/core/java/android/view/TextureView.java +++ b/core/java/android/view/TextureView.java @@ -231,26 +231,12 @@ public class TextureView extends View { @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); - if (mLayer != null) { - boolean success = executeHardwareAction(new Runnable() { - @Override - public void run() { - destroySurface(); - } - }); - - if (!success) { - Log.w(LOG_TAG, "TextureView was not able to destroy its surface: " + this); - } - } + destroySurface(); } private void destroySurface() { if (mLayer != null) { - mSurface.detachFromGLContext(); - // SurfaceTexture owns the texture name and detachFromGLContext - // should have deleted it - mLayer.onTextureDestroyed(); + mLayer.detachSurfaceTexture(mSurface); boolean shouldRelease = true; if (mListener != null) { @@ -608,14 +594,6 @@ public class TextureView extends View { */ public Bitmap getBitmap(Bitmap bitmap) { if (bitmap != null && isAvailable()) { - AttachInfo info = mAttachInfo; - if (info != null && info.mHardwareRenderer != null && - info.mHardwareRenderer.isEnabled()) { - if (!info.mHardwareRenderer.validate()) { - throw new IllegalStateException("Could not acquire hardware rendering context"); - } - } - applyUpdate(); applyTransformMatrix(); diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 1d7e5b296162..e8f5e45fb393 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -76,13 +76,7 @@ public class ThreadedRenderer extends HardwareRenderer { } @Override - void destroyLayers(View view) { - throw new NoSuchMethodError(); - } - - @Override void destroyHardwareResources(View view) { - // TODO: canvas.clearLayerUpdates() destroyResources(view); // TODO: GLES20Canvas.flushCaches(GLES20Canvas.FLUSH_CACHES_LAYERS); } @@ -106,12 +100,6 @@ public class ThreadedRenderer extends HardwareRenderer { } @Override - boolean validate() { - // TODO Remove users of this API - return false; - } - - @Override boolean safelyRun(Runnable action) { nRunWithGlContext(mNativeProxy, action); return true; @@ -150,26 +138,6 @@ public class ThreadedRenderer extends HardwareRenderer { return false; } - @Override - void pushLayerUpdate(HardwareLayer layer) { - throw new NoSuchMethodError(); - } - - @Override - void onLayerCreated(HardwareLayer layer) { - throw new NoSuchMethodError(); - } - - @Override - void onLayerDestroyed(HardwareLayer layer) { - throw new NoSuchMethodError(); - } - - @Override - void flushLayerUpdates() { - throw new NoSuchMethodError(); - } - /** * TODO: Remove * Temporary hack to allow RenderThreadTest prototype app to trigger @@ -203,33 +171,63 @@ public class ThreadedRenderer extends HardwareRenderer { } @Override - HardwareLayer createTextureLayer() { - throw new NoSuchMethodError(); + void detachFunctor(long functor) { + nDetachFunctor(mNativeProxy, functor); + } + + @Override + void attachFunctor(AttachInfo attachInfo, long functor) { + nAttachFunctor(mNativeProxy, functor); } @Override HardwareLayer createDisplayListLayer(int width, int height) { - throw new NoSuchMethodError(); + long layer = nCreateDisplayListLayer(mNativeProxy, width, height); + return HardwareLayer.adoptDisplayListLayer(this, layer); } @Override - SurfaceTexture createSurfaceTexture(HardwareLayer layer) { - throw new NoSuchMethodError(); + HardwareLayer createTextureLayer() { + long layer = nCreateTextureLayer(mNativeProxy); + return HardwareLayer.adoptTextureLayer(this, layer); } @Override - boolean copyLayerInto(HardwareLayer layer, Bitmap bitmap) { - throw new NoSuchMethodError(); + SurfaceTexture createSurfaceTexture(final HardwareLayer layer) { + final SurfaceTexture[] ret = new SurfaceTexture[1]; + nRunWithGlContext(mNativeProxy, new Runnable() { + @Override + public void run() { + ret[0] = layer.createSurfaceTexture(); + } + }); + return ret[0]; } @Override - void detachFunctor(long functor) { - nDetachFunctor(mNativeProxy, functor); + boolean copyLayerInto(final HardwareLayer layer, final Bitmap bitmap) { + return nCopyLayerInto(mNativeProxy, + layer.getDeferredLayerUpdater(), bitmap.mNativeBitmap); } @Override - void attachFunctor(AttachInfo attachInfo, long functor) { - nAttachFunctor(mNativeProxy, functor); + void pushLayerUpdate(HardwareLayer layer) { + // TODO: Remove this, it's not needed outside of GLRenderer + } + + @Override + void onLayerCreated(HardwareLayer layer) { + // TODO: Is this actually useful? + } + + @Override + void flushLayerUpdates() { + // TODO: Figure out what this should do or remove it + } + + @Override + void onLayerDestroyed(HardwareLayer layer) { + nDestroyLayer(mNativeProxy, layer.getDeferredLayerUpdater()); } @Override @@ -261,4 +259,9 @@ public class ThreadedRenderer extends HardwareRenderer { private static native void nAttachFunctor(long nativeProxy, long functor); private static native void nDetachFunctor(long nativeProxy, long functor); + + private static native long nCreateDisplayListLayer(long nativeProxy, int width, int height); + private static native long nCreateTextureLayer(long nativeProxy); + private static native boolean nCopyLayerInto(long nativeProxy, long layer, long bitmap); + private static native void nDestroyLayer(long nativeProxy, long layer); } diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 49dc5728cdb2..9e7046e65fe6 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -13584,19 +13584,15 @@ public class View implements Drawable.Callback, KeyEvent.Callback, switch (mLayerType) { case LAYER_TYPE_HARDWARE: - if (attachInfo.mHardwareRenderer != null && - attachInfo.mHardwareRenderer.isEnabled() && - attachInfo.mHardwareRenderer.validate()) { - getHardwareLayer(); - // TODO: We need a better way to handle this case - // If views have registered pre-draw listeners they need - // to be notified before we build the layer. Those listeners - // may however rely on other events to happen first so we - // cannot just invoke them here until they don't cancel the - // current frame - if (!attachInfo.mTreeObserver.hasOnPreDrawListeners()) { - attachInfo.mViewRootImpl.dispatchFlushHardwareLayerUpdates(); - } + getHardwareLayer(); + // TODO: We need a better way to handle this case + // If views have registered pre-draw listeners they need + // to be notified before we build the layer. Those listeners + // may however rely on other events to happen first so we + // cannot just invoke them here until they don't cancel the + // current frame + if (!attachInfo.mTreeObserver.hasOnPreDrawListeners()) { + attachInfo.mViewRootImpl.dispatchFlushHardwareLayerUpdates(); } break; case LAYER_TYPE_SOFTWARE: @@ -13617,8 +13613,6 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return null; } - if (!mAttachInfo.mHardwareRenderer.validate()) return null; - final int width = mRight - mLeft; final int height = mBottom - mTop; diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 11030d984ad2..a68d06ab948c 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -631,16 +631,25 @@ public final class ViewRootImpl implements ViewParent, } } else { invalidateDisplayLists(); - if (mAttachInfo.mHardwareRenderer != null && - mAttachInfo.mHardwareRenderer.isEnabled()) { - mAttachInfo.mHardwareRenderer.destroyLayers(mView); + destroyHardwareLayer(mView); + } + } + + private static void destroyHardwareLayer(View view) { + view.destroyLayer(true); + + if (view instanceof ViewGroup) { + ViewGroup group = (ViewGroup) view; + + int count = group.getChildCount(); + for (int i = 0; i < count; i++) { + destroyHardwareLayer(group.getChildAt(i)); } } } void flushHardwareLayerUpdates() { - if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled() && - mAttachInfo.mHardwareRenderer.validate()) { + if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) { mAttachInfo.mHardwareRenderer.flushLayerUpdates(); } } @@ -2845,10 +2854,6 @@ public final class ViewRootImpl implements ViewParent, void dispatchDetachedFromWindow() { if (mView != null && mView.mAttachInfo != null) { - if (mAttachInfo.mHardwareRenderer != null && - mAttachInfo.mHardwareRenderer.isEnabled()) { - mAttachInfo.mHardwareRenderer.validate(); - } mAttachInfo.mTreeObserver.dispatchOnWindowAttachedChange(false); mView.dispatchDetachedFromWindow(); } diff --git a/core/jni/android_view_ThreadedRenderer.cpp b/core/jni/android_view_ThreadedRenderer.cpp index e86a2d44be44..bc5c06e8bcb8 100644 --- a/core/jni/android_view_ThreadedRenderer.cpp +++ b/core/jni/android_view_ThreadedRenderer.cpp @@ -76,20 +76,20 @@ static jlong android_view_ThreadedRenderer_createProxy(JNIEnv* env, jobject claz static void android_view_ThreadedRenderer_deleteProxy(JNIEnv* env, jobject clazz, jlong proxyPtr) { - RenderProxy* proxy = reinterpret_cast<RenderProxy*>( proxyPtr); + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); delete proxy; } static jboolean android_view_ThreadedRenderer_initialize(JNIEnv* env, jobject clazz, jlong proxyPtr, jobject jsurface) { - RenderProxy* proxy = reinterpret_cast<RenderProxy*>( proxyPtr); + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); sp<ANativeWindow> window = android_view_Surface_getNativeWindow(env, jsurface); return proxy->initialize(window.get()); } static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject clazz, jlong proxyPtr, jobject jsurface) { - RenderProxy* proxy = reinterpret_cast<RenderProxy*>( proxyPtr); + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); sp<ANativeWindow> window; if (jsurface) { window = android_view_Surface_getNativeWindow(env, jsurface); @@ -99,45 +99,74 @@ static void android_view_ThreadedRenderer_updateSurface(JNIEnv* env, jobject cla static void android_view_ThreadedRenderer_setup(JNIEnv* env, jobject clazz, jlong proxyPtr, jint width, jint height) { - RenderProxy* proxy = reinterpret_cast<RenderProxy*>( proxyPtr); + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); proxy->setup(width, height); } static void android_view_ThreadedRenderer_drawDisplayList(JNIEnv* env, jobject clazz, jlong proxyPtr, jlong displayListPtr, jint dirtyLeft, jint dirtyTop, jint dirtyRight, jint dirtyBottom) { - RenderProxy* proxy = reinterpret_cast<RenderProxy*>( proxyPtr); - DisplayList* displayList = reinterpret_cast<DisplayList*>( displayListPtr); + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + DisplayList* displayList = reinterpret_cast<DisplayList*>(displayListPtr); proxy->drawDisplayList(displayList, dirtyLeft, dirtyTop, dirtyRight, dirtyBottom); } static void android_view_ThreadedRenderer_destroyCanvas(JNIEnv* env, jobject clazz, jlong proxyPtr) { - RenderProxy* proxy = reinterpret_cast<RenderProxy*>( proxyPtr); + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); proxy->destroyCanvas(); } static void android_view_ThreadedRenderer_attachFunctor(JNIEnv* env, jobject clazz, jlong proxyPtr, jlong functorPtr) { - RenderProxy* proxy = reinterpret_cast<RenderProxy*>( proxyPtr); + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); Functor* functor = reinterpret_cast<Functor*>(functorPtr); proxy->attachFunctor(functor); } static void android_view_ThreadedRenderer_detachFunctor(JNIEnv* env, jobject clazz, jlong proxyPtr, jlong functorPtr) { - RenderProxy* proxy = reinterpret_cast<RenderProxy*>( proxyPtr); + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); Functor* functor = reinterpret_cast<Functor*>(functorPtr); proxy->detachFunctor(functor); } static void android_view_ThreadedRenderer_runWithGlContext(JNIEnv* env, jobject clazz, jlong proxyPtr, jobject jrunnable) { - RenderProxy* proxy = reinterpret_cast<RenderProxy*>( proxyPtr); + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); RenderTask* task = new JavaTask(env, jrunnable); proxy->runWithGlContext(task); } +static jlong android_view_ThreadedRenderer_createDisplayListLayer(JNIEnv* env, jobject clazz, + jlong proxyPtr, jint width, jint height) { + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + DeferredLayerUpdater* layer = proxy->createDisplayListLayer(width, height); + return reinterpret_cast<jlong>(layer); +} + +static jlong android_view_ThreadedRenderer_createTextureLayer(JNIEnv* env, jobject clazz, + jlong proxyPtr) { + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + DeferredLayerUpdater* layer = proxy->createTextureLayer(); + return reinterpret_cast<jlong>(layer); +} + +static jboolean android_view_ThreadedRenderer_copyLayerInto(JNIEnv* env, jobject clazz, + jlong proxyPtr, jlong layerPtr, jlong bitmapPtr) { + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); + SkBitmap* bitmap = reinterpret_cast<SkBitmap*>(bitmapPtr); + return proxy->copyLayerInto(layer, bitmap); +} + +static void android_view_ThreadedRenderer_destroyLayer(JNIEnv* env, jobject clazz, + jlong proxyPtr, jlong layerPtr) { + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(layerPtr); + proxy->destroyLayer(layer); +} + #endif // ---------------------------------------------------------------------------- @@ -159,6 +188,10 @@ static JNINativeMethod gMethods[] = { { "nAttachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_attachFunctor}, { "nDetachFunctor", "(JJ)V", (void*) android_view_ThreadedRenderer_detachFunctor}, { "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 }, + { "nCopyLayerInto", "(JJJ)Z", (void*) android_view_ThreadedRenderer_copyLayerInto }, + { "nDestroyLayer", "(JJ)V", (void*) android_view_ThreadedRenderer_destroyLayer }, #endif }; diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index 5d3d39399d25..efb12980de7f 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -123,27 +123,5 @@ void DeferredLayerUpdater::doUpdateTexImage() { } } -void DeferredLayerUpdater::applyDeferred(DeferredLayerUpdater* deferredApply) { - // Default assignment operator doesn't quite work, and fails due to mCaches anyway - deferredApply->mWidth = mWidth; - deferredApply->mHeight = mHeight; - deferredApply->mBlend = mBlend; - deferredApply->mAlpha = mAlpha; - deferredApply->mMode = mMode; - deferredApply->mDirtyRect.set(mDirtyRect); - deferredApply->mDisplayList = mDisplayList; - deferredApply->mSurfaceTexture = mSurfaceTexture; - deferredApply->mNeedsGLContextAttach = mNeedsGLContextAttach; - deferredApply->mUpdateTexImage = mUpdateTexImage; - deferredApply->setColorFilter(mColorFilter); - deferredApply->setTransform(mTransform); - - mDisplayList = 0; - mDirtyRect.setEmpty(); - mTransform = 0; - mNeedsGLContextAttach = false; - mUpdateTexImage = false; -} - } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h index 9800c2f5ede0..624db2ce67be 100644 --- a/libs/hwui/DeferredLayerUpdater.h +++ b/libs/hwui/DeferredLayerUpdater.h @@ -82,7 +82,6 @@ public: ANDROID_API void setColorFilter(SkColorFilter* colorFilter); ANDROID_API bool apply(); - ANDROID_API void applyDeferred(DeferredLayerUpdater* deferredApply); ANDROID_API Layer* backingLayer() { return mLayer; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 4e665d9ff9c2..fe781bd771f9 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -24,6 +24,8 @@ #include "RenderThread.h" #include "../Caches.h" +#include "../DeferredLayerUpdater.h" +#include "../LayerRenderer.h" #include "../OpenGLRenderer.h" #include "../Stencil.h" @@ -371,6 +373,17 @@ void CanvasContext::setup(int width, int height) { mCanvas->setViewport(width, height); } +void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters) { + mGlobalContext->makeCurrent(mEglSurface); + for (size_t i = 0; i < layerUpdaters->size(); i++) { + DeferredLayerUpdater* update = layerUpdaters->itemAt(i); + LOG_ALWAYS_FATAL_IF(!update->apply(), "Failed to update layer!"); + if (update->backingLayer()->deferredUpdateScheduled) { + mCanvas->pushLayerUpdate(update->backingLayer()); + } + } +} + void CanvasContext::drawDisplayList(DisplayList* displayList, Rect* dirty) { LOG_ALWAYS_FATAL_IF(!mCanvas || mEglSurface == EGL_NO_SURFACE, "drawDisplayList called on a context with no canvas or surface!"); @@ -462,14 +475,23 @@ void CanvasContext::queueFunctorsTask(int delayMs) { mRenderThread.queueDelayed(&mInvokeFunctorsTask, delayMs); } +bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { + requireGlContext(); + layer->apply(); + return LayerRenderer::copyLayer(layer->backingLayer(), bitmap); +} + void CanvasContext::runWithGlContext(RenderTask* task) { + requireGlContext(); + task->run(); +} + +void CanvasContext::requireGlContext() { if (mEglSurface != EGL_NO_SURFACE) { mGlobalContext->makeCurrent(mEglSurface); } else { mGlobalContext->usePBufferSurface(); } - - task->run(); } } /* namespace renderthread */ diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 3197df3afa47..5fac5821f99d 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -19,7 +19,9 @@ #include <cutils/compiler.h> #include <EGL/egl.h> +#include <SkBitmap.h> #include <utils/Functor.h> +#include <utils/Vector.h> #include "RenderTask.h" @@ -28,6 +30,7 @@ namespace android { namespace uirenderer { +class DeferredLayerUpdater; class DisplayList; class OpenGLRenderer; class Rect; @@ -59,9 +62,12 @@ public: bool initialize(EGLNativeWindowType window); void updateSurface(EGLNativeWindowType window); void setup(int width, int height); + void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters); void drawDisplayList(DisplayList* displayList, Rect* dirty); void destroyCanvas(); + bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap); + void attachFunctor(Functor* functor); void detachFunctor(Functor* functor); @@ -78,6 +84,8 @@ private: void removeFunctorsTask(); void queueFunctorsTask(int delayMs = FUNCTOR_PROCESS_DELAY); + void requireGlContext(); + GlobalContext* mGlobalContext; RenderThread& mRenderThread; EGLSurface mEglSurface; diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 34f19610f01a..0c667fd0046f 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -22,7 +22,9 @@ #include "RenderTask.h" #include "RenderThread.h" +#include "../DeferredLayerUpdater.h" #include "../DisplayList.h" +#include "../LayerRenderer.h" #include "../Rect.h" namespace android { @@ -31,6 +33,7 @@ namespace renderthread { #define ARGS(method) method ## Args +#define CREATE_BRIDGE0(name) CREATE_BRIDGE(name,,,,,,,,) #define CREATE_BRIDGE1(name, a1) CREATE_BRIDGE(name, a1,,,,,,,) #define CREATE_BRIDGE2(name, a1, a2) CREATE_BRIDGE(name, a1,a2,,,,,,) #define CREATE_BRIDGE3(name, a1, a2, a3) CREATE_BRIDGE(name, a1,a2,a3,,,,,) @@ -114,13 +117,14 @@ void RenderProxy::setup(int width, int height) { post(task); } -CREATE_BRIDGE3(drawDisplayList, CanvasContext* context, DisplayList* displayList, - Rect dirty) { +CREATE_BRIDGE4(drawDisplayList, CanvasContext* context, DisplayList* displayList, + Rect dirty, const Vector<DeferredLayerUpdater*>* layerUpdates) { Rect* dirty = &args->dirty; if (dirty->bottom == -1 && dirty->left == -1 && dirty->top == -1 && dirty->right == -1) { dirty = 0; } + args->context->processLayerUpdates(args->layerUpdates); args->context->drawDisplayList(args->displayList, dirty); return NULL; } @@ -131,6 +135,7 @@ void RenderProxy::drawDisplayList(DisplayList* displayList, args->context = mContext; args->displayList = displayList; args->dirty.set(dirtyLeft, dirtyTop, dirtyRight, dirtyBottom); + args->layerUpdates = &mLayers; // TODO: Switch to post() once some form of thread safety strategy is in place postAndWait(task); } @@ -182,6 +187,70 @@ void RenderProxy::runWithGlContext(RenderTask* gltask) { postAndWait(task); } +CREATE_BRIDGE2(createDisplayListLayer, int width, int height) { + Layer* layer = LayerRenderer::createRenderLayer(args->width, args->height); + if (!layer) return 0; + + OpenGLRenderer* renderer = new LayerRenderer(layer); + renderer->initProperties(); + return new DeferredLayerUpdater(layer, renderer); +} + +DeferredLayerUpdater* RenderProxy::createDisplayListLayer(int width, int height) { + SETUP_TASK(createDisplayListLayer); + args->width = width; + args->height = height; + void* retval = postAndWait(task); + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); + mLayers.push(layer); + return layer; +} + +CREATE_BRIDGE0(createTextureLayer) { + Layer* layer = LayerRenderer::createTextureLayer(); + if (!layer) return 0; + return new DeferredLayerUpdater(layer); +} + +DeferredLayerUpdater* RenderProxy::createTextureLayer() { + SETUP_TASK(createTextureLayer); + void* retval = postAndWait(task); + DeferredLayerUpdater* layer = reinterpret_cast<DeferredLayerUpdater*>(retval); + mLayers.push(layer); + return layer; +} + +CREATE_BRIDGE1(destroyLayer, Layer* layer) { + LayerRenderer::destroyLayer(args->layer); + return NULL; +} + +CREATE_BRIDGE3(copyLayerInto, CanvasContext* context, DeferredLayerUpdater* layer, + SkBitmap* bitmap) { + bool success = args->context->copyLayerInto(args->layer, args->bitmap); + return (void*) success; +} + +bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { + SETUP_TASK(copyLayerInto); + args->context = mContext; + args->layer = layer; + args->bitmap = bitmap; + return (bool) postAndWait(task); +} + +void RenderProxy::destroyLayer(DeferredLayerUpdater* layer) { + for (size_t i = 0; i < mLayers.size(); i++) { + if (mLayers[i] == layer) { + mLayers.removeAt(i); + break; + } + } + SETUP_TASK(destroyLayer); + args->layer = layer->detachBackingLayer(); + post(task); +} + MethodInvokeRenderTask* RenderProxy::createTask(RunnableMethod method) { // TODO: Consider having a small pool of these to avoid alloc churn return new MethodInvokeRenderTask(method); diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 1ad0c2dd7bca..8ff3d638feca 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -21,15 +21,19 @@ #include <cutils/compiler.h> #include <EGL/egl.h> +#include <SkBitmap.h> #include <utils/Condition.h> #include <utils/Functor.h> #include <utils/Mutex.h> #include <utils/StrongPointer.h> +#include <utils/Vector.h> namespace android { namespace uirenderer { +class DeferredLayerUpdater; class DisplayList; +class Layer; class Rect; namespace renderthread { @@ -64,6 +68,11 @@ public: ANDROID_API void runWithGlContext(RenderTask* task); + ANDROID_API DeferredLayerUpdater* createDisplayListLayer(int width, int height); + ANDROID_API DeferredLayerUpdater* createTextureLayer(); + ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap); + ANDROID_API void destroyLayer(DeferredLayerUpdater* layer); + private: RenderThread& mRenderThread; CanvasContext* mContext; @@ -71,6 +80,8 @@ private: Mutex mSyncMutex; Condition mSyncCondition; + Vector<DeferredLayerUpdater*> mLayers; + void destroyContext(); MethodInvokeRenderTask* createTask(RunnableMethod method); |