diff options
Diffstat (limited to 'libs/hwui')
-rw-r--r-- | libs/hwui/AnimatorManager.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/Caches.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/ClipArea.cpp | 9 | ||||
-rw-r--r-- | libs/hwui/ClipArea.h | 2 | ||||
-rw-r--r-- | libs/hwui/RenderNode.cpp | 11 | ||||
-rw-r--r-- | libs/hwui/SkiaShader.cpp | 8 | ||||
-rw-r--r-- | libs/hwui/Texture.h | 2 | ||||
-rw-r--r-- | libs/hwui/TextureCache.cpp | 20 | ||||
-rw-r--r-- | libs/hwui/TextureCache.h | 27 | ||||
-rw-r--r-- | libs/hwui/TreeInfo.h | 2 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 21 | ||||
-rw-r--r-- | libs/hwui/renderthread/DrawFrameTask.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/renderthread/EglManager.cpp | 12 | ||||
-rw-r--r-- | libs/hwui/renderthread/EglManager.h | 2 | ||||
-rw-r--r-- | libs/hwui/unit_tests/ClipAreaTests.cpp | 11 |
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()); +} } } |