diff options
Diffstat (limited to 'libs/hwui/renderthread')
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 82 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.h | 28 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.cpp | 67 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.h | 30 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 58 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.h | 8 |
6 files changed, 61 insertions, 212 deletions
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index c231f6f..3638184 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -313,14 +313,11 @@ CanvasContext::CanvasContext(bool translucent) , mDirtyRegionsEnabled(false) , mOpaque(!translucent) , mCanvas(0) - , mHaveNewSurface(false) - , mInvokeFunctorsPending(false) - , mInvokeFunctorsTask(this) { + , mHaveNewSurface(false) { mGlobalContext = GlobalContext::get(); } CanvasContext::~CanvasContext() { - removeFunctorsTask(); destroyCanvas(); } @@ -347,6 +344,7 @@ void CanvasContext::setSurface(EGLNativeWindowType window) { if (mEglSurface != EGL_NO_SURFACE) { mDirtyRegionsEnabled = mGlobalContext->enableDirtyRegions(mEglSurface); + mGlobalContext->makeCurrent(mEglSurface); mHaveNewSurface = true; } } @@ -356,14 +354,15 @@ void CanvasContext::swapBuffers() { mHaveNewSurface = false; } -void CanvasContext::makeCurrent() { +void CanvasContext::requireSurface() { + LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE, + "requireSurface() called but no surface set!"); mGlobalContext->makeCurrent(mEglSurface); } bool CanvasContext::initialize(EGLNativeWindowType window) { if (mCanvas) return false; setSurface(window); - makeCurrent(); mCanvas = new OpenGLRenderer(); mCanvas->initProperties(); return true; @@ -371,7 +370,11 @@ bool CanvasContext::initialize(EGLNativeWindowType window) { void CanvasContext::updateSurface(EGLNativeWindowType window) { setSurface(window); - makeCurrent(); +} + +void CanvasContext::pauseSurface(EGLNativeWindowType window) { + // TODO: For now we just need a fence, in the future suspend any animations + // and such to prevent from trying to render into this surface } void CanvasContext::setup(int width, int height) { @@ -379,15 +382,13 @@ void CanvasContext::setup(int width, int height) { mCanvas->setViewport(width, height); } -void CanvasContext::setDisplayListData(RenderNode* displayList, DisplayListData* newData) { - displayList->setData(newData); -} - -void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters) { +void CanvasContext::processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, + bool* hasFunctors) { + LOG_ALWAYS_FATAL_IF(!mCanvas, "Cannot process layer updates without a canvas!"); 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!"); + LOG_ALWAYS_FATAL_IF(!update->apply(hasFunctors), "Failed to update layer!"); if (update->backingLayer()->deferredUpdateScheduled) { mCanvas->pushLayerUpdate(update->backingLayer()); } @@ -428,60 +429,23 @@ void CanvasContext::drawDisplayList(RenderNode* displayList, Rect* dirty) { } } -void InvokeFunctorsTask::run() { - mContext->invokeFunctors(); -} - -void CanvasContext::attachFunctor(Functor* functor) { - if (!mCanvas) return; - - mCanvas->attachFunctor(functor); - removeFunctorsTask(); - queueFunctorsTask(0); -} - -void CanvasContext::detachFunctor(Functor* functor) { - if (!mCanvas) return; - - mCanvas->detachFunctor(functor); -} - void CanvasContext::invokeFunctor(Functor* functor) { + ATRACE_CALL(); DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext; if (mGlobalContext->hasContext()) { requireGlContext(); mode = DrawGlInfo::kModeProcess; } - (*functor)(mode, NULL); -} - -void CanvasContext::invokeFunctors() { - mInvokeFunctorsPending = false; - - if (!mCanvas) return; - - makeCurrent(); - Rect dirty; - mCanvas->invokeFunctors(dirty); -} - -void CanvasContext::removeFunctorsTask() { - if (!mInvokeFunctorsPending) return; - - mInvokeFunctorsPending = false; - mRenderThread.remove(&mInvokeFunctorsTask); -} - -void CanvasContext::queueFunctorsTask(int delayMs) { - if (mInvokeFunctorsPending) return; - - mInvokeFunctorsPending = true; - mRenderThread.queueDelayed(&mInvokeFunctorsTask, delayMs); + // TODO: Remove the dummy info in the future + DrawGlInfo dummyInfo; + memset(&dummyInfo, 0, sizeof(DrawGlInfo)); + (*functor)(mode, &dummyInfo); } bool CanvasContext::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap) { requireGlContext(); - layer->apply(); + bool hasFunctors; + layer->apply(&hasFunctors); return LayerRenderer::copyLayer(layer->backingLayer(), bitmap); } @@ -491,12 +455,12 @@ void CanvasContext::runWithGlContext(RenderTask* task) { } Layer* CanvasContext::createRenderLayer(int width, int height) { - requireGlContext(); + requireSurface(); return LayerRenderer::createRenderLayer(width, height); } Layer* CanvasContext::createTextureLayer() { - requireGlContext(); + requireSurface(); return LayerRenderer::createTextureLayer(); } diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index 6f1c37f..dcb5957 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -43,17 +43,6 @@ class GlobalContext; class CanvasContext; class RenderThread; -class InvokeFunctorsTask : public RenderTask { -public: - InvokeFunctorsTask(CanvasContext* context) - : mContext(context) {} - - virtual void run(); - -private: - CanvasContext* mContext; -}; - // This per-renderer class manages the bridge between the global EGL context // and the render surface. class CanvasContext { @@ -63,16 +52,14 @@ public: bool initialize(EGLNativeWindowType window); void updateSurface(EGLNativeWindowType window); + void pauseSurface(EGLNativeWindowType window); void setup(int width, int height); - void setDisplayListData(RenderNode* displayList, DisplayListData* newData); - void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters); + void processLayerUpdates(const Vector<DeferredLayerUpdater*>* layerUpdaters, bool* hasFunctors); void drawDisplayList(RenderNode* displayList, Rect* dirty); void destroyCanvas(); bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap); - void attachFunctor(Functor* functor); - void detachFunctor(Functor* functor); void invokeFunctor(Functor* functor); void runWithGlContext(RenderTask* task); @@ -83,12 +70,7 @@ public: private: void setSurface(EGLNativeWindowType window); void swapBuffers(); - void makeCurrent(); - - friend class InvokeFunctorsTask; - void invokeFunctors(); - void removeFunctorsTask(); - void queueFunctorsTask(int delayMs = FUNCTOR_PROCESS_DELAY); + void requireSurface(); void requireGlContext(); @@ -100,10 +82,6 @@ private: bool mOpaque; OpenGLRenderer* mCanvas; bool mHaveNewSurface; - - bool mInvokeFunctorsPending; - InvokeFunctorsTask mInvokeFunctorsTask; - }; } /* namespace renderthread */ diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp index 7b509a2..cf6c8db 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -30,19 +30,7 @@ namespace android { namespace uirenderer { namespace renderthread { -SetDisplayListData::SetDisplayListData() : mNewData(0) {} - -SetDisplayListData::SetDisplayListData(RenderNode* node, DisplayListData* newData) - : mTargetNode(node), mNewData(newData) { -} - -SetDisplayListData::~SetDisplayListData() {} - -void SetDisplayListData::apply() const { - mTargetNode->setData(mNewData); -} - -DrawFrameTask::DrawFrameTask() : mContext(0), mTaskMode(MODE_INVALID), mRenderNode(0) { +DrawFrameTask::DrawFrameTask() : mContext(0), mRenderNode(0) { } DrawFrameTask::~DrawFrameTask() { @@ -52,13 +40,6 @@ void DrawFrameTask::setContext(CanvasContext* context) { mContext = context; } -void DrawFrameTask::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) { - LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to setDisplayListData with!"); - - SetDisplayListData setter(renderNode, newData); - mDisplayListDataUpdates.push(setter); -} - void DrawFrameTask::addLayer(DeferredLayerUpdater* layer) { LOG_ALWAYS_FATAL_IF(!mContext, "Lifecycle violation, there's no context to addLayer with!"); @@ -88,23 +69,14 @@ void DrawFrameTask::drawFrame(RenderThread* renderThread) { LOG_ALWAYS_FATAL_IF(!mRenderNode.get(), "Cannot drawFrame with no render node!"); LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!"); - postAndWait(renderThread, MODE_FULL); + postAndWait(renderThread); // Reset the single-frame data mDirty.setEmpty(); mRenderNode = 0; } -void DrawFrameTask::flushStateChanges(RenderThread* renderThread) { - LOG_ALWAYS_FATAL_IF(!mContext, "Cannot drawFrame with no CanvasContext!"); - - postAndWait(renderThread, MODE_STATE_ONLY); -} - -void DrawFrameTask::postAndWait(RenderThread* renderThread, TaskMode mode) { - LOG_ALWAYS_FATAL_IF(mode == MODE_INVALID, "That's not a real mode, silly!"); - - mTaskMode = mode; +void DrawFrameTask::postAndWait(RenderThread* renderThread) { AutoMutex _lock(mLock); renderThread->queue(this); mSignal.wait(mLock); @@ -113,21 +85,14 @@ void DrawFrameTask::postAndWait(RenderThread* renderThread, TaskMode mode) { void DrawFrameTask::run() { ATRACE_NAME("DrawFrame"); - syncFrameState(); - - if (mTaskMode == MODE_STATE_ONLY) { - unblockUiThread(); - return; - } + // canUnblockUiThread is temporary until WebView has a solution for syncing frame state + bool canUnblockUiThread = syncFrameState(); // Grab a copy of everything we need Rect dirtyCopy(mDirty); sp<RenderNode> renderNode = mRenderNode; CanvasContext* context = mContext; - // This is temporary until WebView has a solution for syncing frame state - bool canUnblockUiThread = !requiresSynchronousDraw(renderNode.get()); - // From this point on anything in "this" is *UNSAFE TO ACCESS* if (canUnblockUiThread) { unblockUiThread(); @@ -140,21 +105,17 @@ void DrawFrameTask::run() { } } -void DrawFrameTask::syncFrameState() { +bool DrawFrameTask::syncFrameState() { ATRACE_CALL(); - for (size_t i = 0; i < mDisplayListDataUpdates.size(); i++) { - const SetDisplayListData& setter = mDisplayListDataUpdates[i]; - setter.apply(); - } - mDisplayListDataUpdates.clear(); + bool hasFunctors = false; + mContext->processLayerUpdates(&mLayers, &hasFunctors); - mContext->processLayerUpdates(&mLayers); + TreeInfo info = {0}; + mRenderNode->prepareTree(info); + hasFunctors |= info.hasFunctors; - // If we don't have an mRenderNode this is a state flush only - if (mRenderNode.get()) { - mRenderNode->updateProperties(); - } + return !hasFunctors; } void DrawFrameTask::unblockUiThread() { @@ -172,10 +133,6 @@ void DrawFrameTask::drawRenderNode(CanvasContext* context, RenderNode* renderNod context->drawDisplayList(renderNode, dirty); } -bool DrawFrameTask::requiresSynchronousDraw(RenderNode* renderNode) { - return renderNode->hasFunctors(); -} - } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h index 4e9b244..055d4cf 100644 --- a/libs/hwui/renderthread/DrawFrameTask.h +++ b/libs/hwui/renderthread/DrawFrameTask.h @@ -37,18 +37,6 @@ namespace renderthread { class CanvasContext; class RenderThread; -class SetDisplayListData { -public: - // This ctor exists for Vector's usage - SetDisplayListData(); - SetDisplayListData(RenderNode* node, DisplayListData* newData); - ~SetDisplayListData(); - void apply() const; -private: - sp<RenderNode> mTargetNode; - DisplayListData* mNewData; -}; - /* * This is a special Super Task. It is re-used multiple times by RenderProxy, * and contains state (such as layer updaters & new DisplayListDatas) that is @@ -62,33 +50,21 @@ public: void setContext(CanvasContext* context); - void setDisplayListData(RenderNode* renderNode, DisplayListData* newData); void addLayer(DeferredLayerUpdater* layer); void removeLayer(DeferredLayerUpdater* layer); void setRenderNode(RenderNode* renderNode); void setDirty(int left, int top, int right, int bottom); void drawFrame(RenderThread* renderThread); - void flushStateChanges(RenderThread* renderThread); virtual void run(); private: - enum TaskMode { - MODE_INVALID, - MODE_FULL, - MODE_STATE_ONLY, - }; - - void postAndWait(RenderThread* renderThread, TaskMode mode); - void syncFrameState(); + void postAndWait(RenderThread* renderThread); + bool syncFrameState(); void unblockUiThread(); static void drawRenderNode(CanvasContext* context, RenderNode* renderNode, Rect* dirty); - // This checks to see if there are any drawGlFunctors which would require - // a synchronous drawRenderNode() - static bool requiresSynchronousDraw(RenderNode* renderNode); - Mutex mLock; Condition mSignal; @@ -97,10 +73,8 @@ private: /********************************************* * Single frame data *********************************************/ - TaskMode mTaskMode; sp<RenderNode> mRenderNode; Rect mDirty; - Vector<SetDisplayListData> mDisplayListDataUpdates; /********************************************* * Multi frame data diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index e817e61..b233ae9 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -75,9 +75,6 @@ CREATE_BRIDGE1(destroyContext, CanvasContext* context) { void RenderProxy::destroyContext() { if (mContext) { - // Flush any pending changes to ensure all garbage is destroyed - mDrawFrameTask.flushStateChanges(&mRenderThread); - SETUP_TASK(destroyContext); args->context = mContext; mContext = 0; @@ -92,10 +89,10 @@ CREATE_BRIDGE2(initialize, CanvasContext* context, EGLNativeWindowType window) { return (void*) args->context->initialize(args->window); } -bool RenderProxy::initialize(EGLNativeWindowType window) { +bool RenderProxy::initialize(const sp<ANativeWindow>& window) { SETUP_TASK(initialize); args->context = mContext; - args->window = window; + args->window = window.get(); return (bool) postAndWait(task); } @@ -104,11 +101,23 @@ CREATE_BRIDGE2(updateSurface, CanvasContext* context, EGLNativeWindowType window return NULL; } -void RenderProxy::updateSurface(EGLNativeWindowType window) { +void RenderProxy::updateSurface(const sp<ANativeWindow>& window) { SETUP_TASK(updateSurface); args->context = mContext; - args->window = window; - post(task); + args->window = window.get(); + postAndWait(task); +} + +CREATE_BRIDGE2(pauseSurface, CanvasContext* context, EGLNativeWindowType window) { + args->context->pauseSurface(args->window); + return NULL; +} + +void RenderProxy::pauseSurface(const sp<ANativeWindow>& window) { + SETUP_TASK(pauseSurface); + args->context = mContext; + args->window = window.get(); + postAndWait(task); } CREATE_BRIDGE3(setup, CanvasContext* context, int width, int height) { @@ -124,10 +133,6 @@ void RenderProxy::setup(int width, int height) { post(task); } -void RenderProxy::setDisplayListData(RenderNode* renderNode, DisplayListData* newData) { - mDrawFrameTask.setDisplayListData(renderNode, newData); -} - void RenderProxy::drawDisplayList(RenderNode* displayList, int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom) { mDrawFrameTask.setRenderNode(displayList); @@ -141,45 +146,18 @@ CREATE_BRIDGE1(destroyCanvas, CanvasContext* context) { } void RenderProxy::destroyCanvas() { - // If the canvas is being destroyed we won't be drawing again anytime soon - // So flush any pending state changes to allow for resource cleanup. - mDrawFrameTask.flushStateChanges(&mRenderThread); - SETUP_TASK(destroyCanvas); args->context = mContext; post(task); } -CREATE_BRIDGE2(attachFunctor, CanvasContext* context, Functor* functor) { - args->context->attachFunctor(args->functor); - return NULL; -} - -void RenderProxy::attachFunctor(Functor* functor) { - SETUP_TASK(attachFunctor); - args->context = mContext; - args->functor = functor; - post(task); -} - -CREATE_BRIDGE2(detachFunctor, CanvasContext* context, Functor* functor) { - args->context->detachFunctor(args->functor); - return NULL; -} - -void RenderProxy::detachFunctor(Functor* functor) { - SETUP_TASK(detachFunctor); - args->context = mContext; - args->functor = functor; - post(task); -} - CREATE_BRIDGE2(invokeFunctor, CanvasContext* context, Functor* functor) { args->context->invokeFunctor(args->functor); return NULL; } void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { + ATRACE_CALL(); SETUP_TASK(invokeFunctor); args->context = mContext; args->functor = functor; diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index c50da79..3eb8ed8 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -59,16 +59,14 @@ public: ANDROID_API RenderProxy(bool translucent); ANDROID_API virtual ~RenderProxy(); - ANDROID_API bool initialize(EGLNativeWindowType window); - ANDROID_API void updateSurface(EGLNativeWindowType window); + ANDROID_API bool initialize(const sp<ANativeWindow>& window); + ANDROID_API void updateSurface(const sp<ANativeWindow>& window); + ANDROID_API void pauseSurface(const sp<ANativeWindow>& window); ANDROID_API void setup(int width, int height); - ANDROID_API void setDisplayListData(RenderNode* renderNode, DisplayListData* newData); ANDROID_API void drawDisplayList(RenderNode* displayList, int dirtyLeft, int dirtyTop, int dirtyRight, int dirtyBottom); ANDROID_API void destroyCanvas(); - ANDROID_API void attachFunctor(Functor* functor); - ANDROID_API void detachFunctor(Functor* functor); ANDROID_API void invokeFunctor(Functor* functor, bool waitForCompletion); ANDROID_API void runWithGlContext(RenderTask* task); |