summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/hwui/DeferredLayerUpdater.cpp8
-rw-r--r--libs/hwui/DeferredLayerUpdater.h6
-rw-r--r--libs/hwui/RenderNode.cpp6
-rw-r--r--libs/hwui/hwui/Bitmap.cpp2
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp16
-rw-r--r--libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h9
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.cpp4
-rw-r--r--libs/hwui/pipeline/skia/SkiaPipeline.h2
-rw-r--r--libs/hwui/renderstate/RenderState.cpp83
-rw-r--r--libs/hwui/renderstate/RenderState.h71
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp7
-rw-r--r--libs/hwui/renderthread/CanvasContext.h6
-rw-r--r--libs/hwui/renderthread/RenderProxy.cpp7
-rw-r--r--libs/hwui/renderthread/RenderProxy.h2
-rw-r--r--libs/hwui/renderthread/RenderThread.cpp4
-rw-r--r--libs/hwui/renderthread/VulkanManager.cpp3
-rw-r--r--libs/hwui/tests/common/TestUtils.h1
-rw-r--r--libs/hwui/tests/unit/SkiaPipelineTests.cpp10
18 files changed, 71 insertions, 176 deletions
diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp
index 837d5461d2a8..b772e5b87f2a 100644
--- a/libs/hwui/DeferredLayerUpdater.cpp
+++ b/libs/hwui/DeferredLayerUpdater.cpp
@@ -29,12 +29,16 @@ DeferredLayerUpdater::DeferredLayerUpdater(RenderState& renderState)
, mGLContextAttached(false)
, mUpdateTexImage(false)
, mLayer(nullptr) {
- renderState.registerDeferredLayerUpdater(this);
+ renderState.registerContextCallback(this);
}
DeferredLayerUpdater::~DeferredLayerUpdater() {
setTransform(nullptr);
- mRenderState.unregisterDeferredLayerUpdater(this);
+ mRenderState.removeContextCallback(this);
+ destroyLayer();
+}
+
+void DeferredLayerUpdater::onContextDestroyed() {
destroyLayer();
}
diff --git a/libs/hwui/DeferredLayerUpdater.h b/libs/hwui/DeferredLayerUpdater.h
index 4c323b861002..b2c5131dd613 100644
--- a/libs/hwui/DeferredLayerUpdater.h
+++ b/libs/hwui/DeferredLayerUpdater.h
@@ -27,6 +27,7 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
+#include "renderstate/RenderState.h"
#include "surfacetexture/SurfaceTexture.h"
#include "Layer.h"
#include "Rect.h"
@@ -38,7 +39,7 @@ class RenderState;
// Container to hold the properties a layer should be set to at the start
// of a render pass
-class DeferredLayerUpdater : public VirtualLightRefBase {
+class DeferredLayerUpdater : public VirtualLightRefBase, public IGpuContextCallback {
public:
// Note that DeferredLayerUpdater assumes it is taking ownership of the layer
// and will not call incrementRef on it as a result.
@@ -98,6 +99,9 @@ public:
void destroyLayer();
+protected:
+ void onContextDestroyed() override;
+
private:
RenderState& mRenderState;
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 26e5cea2452a..06dbb2410a12 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -158,7 +158,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
CC_UNLIKELY(properties().getWidth() == 0) || CC_UNLIKELY(properties().getHeight() == 0) ||
CC_UNLIKELY(!properties().fitsOnLayer())) {
if (CC_UNLIKELY(hasLayer())) {
- renderthread::CanvasContext::destroyLayer(this);
+ this->setLayerSurface(nullptr);
}
return;
}
@@ -317,7 +317,7 @@ void RenderNode::deleteDisplayList(TreeObserver& observer, TreeInfo* info) {
void RenderNode::destroyHardwareResources(TreeInfo* info) {
if (hasLayer()) {
- renderthread::CanvasContext::destroyLayer(this);
+ this->setLayerSurface(nullptr);
}
setStagingDisplayList(nullptr);
@@ -327,7 +327,7 @@ void RenderNode::destroyHardwareResources(TreeInfo* info) {
void RenderNode::destroyLayers() {
if (hasLayer()) {
- renderthread::CanvasContext::destroyLayer(this);
+ this->setLayerSurface(nullptr);
}
if (mDisplayList) {
mDisplayList->updateChildren([](RenderNode* child) { child->destroyLayers(); });
diff --git a/libs/hwui/hwui/Bitmap.cpp b/libs/hwui/hwui/Bitmap.cpp
index 6556a6413ef5..9c284531674f 100644
--- a/libs/hwui/hwui/Bitmap.cpp
+++ b/libs/hwui/hwui/Bitmap.cpp
@@ -230,8 +230,6 @@ Bitmap::~Bitmap() {
mPixelStorage.hardware.buffer = nullptr;
break;
}
-
- android::uirenderer::renderthread::RenderProxy::onBitmapDestroyed(getStableID());
}
bool Bitmap::hasHardwareMipMap() const {
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 3b1ebd690465..e8bf4922cd46 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -21,6 +21,7 @@
#include "SkiaPipeline.h"
#include "SkiaProfileRenderer.h"
#include "hwui/Bitmap.h"
+#include "private/hwui/DrawGlInfo.h"
#include "renderstate/RenderState.h"
#include "renderthread/EglManager.h"
#include "renderthread/Frame.h"
@@ -43,7 +44,13 @@ namespace uirenderer {
namespace skiapipeline {
SkiaOpenGLPipeline::SkiaOpenGLPipeline(RenderThread& thread)
- : SkiaPipeline(thread), mEglManager(thread.eglManager()) {}
+ : SkiaPipeline(thread), mEglManager(thread.eglManager()) {
+ thread.renderState().registerContextCallback(this);
+}
+
+SkiaOpenGLPipeline::~SkiaOpenGLPipeline() {
+ mRenderThread.renderState().removeContextCallback(this);
+}
MakeCurrentResult SkiaOpenGLPipeline::makeCurrent() {
// TODO: Figure out why this workaround is needed, see b/13913604
@@ -135,6 +142,13 @@ DeferredLayerUpdater* SkiaOpenGLPipeline::createTextureLayer() {
return new DeferredLayerUpdater(mRenderThread.renderState());
}
+void SkiaOpenGLPipeline::onContextDestroyed() {
+ if (mEglSurface != EGL_NO_SURFACE) {
+ mEglManager.destroySurface(mEglSurface);
+ mEglSurface = EGL_NO_SURFACE;
+ }
+}
+
void SkiaOpenGLPipeline::onStop() {
if (mEglManager.isCurrent(mEglSurface)) {
mEglManager.makeCurrent(EGL_NO_SURFACE);
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
index fbdf3139dabd..086a76088a75 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.h
@@ -18,6 +18,8 @@
#include "SkiaPipeline.h"
+#include "renderstate/RenderState.h"
+
namespace android {
class Bitmap;
@@ -25,10 +27,10 @@ class Bitmap;
namespace uirenderer {
namespace skiapipeline {
-class SkiaOpenGLPipeline : public SkiaPipeline {
+class SkiaOpenGLPipeline : public SkiaPipeline, public IGpuContextCallback {
public:
SkiaOpenGLPipeline(renderthread::RenderThread& thread);
- virtual ~SkiaOpenGLPipeline() {}
+ virtual ~SkiaOpenGLPipeline();
renderthread::MakeCurrentResult makeCurrent() override;
renderthread::Frame getFrame() override;
@@ -50,6 +52,9 @@ public:
static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor);
+protected:
+ void onContextDestroyed() override;
+
private:
renderthread::EglManager& mEglManager;
EGLSurface mEglSurface = EGL_NO_SURFACE;
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
index 7f8abb8afa97..2dfe7c71ca1b 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp
@@ -200,10 +200,6 @@ bool SkiaPipeline::createOrUpdateLayer(RenderNode* node, const DamageAccumulator
return false;
}
-void SkiaPipeline::destroyLayer(RenderNode* node) {
- node->setLayerSurface(nullptr);
-}
-
void SkiaPipeline::prepareToDraw(const RenderThread& thread, Bitmap* bitmap) {
GrContext* context = thread.getGrContext();
if (context) {
diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h
index b78dea1a5c87..ee9158c5ffc1 100644
--- a/libs/hwui/pipeline/skia/SkiaPipeline.h
+++ b/libs/hwui/pipeline/skia/SkiaPipeline.h
@@ -54,8 +54,6 @@ public:
std::vector<VectorDrawableRoot*>* getVectorDrawables() { return &mVectorDrawables; }
- static void destroyLayer(RenderNode* node);
-
static void prepareToDraw(const renderthread::RenderThread& thread, Bitmap* bitmap);
void renderLayersImpl(const LayerUpdateQueue& layers, bool opaque);
diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp
index b524bcb096da..fad9440be73f 100644
--- a/libs/hwui/renderstate/RenderState.cpp
+++ b/libs/hwui/renderstate/RenderState.cpp
@@ -14,89 +14,26 @@
* limitations under the License.
*/
#include "renderstate/RenderState.h"
-#include <GpuMemoryTracker.h>
-#include "DeferredLayerUpdater.h"
-#include "Snapshot.h"
-#include "renderthread/CanvasContext.h"
-#include "renderthread/EglManager.h"
-#include "utils/GLUtils.h"
-
-#include <algorithm>
-
-#include <ui/ColorSpace.h>
+#include "renderthread/RenderThread.h"
+#include "GpuMemoryTracker.h"
namespace android {
namespace uirenderer {
-RenderState::RenderState(renderthread::RenderThread& thread)
- : mRenderThread(thread), mViewportWidth(0), mViewportHeight(0), mFramebuffer(0) {
+RenderState::RenderState(renderthread::RenderThread& thread) : mRenderThread(thread) {
mThreadId = pthread_self();
}
-RenderState::~RenderState() {
-}
-
void RenderState::onContextCreated() {
GpuMemoryTracker::onGpuContextCreated();
}
void RenderState::onContextDestroyed() {
- destroyLayersInUpdater();
- GpuMemoryTracker::onGpuContextDestroyed();
-}
-
-GrContext* RenderState::getGrContext() const {
- return mRenderThread.getGrContext();
-}
-
-void RenderState::onBitmapDestroyed(uint32_t pixelRefId) {
- // DEAD CODE
-}
-
-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);
+ for(auto callback : mContextCallbacks) {
+ callback->onContextDestroyed();
}
-}
-
-GLuint RenderState::createFramebuffer() {
- GLuint ret;
- glGenFramebuffers(1, &ret);
- return ret;
-}
-
-void RenderState::deleteFramebuffer(GLuint fbo) {
- if (mFramebuffer == fbo) {
- // GL defines that deleting the currently bound FBO rebinds FBO 0.
- // Reflect this in our cached value.
- mFramebuffer = 0;
- }
- glDeleteFramebuffers(1, &fbo);
-}
-
-void RenderState::debugOverdraw(bool enable, bool clear) {
- // DEAD CODE
-}
-
-static void destroyLayerInUpdater(DeferredLayerUpdater* layerUpdater) {
- layerUpdater->destroyLayer();
-}
-
-void RenderState::destroyLayersInUpdater() {
- std::for_each(mActiveLayerUpdaters.begin(), mActiveLayerUpdaters.end(), destroyLayerInUpdater);
+ GpuMemoryTracker::onGpuContextDestroyed();
}
void RenderState::postDecStrong(VirtualLightRefBase* object) {
@@ -111,13 +48,5 @@ void RenderState::postDecStrong(VirtualLightRefBase* object) {
// Render
///////////////////////////////////////////////////////////////////////////////
-void RenderState::dump() {
- // DEAD CODE
-}
-
-renderthread::RenderThread& RenderState::getRenderThread() {
- return mRenderThread;
-}
-
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderstate/RenderState.h b/libs/hwui/renderstate/RenderState.h
index f39aa4b96547..ff5d02fe359a 100644
--- a/libs/hwui/renderstate/RenderState.h
+++ b/libs/hwui/renderstate/RenderState.h
@@ -18,29 +18,26 @@
#include "utils/Macros.h"
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-#include <private/hwui/DrawGlInfo.h>
-#include <ui/Region.h>
-#include <utils/Functor.h>
-#include <utils/Mutex.h>
#include <utils/RefBase.h>
#include <set>
-class GrContext;
-
namespace android {
namespace uirenderer {
class Layer;
-class DeferredLayerUpdater;
namespace renderthread {
class CacheManager;
-class CanvasContext;
class RenderThread;
}
+class IGpuContextCallback {
+public:
+ virtual void onContextDestroyed() = 0;
+protected:
+ virtual ~IGpuContextCallback() {}
+};
+
// wrapper of Caches for users to migrate to.
class RenderState {
PREVENT_COPY_AND_ASSIGN(RenderState);
@@ -48,66 +45,30 @@ class RenderState {
friend class renderthread::CacheManager;
public:
- void onContextCreated();
- void onContextDestroyed();
-
- void onBitmapDestroyed(uint32_t pixelRefId);
-
- void setViewport(GLsizei width, GLsizei height);
- void getViewport(GLsizei* outWidth, GLsizei* outHeight);
-
- void bindFramebuffer(GLuint fbo);
- GLuint getFramebuffer() { return mFramebuffer; }
- GLuint createFramebuffer();
- void deleteFramebuffer(GLuint fbo);
-
- void debugOverdraw(bool enable, bool clear);
+ void registerContextCallback(IGpuContextCallback* cb) { mContextCallbacks.insert(cb); }
+ void removeContextCallback(IGpuContextCallback* cb) { mContextCallbacks.erase(cb); }
void registerLayer(Layer* layer) { mActiveLayers.insert(layer); }
void unregisterLayer(Layer* layer) { mActiveLayers.erase(layer); }
- void registerCanvasContext(renderthread::CanvasContext* context) {
- mRegisteredContexts.insert(context);
- }
-
- void unregisterCanvasContext(renderthread::CanvasContext* context) {
- mRegisteredContexts.erase(context);
- }
-
- void registerDeferredLayerUpdater(DeferredLayerUpdater* layerUpdater) {
- mActiveLayerUpdaters.insert(layerUpdater);
- }
-
- void unregisterDeferredLayerUpdater(DeferredLayerUpdater* layerUpdater) {
- mActiveLayerUpdaters.erase(layerUpdater);
- }
-
// TODO: This system is a little clunky feeling, this could use some
// more thinking...
void postDecStrong(VirtualLightRefBase* object);
- GrContext* getGrContext() const;
-
- void dump();
-
- renderthread::RenderThread& getRenderThread();
+ renderthread::RenderThread& getRenderThread() const { return mRenderThread; }
private:
- void destroyLayersInUpdater();
-
explicit RenderState(renderthread::RenderThread& thread);
- ~RenderState();
+ ~RenderState() {}
- renderthread::RenderThread& mRenderThread;
+ // Context notifications are only to be triggered by renderthread::RenderThread
+ void onContextCreated();
+ void onContextDestroyed();
+ std::set<IGpuContextCallback*> mContextCallbacks;
std::set<Layer*> mActiveLayers;
- std::set<DeferredLayerUpdater*> mActiveLayerUpdaters;
- std::set<renderthread::CanvasContext*> mRegisteredContexts;
-
- GLsizei mViewportWidth;
- GLsizei mViewportHeight;
- GLuint mFramebuffer;
+ renderthread::RenderThread& mRenderThread;
pthread_t mThreadId;
};
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index ea6a851419c0..c8c394a72541 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -27,7 +27,6 @@
#include "pipeline/skia/SkiaOpenGLPipeline.h"
#include "pipeline/skia/SkiaPipeline.h"
#include "pipeline/skia/SkiaVulkanPipeline.h"
-#include "renderstate/RenderState.h"
#include "utils/GLUtils.h"
#include "utils/TimeUtils.h"
#include "../Properties.h"
@@ -76,10 +75,6 @@ CanvasContext* CanvasContext::create(RenderThread& thread, bool translucent,
return nullptr;
}
-void CanvasContext::destroyLayer(RenderNode* node) {
- skiapipeline::SkiaPipeline::destroyLayer(node);
-}
-
void CanvasContext::invokeFunctor(const RenderThread& thread, Functor* functor) {
ATRACE_CALL();
auto renderType = Properties::getRenderPipelineType();
@@ -113,13 +108,11 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, RenderNode*
, mRenderPipeline(std::move(renderPipeline)) {
rootRenderNode->makeRoot();
mRenderNodes.emplace_back(rootRenderNode);
- mRenderThread.renderState().registerCanvasContext(this);
mProfiler.setDensity(mRenderThread.mainDisplayInfo().density);
}
CanvasContext::~CanvasContext() {
destroy();
- mRenderThread.renderState().unregisterCanvasContext(this);
for (auto& node : mRenderNodes) {
node->clearRoot();
}
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index 8448788eb9a6..2315cb9c73f9 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -96,12 +96,6 @@ public:
*/
void unpinImages() { mRenderPipeline->unpinImages(); }
- /**
- * Destroy any layers that have been attached to the provided RenderNode removing
- * any state that may have been set during createOrUpdateLayer().
- */
- static void destroyLayer(RenderNode* node);
-
static void invokeFunctor(const RenderThread& thread, Functor* functor);
static void prepareToDraw(const RenderThread& thread, Bitmap* bitmap);
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 7a5348ac85d9..6106e24c093b 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -345,13 +345,6 @@ int RenderProxy::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) {
}
}
-void RenderProxy::onBitmapDestroyed(uint32_t pixelRefId) {
- if (!RenderThread::hasInstance()) return;
- RenderThread& thread = RenderThread::getInstance();
- thread.queue().post(
- [&thread, pixelRefId]() { thread.renderState().onBitmapDestroyed(pixelRefId); });
-}
-
void RenderProxy::disableVsync() {
Properties::disableVsync = true;
}
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 969ad00d7443..d22f56ef38fd 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -127,8 +127,6 @@ public:
static int copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap);
- static void onBitmapDestroyed(uint32_t pixelRefId);
-
ANDROID_API static void disableVsync();
static void repackVectorDrawableAtlas();
diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp
index a5dcc72636d1..207673c1c8dd 100644
--- a/libs/hwui/renderthread/RenderThread.cpp
+++ b/libs/hwui/renderthread/RenderThread.cpp
@@ -177,7 +177,6 @@ void RenderThread::requireGlContext() {
return;
}
mEglManager->initialize();
- renderState().onContextCreated();
#ifdef HWUI_GLES_WRAP_ENABLED
debug::GlesDriver* driver = debug::GlesDriver::get();
@@ -201,7 +200,6 @@ void RenderThread::requireGlContext() {
void RenderThread::destroyGlContext() {
if (mEglManager->hasEglContext()) {
setGrContext(nullptr);
- renderState().onContextDestroyed();
mEglManager->destroy();
}
}
@@ -243,10 +241,12 @@ Readback& RenderThread::readback() {
void RenderThread::setGrContext(sk_sp<GrContext> context) {
mCacheManager->reset(context);
if (mGrContext) {
+ mRenderState->onContextDestroyed();
mGrContext->releaseResourcesAndAbandonContext();
}
mGrContext = std::move(context);
if (mGrContext) {
+ mRenderState->onContextCreated();
DeviceInfo::setMaxTextureSize(mGrContext->maxRenderTargetSize());
}
}
diff --git a/libs/hwui/renderthread/VulkanManager.cpp b/libs/hwui/renderthread/VulkanManager.cpp
index 488117253e7a..e60d43e4001e 100644
--- a/libs/hwui/renderthread/VulkanManager.cpp
+++ b/libs/hwui/renderthread/VulkanManager.cpp
@@ -39,7 +39,6 @@ namespace renderthread {
VulkanManager::VulkanManager(RenderThread& thread) : mRenderThread(thread) {}
void VulkanManager::destroy() {
- mRenderThread.renderState().onContextDestroyed();
mRenderThread.setGrContext(nullptr);
if (VK_NULL_HANDLE != mCommandPool) {
@@ -401,8 +400,6 @@ void VulkanManager::initialize() {
if (Properties::enablePartialUpdates && Properties::useBufferAge) {
mSwapBehavior = SwapBehavior::BufferAge;
}
-
- mRenderThread.renderState().onContextCreated();
}
// Returns the next BackbufferInfo to use for the next draw. The function will make sure all
diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h
index c35f512553d8..a00b8db3c617 100644
--- a/libs/hwui/tests/common/TestUtils.h
+++ b/libs/hwui/tests/common/TestUtils.h
@@ -24,6 +24,7 @@
#include <Snapshot.h>
#include <hwui/Bitmap.h>
#include <pipeline/skia/SkiaRecordingCanvas.h>
+#include <private/hwui/DrawGlInfo.h>
#include <renderstate/RenderState.h>
#include <renderthread/RenderThread.h>
diff --git a/libs/hwui/tests/unit/SkiaPipelineTests.cpp b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
index 5e5d13485942..680fcb3a732b 100644
--- a/libs/hwui/tests/unit/SkiaPipelineTests.cpp
+++ b/libs/hwui/tests/unit/SkiaPipelineTests.cpp
@@ -382,3 +382,13 @@ RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, clip_replace) {
SkRect::MakeWH(CANVAS_WIDTH, CANVAS_HEIGHT), surface);
EXPECT_EQ(1, surface->canvas()->mDrawCounter);
}
+
+RENDERTHREAD_SKIA_PIPELINE_TEST(SkiaPipeline, context_lost) {
+ auto pipeline = std::make_unique<SkiaOpenGLPipeline>(renderThread);
+ EXPECT_FALSE(pipeline->isSurfaceReady());
+ EXPECT_TRUE(pipeline->setSurface((Surface*)0x01, SwapBehavior::kSwap_default, ColorMode::Legacy));
+ EXPECT_TRUE(pipeline->isSurfaceReady());
+ renderThread.destroyGlContext();
+ EXPECT_FALSE(pipeline->isSurfaceReady());
+}
+