summaryrefslogtreecommitdiffstats
path: root/libs/hwui
diff options
context:
space:
mode:
Diffstat (limited to 'libs/hwui')
-rw-r--r--libs/hwui/AnimatorManager.cpp2
-rw-r--r--libs/hwui/Caches.cpp5
-rw-r--r--libs/hwui/ClipArea.cpp9
-rw-r--r--libs/hwui/ClipArea.h2
-rw-r--r--libs/hwui/RenderNode.cpp11
-rw-r--r--libs/hwui/SkiaShader.cpp8
-rw-r--r--libs/hwui/Texture.h2
-rw-r--r--libs/hwui/TextureCache.cpp20
-rw-r--r--libs/hwui/TextureCache.h27
-rw-r--r--libs/hwui/TreeInfo.h2
-rw-r--r--libs/hwui/renderthread/CanvasContext.cpp21
-rw-r--r--libs/hwui/renderthread/DrawFrameTask.cpp2
-rw-r--r--libs/hwui/renderthread/EglManager.cpp12
-rw-r--r--libs/hwui/renderthread/EglManager.h2
-rw-r--r--libs/hwui/unit_tests/ClipAreaTests.cpp11
15 files changed, 90 insertions, 46 deletions
diff --git a/libs/hwui/AnimatorManager.cpp b/libs/hwui/AnimatorManager.cpp
index 966959a..0dababd 100644
--- a/libs/hwui/AnimatorManager.cpp
+++ b/libs/hwui/AnimatorManager.cpp
@@ -117,7 +117,6 @@ uint32_t AnimatorManager::animate(TreeInfo& info) {
uint32_t dirty = animateCommon(info);
- mParent.mProperties.updateMatrix();
info.damageAccumulator->pushTransform(&mParent);
mParent.damageSelf(info);
@@ -136,6 +135,7 @@ uint32_t AnimatorManager::animateCommon(TreeInfo& info) {
newEnd = std::remove_if(mAnimators.begin(), mAnimators.end(), functor);
mAnimators.erase(newEnd, mAnimators.end());
mAnimationHandle->notifyAnimationsRan();
+ mParent.mProperties.updateMatrix();
return functor.dirtyMask;
}
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 1030451..aa73d44 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -248,11 +248,6 @@ void Caches::clearGarbage() {
void Caches::flush(FlushMode mode) {
FLUSH_LOGD("Flushing caches (mode %d)", mode);
- // We must stop tasks before clearing caches
- if (mode > kFlushMode_Layers) {
- tasks.stop();
- }
-
switch (mode) {
case kFlushMode_Full:
textureCache.clear();
diff --git a/libs/hwui/ClipArea.cpp b/libs/hwui/ClipArea.cpp
index eb520b4..b1a6844 100644
--- a/libs/hwui/ClipArea.cpp
+++ b/libs/hwui/ClipArea.cpp
@@ -263,10 +263,11 @@ void ClipArea::enterRectangleMode() {
bool ClipArea::rectangleModeClipRectWithTransform(const Rect& r,
const mat4* transform, SkRegion::Op op) {
- // TODO: we should be able to handle kReplace_Op efficiently without
- // going through RegionMode and later falling back into RectangleMode.
-
- if (op != SkRegion::kIntersect_Op) {
+ if (op == SkRegion::kReplace_Op && transform->rectToRect()) {
+ mClipRect = r;
+ transform->mapRect(mClipRect);
+ return true;
+ } else if (op != SkRegion::kIntersect_Op) {
enterRegionMode();
return regionModeClipRectWithTransform(r, transform, op);
}
diff --git a/libs/hwui/ClipArea.h b/libs/hwui/ClipArea.h
index e284af0..51ef27b 100644
--- a/libs/hwui/ClipArea.h
+++ b/libs/hwui/ClipArea.h
@@ -153,6 +153,8 @@ private:
}
void regionFromPath(const SkPath& path, SkRegion& pathAsRegion) {
+ // TODO: this should not mask every path to the viewport - this makes it impossible to use
+ // paths to clip to larger areas (which is valid e.g. with SkRegion::kReplace_Op)
pathAsRegion.setPath(path, createViewportRegion());
}
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 80f349a..0951fc1 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -214,10 +214,10 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
info.renderer->pushLayerUpdate(mLayer);
}
- if (CC_UNLIKELY(info.canvasContext)) {
- // If canvasContext is not null that means there are prefetched layers
- // that need to be accounted for. That might be us, so tell CanvasContext
- // that this layer is in the tree and should not be destroyed.
+ if (info.canvasContext) {
+ // There might be prefetched layers that need to be accounted for.
+ // That might be us, so tell CanvasContext that this layer is in the
+ // tree and should not be destroyed.
info.canvasContext->markLayerInUse(this);
}
}
@@ -339,7 +339,8 @@ void RenderNode::prepareSubTree(TreeInfo& info, bool functorsNeedLayer, DisplayL
TextureCache& cache = Caches::getInstance().textureCache;
info.out.hasFunctors |= subtree->functors.size();
for (size_t i = 0; info.prepareTextures && i < subtree->bitmapResources.size(); i++) {
- info.prepareTextures = cache.prefetchAndMarkInUse(subtree->bitmapResources[i]);
+ info.prepareTextures = cache.prefetchAndMarkInUse(
+ info.canvasContext, subtree->bitmapResources[i]);
}
for (size_t i = 0; i < subtree->children().size(); i++) {
DrawRenderNodeOp* op = subtree->children()[i];
diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp
index a2aa2d1..81d8516 100644
--- a/libs/hwui/SkiaShader.cpp
+++ b/libs/hwui/SkiaShader.cpp
@@ -203,7 +203,13 @@ bool tryStoreBitmap(Caches& caches, const SkShader& shader, const Matrix4& model
return false;
}
- outData->bitmapTexture = caches.textureCache.get(&bitmap);
+ /*
+ * Bypass the AssetAtlas, since those textures:
+ * 1) require UV mapping, which isn't implemented in matrix computation below
+ * 2) can't handle REPEAT simply
+ * 3) are safe to upload here (outside of sync stage), since they're static
+ */
+ outData->bitmapTexture = caches.textureCache.getAndBypassAtlas(&bitmap);
if (!outData->bitmapTexture) return false;
outData->bitmapSampler = (*textureUnit)++;
diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h
index 7227ce0..4bcd96d 100644
--- a/libs/hwui/Texture.h
+++ b/libs/hwui/Texture.h
@@ -97,7 +97,7 @@ public:
* Whether or not the Texture is marked in use and thus not evictable for
* the current frame. This is reset at the start of a new frame.
*/
- bool isInUse = false;
+ void* isInUse = nullptr;
private:
/**
diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp
index fe1b7fd..fda0091 100644
--- a/libs/hwui/TextureCache.cpp
+++ b/libs/hwui/TextureCache.cpp
@@ -122,10 +122,12 @@ void TextureCache::setAssetAtlas(AssetAtlas* assetAtlas) {
mAssetAtlas = assetAtlas;
}
-void TextureCache::resetMarkInUse() {
+void TextureCache::resetMarkInUse(void* ownerToken) {
LruCache<uint32_t, Texture*>::Iterator iter(mCache);
while (iter.next()) {
- iter.value()->isInUse = false;
+ if (iter.value()->isInUse == ownerToken) {
+ iter.value()->isInUse = nullptr;
+ }
}
}
@@ -140,8 +142,8 @@ bool TextureCache::canMakeTextureFromBitmap(const SkBitmap* bitmap) {
// Returns a prepared Texture* that either is already in the cache or can fit
// in the cache (and is thus added to the cache)
-Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) {
- if (CC_LIKELY(mAssetAtlas)) {
+Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap, AtlasUsageType atlasUsageType) {
+ if (CC_LIKELY(mAssetAtlas != nullptr) && atlasUsageType == AtlasUsageType::Use) {
AssetAtlas::Entry* entry = mAssetAtlas->getEntry(bitmap);
if (CC_UNLIKELY(entry)) {
return entry->texture;
@@ -189,16 +191,16 @@ Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap) {
return texture;
}
-bool TextureCache::prefetchAndMarkInUse(const SkBitmap* bitmap) {
- Texture* texture = getCachedTexture(bitmap);
+bool TextureCache::prefetchAndMarkInUse(void* ownerToken, const SkBitmap* bitmap) {
+ Texture* texture = getCachedTexture(bitmap, AtlasUsageType::Use);
if (texture) {
- texture->isInUse = true;
+ texture->isInUse = ownerToken;
}
return texture;
}
-Texture* TextureCache::get(const SkBitmap* bitmap) {
- Texture* texture = getCachedTexture(bitmap);
+Texture* TextureCache::get(const SkBitmap* bitmap, AtlasUsageType atlasUsageType) {
+ Texture* texture = getCachedTexture(bitmap, atlasUsageType);
if (!texture) {
if (!canMakeTextureFromBitmap(bitmap)) {
diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h
index e7fc990..7a7ee5a 100644
--- a/libs/hwui/TextureCache.h
+++ b/libs/hwui/TextureCache.h
@@ -66,20 +66,30 @@ public:
/**
* Resets all Textures to not be marked as in use
*/
- void resetMarkInUse();
+ void resetMarkInUse(void* ownerToken);
/**
* Attempts to precache the SkBitmap. Returns true if a Texture was successfully
* acquired for the bitmap, false otherwise. If a Texture was acquired it is
* marked as in use.
*/
- bool prefetchAndMarkInUse(const SkBitmap* bitmap);
+ bool prefetchAndMarkInUse(void* ownerToken, const SkBitmap* bitmap);
/**
- * Returns the texture associated with the specified bitmap. If the texture
- * cannot be found in the cache, a new texture is generated.
+ * Returns the texture associated with the specified bitmap from either within the cache, or
+ * the AssetAtlas. If the texture cannot be found in the cache, a new texture is generated.
*/
- Texture* get(const SkBitmap* bitmap);
+ Texture* get(const SkBitmap* bitmap) {
+ return get(bitmap, AtlasUsageType::Use);
+ }
+
+ /**
+ * Returns the texture associated with the specified bitmap. If the texture cannot be found in
+ * the cache, a new texture is generated, even if it resides in the AssetAtlas.
+ */
+ Texture* getAndBypassAtlas(const SkBitmap* bitmap) {
+ return get(bitmap, AtlasUsageType::Bypass);
+ }
/**
* Removes the texture associated with the specified pixelRef. This is meant
@@ -123,10 +133,15 @@ public:
void setAssetAtlas(AssetAtlas* assetAtlas);
private:
+ enum class AtlasUsageType {
+ Use,
+ Bypass,
+ };
bool canMakeTextureFromBitmap(const SkBitmap* bitmap);
- Texture* getCachedTexture(const SkBitmap* bitmap);
+ Texture* get(const SkBitmap* bitmap, AtlasUsageType atlasUsageType);
+ Texture* getCachedTexture(const SkBitmap* bitmap, AtlasUsageType atlasUsageType);
/**
* Generates the texture from a bitmap into the specified texture structure.
diff --git a/libs/hwui/TreeInfo.h b/libs/hwui/TreeInfo.h
index 0799c6c..ed853f7 100644
--- a/libs/hwui/TreeInfo.h
+++ b/libs/hwui/TreeInfo.h
@@ -95,7 +95,7 @@ public:
// layer updates or similar. May be NULL.
OpenGLRenderer* renderer;
ErrorHandler* errorHandler;
- // TODO: Remove this? May be NULL
+ // May be NULL (TODO: can it really?)
renderthread::CanvasContext* canvasContext;
struct Out {
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 260fb6f..e472e93 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -145,7 +145,11 @@ 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 |= mEglManager.makeCurrent(mEglSurface);
+ EGLint error = 0;
+ mHaveNewSurface |= mEglManager.makeCurrent(mEglSurface, &error);
+ if (error) {
+ setSurface(nullptr);
+ }
}
void CanvasContext::processLayerUpdate(DeferredLayerUpdater* layerUpdater) {
@@ -174,16 +178,13 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t sy
info.damageAccumulator = &mDamageAccumulator;
info.renderer = mCanvas;
- if (mPrefetechedLayers.size() && info.mode == TreeInfo::MODE_FULL) {
- info.canvasContext = this;
- }
+ info.canvasContext = this;
+
mAnimationContext->startFrame(info.mode);
mRootRenderNode->prepareTree(info);
mAnimationContext->runRemainingAnimations(info);
- if (info.canvasContext) {
- freePrefetechedLayers();
- }
+ freePrefetechedLayers();
if (CC_UNLIKELY(!mNativeWindow.get())) {
mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
@@ -365,7 +366,11 @@ void CanvasContext::destroyHardwareResources() {
if (mEglManager.hasEglContext()) {
freePrefetechedLayers();
mRootRenderNode->destroyHardwareResources();
- Caches::getInstance().flush(Caches::kFlushMode_Layers);
+ Caches& caches = Caches::getInstance();
+ // Make sure to release all the textures we were owning as there won't
+ // be another draw
+ caches.textureCache.resetMarkInUse(this);
+ caches.flush(Caches::kFlushMode_Layers);
}
}
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index 6507ce8..a4ac13b 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -114,7 +114,7 @@ bool DrawFrameTask::syncFrameState(TreeInfo& info) {
int64_t vsync = mFrameInfo[static_cast<int>(FrameInfoIndex::Vsync)];
mRenderThread->timeLord().vsyncReceived(vsync);
mContext->makeCurrent();
- Caches::getInstance().textureCache.resetMarkInUse();
+ Caches::getInstance().textureCache.resetMarkInUse(mContext);
for (size_t i = 0; i < mLayers.size(); i++) {
mContext->processLayerUpdate(mLayers[i].get());
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index cb34e00..eb332d5 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -217,7 +217,7 @@ void EglManager::destroy() {
mCurrentSurface = EGL_NO_SURFACE;
}
-bool EglManager::makeCurrent(EGLSurface surface) {
+bool EglManager::makeCurrent(EGLSurface surface, EGLint* errOut) {
if (isCurrent(surface)) return false;
if (surface == EGL_NO_SURFACE) {
@@ -225,8 +225,14 @@ bool EglManager::makeCurrent(EGLSurface surface) {
surface = mPBufferSurface;
}
if (!eglMakeCurrent(mEglDisplay, surface, surface, mEglContext)) {
- LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s",
- (void*)surface, egl_error_str());
+ if (errOut) {
+ *errOut = eglGetError();
+ ALOGW("Failed to make current on surface %p, error=%s",
+ (void*)surface, egl_error_str(*errOut));
+ } else {
+ LOG_ALWAYS_FATAL("Failed to make current on surface %p, error=%s",
+ (void*)surface, egl_error_str());
+ }
}
mCurrentSurface = surface;
return true;
diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h
index 8881de6..0a8cfd3 100644
--- a/libs/hwui/renderthread/EglManager.h
+++ b/libs/hwui/renderthread/EglManager.h
@@ -44,7 +44,7 @@ public:
bool isCurrent(EGLSurface surface) { return mCurrentSurface == surface; }
// Returns true if the current surface changed, false if it was already current
- bool makeCurrent(EGLSurface surface);
+ bool makeCurrent(EGLSurface surface, EGLint* errOut = nullptr);
void beginFrame(EGLSurface surface, EGLint* width, EGLint* height);
bool swapBuffers(EGLSurface surface, const SkRect& dirty, EGLint width, EGLint height);
diff --git a/libs/hwui/unit_tests/ClipAreaTests.cpp b/libs/hwui/unit_tests/ClipAreaTests.cpp
index 166d5b6..0c5e5e7 100644
--- a/libs/hwui/unit_tests/ClipAreaTests.cpp
+++ b/libs/hwui/unit_tests/ClipAreaTests.cpp
@@ -112,5 +112,16 @@ TEST(ClipArea, paths) {
regionBounds.set(skRect);
EXPECT_EQ(expected, regionBounds);
}
+
+TEST(ClipArea, replaceNegative) {
+ ClipArea area(createClipArea());
+ area.setClip(0, 0, 100, 100);
+
+ Matrix4 transform;
+ transform.loadIdentity();
+ Rect expected(-50, -50, 50, 50);
+ area.clipRectWithTransform(expected, &transform, SkRegion::kReplace_Op);
+ EXPECT_EQ(expected, area.getClipRect());
+}
}
}