diff options
Diffstat (limited to 'libs/hwui')
-rw-r--r-- | libs/hwui/AssetAtlas.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/AssetAtlas.h | 26 | ||||
-rw-r--r-- | libs/hwui/DisplayList.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/DisplayListCanvas.h | 7 | ||||
-rw-r--r-- | libs/hwui/Properties.cpp | 5 | ||||
-rw-r--r-- | libs/hwui/Properties.h | 19 | ||||
-rw-r--r-- | libs/hwui/ResourceCache.cpp | 70 | ||||
-rw-r--r-- | libs/hwui/ResourceCache.h | 40 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.cpp | 47 | ||||
-rw-r--r-- | libs/hwui/renderthread/CanvasContext.h | 3 | ||||
-rw-r--r-- | libs/hwui/renderthread/EglManager.cpp | 38 | ||||
-rw-r--r-- | libs/hwui/renderthread/EglManager.h | 3 | ||||
-rw-r--r-- | libs/hwui/renderthread/RenderProxy.cpp | 1 |
13 files changed, 91 insertions, 179 deletions
diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp index 882826e..2889d2f 100644 --- a/libs/hwui/AssetAtlas.cpp +++ b/libs/hwui/AssetAtlas.cpp @@ -112,9 +112,6 @@ private: Texture* const mDelegate; }; // struct DelegateTexture -/** - * TODO: This method does not take the rotation flag into account - */ void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) { const float width = float(mTexture->width); const float height = float(mTexture->height); @@ -128,7 +125,6 @@ void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) { // pointers on 64 bit architectures. const int x = static_cast<int>(map[i++]); const int y = static_cast<int>(map[i++]); - bool rotated = map[i++] > 0; // Bitmaps should never be null, we're just extra paranoid if (!pixelRef) continue; @@ -142,7 +138,7 @@ void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) { texture->width = pixelRef->info().width(); texture->height = pixelRef->info().height(); - Entry* entry = new Entry(pixelRef, x, y, rotated, texture, mapper, *this); + Entry* entry = new Entry(pixelRef, texture, mapper, *this); texture->uvMapper = &entry->uvMapper; mEntries.add(entry->pixelRef, entry); diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h index 17c5281..f1cd0b4 100644 --- a/libs/hwui/AssetAtlas.h +++ b/libs/hwui/AssetAtlas.h @@ -45,8 +45,8 @@ class Image; class AssetAtlas { public: /** - * Entry representing the position and rotation of a - * bitmap inside the atlas. + * Entry representing the texture and uvMapper of a PixelRef in the + * atlas */ class Entry { public: @@ -78,30 +78,15 @@ public: SkPixelRef* pixelRef; /** - * Location of the bitmap inside the atlas, in pixels. - */ - int x; - int y; - - /** - * If set, the bitmap is rotated 90 degrees (clockwise) - * inside the atlas. - */ - bool rotated; - - /** * Atlas this entry belongs to. */ const AssetAtlas& atlas; - Entry(SkPixelRef* pixelRef, int x, int y, bool rotated, - Texture* texture, const UvMapper& mapper, const AssetAtlas& atlas) + Entry(SkPixelRef* pixelRef, Texture* texture, const UvMapper& mapper, + const AssetAtlas& atlas) : texture(texture) , uvMapper(mapper) , pixelRef(pixelRef) - , x(x) - , y(y) - , rotated(rotated) , atlas(atlas) { } @@ -120,8 +105,7 @@ public: * Initializes the atlas with the specified buffer and * map. The buffer is a gralloc'd texture that will be * used as an EGLImage. The map is a list of SkBitmap* - * and their (x, y) positions as well as their rotation - * flags. + * and their (x, y) positions * * This method returns immediately if the atlas is already * initialized. To re-initialize the atlas, you must diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index 4540bec..e679bff 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -41,10 +41,6 @@ void DisplayListData::cleanupResources() { ResourceCache& resourceCache = ResourceCache::getInstance(); resourceCache.lock(); - for (size_t i = 0; i < bitmapResources.size(); i++) { - resourceCache.decrementRefcountLocked(bitmapResources.itemAt(i)); - } - for (size_t i = 0; i < patchResources.size(); i++) { resourceCache.decrementRefcountLocked(patchResources.itemAt(i)); } @@ -59,7 +55,6 @@ void DisplayListData::cleanupResources() { delete path; } - bitmapResources.clear(); patchResources.clear(); pathResources.clear(); paints.clear(); diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h index 0064236..d997ef4 100644 --- a/libs/hwui/DisplayListCanvas.h +++ b/libs/hwui/DisplayListCanvas.h @@ -350,9 +350,10 @@ private: // correctly, such as creating the bitmap from scratch, drawing with it, changing its // contents, and drawing again. The only fix would be to always copy it the first time, // which doesn't seem worth the extra cycles for this unlikely case. - const SkBitmap* cachedBitmap = mResourceCache.insert(bitmap); - mDisplayListData->bitmapResources.add(cachedBitmap); - return cachedBitmap; + SkBitmap* localBitmap = new (alloc()) SkBitmap(bitmap); + alloc().autoDestroy(localBitmap); + mDisplayListData->bitmapResources.push_back(localBitmap); + return localBitmap; } inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) { diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index fd32b6f..723a177 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -28,6 +28,8 @@ bool Properties::drawReorderDisabled = false; bool Properties::debugLayersUpdates = false; bool Properties::debugOverdraw = false; bool Properties::showDirtyRegions = false; +bool Properties::skipEmptyFrames = true; +bool Properties::swapBuffersWithDamage = false; DebugLevel Properties::debugLevel = kDebugDisabled; OverdrawColorSet Properties::overdrawColorSet = OverdrawColorSet::Default; @@ -101,6 +103,9 @@ bool Properties::load() { debugLevel = (DebugLevel) atoi(property); } + skipEmptyFrames = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE, true); + swapBuffersWithDamage = property_get_bool(PROPERTY_SWAP_WITH_DAMAGE, false); + return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw) || (prevDebugStencilClip != debugStencilClip); diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 46fa940..cb5560f 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -158,6 +158,21 @@ enum DebugLevel { */ #define PROPERTY_DISABLE_DRAW_REORDER "debug.hwui.disable_draw_reorder" +/** + * Setting this property will enable or disable the dropping of frames with + * empty damage. Default is "true". + */ +#define PROPERTY_SKIP_EMPTY_DAMAGE "debug.hwui.skip_empty_damage" + +/** + * Setting this property will enable usage of EGL_KHR_swap_buffers_with_damage + * See: https://www.khronos.org/registry/egl/extensions/KHR/EGL_KHR_swap_buffers_with_damage.txt + * Default is "false" temporarily + * TODO: Change to "true", make sure to remove the log in EglManager::swapBuffers + * before changing this to default to true! + */ +#define PROPERTY_SWAP_WITH_DAMAGE "debug.hwui.swap_with_damage" + /////////////////////////////////////////////////////////////////////////////// // Runtime configuration properties /////////////////////////////////////////////////////////////////////////////// @@ -288,6 +303,10 @@ public: static bool debugLayersUpdates; static bool debugOverdraw; static bool showDirtyRegions; + // TODO: Remove after stabilization period + static bool skipEmptyFrames; + // TODO: Remove after stabilization period + static bool swapBuffersWithDamage; static DebugLevel debugLevel; static OverdrawColorSet overdrawColorSet; diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp index 454fedc..75d8134 100644 --- a/libs/hwui/ResourceCache.cpp +++ b/libs/hwui/ResourceCache.cpp @@ -59,21 +59,6 @@ void ResourceCache::unlock() { mLock.unlock(); } -const SkBitmap* ResourceCache::insert(const SkBitmap& bitmapResource) { - Mutex::Autolock _l(mLock); - - BitmapKey bitmapKey(bitmapResource); - ssize_t index = mBitmapCache.indexOfKey(bitmapKey); - if (index == NAME_NOT_FOUND) { - SkBitmap* cachedBitmap = new SkBitmap(bitmapResource); - index = mBitmapCache.add(bitmapKey, cachedBitmap); - return cachedBitmap; - } - - mBitmapCache.keyAt(index).mRefCount++; - return mBitmapCache.valueAt(index); -} - void ResourceCache::incrementRefcount(void* resource, ResourceType resourceType) { Mutex::Autolock _l(mLock); incrementRefcountLocked(resource, resourceType); @@ -98,11 +83,6 @@ void ResourceCache::decrementRefcount(void* resource) { decrementRefcountLocked(resource); } -void ResourceCache::decrementRefcount(const SkBitmap* bitmapResource) { - Mutex::Autolock _l(mLock); - decrementRefcountLocked(bitmapResource); -} - void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) { decrementRefcount((void*) patchResource); } @@ -120,23 +100,6 @@ void ResourceCache::decrementRefcountLocked(void* resource) { } } -void ResourceCache::decrementRefcountLocked(const SkBitmap* bitmapResource) { - BitmapKey bitmapKey(*bitmapResource); - ssize_t index = mBitmapCache.indexOfKey(bitmapKey); - - LOG_ALWAYS_FATAL_IF(index == NAME_NOT_FOUND, - "Decrementing the reference of an untracked Bitmap"); - - const BitmapKey& cacheEntry = mBitmapCache.keyAt(index); - if (cacheEntry.mRefCount == 1) { - // delete the bitmap and remove it from the cache - delete mBitmapCache.valueAt(index); - mBitmapCache.removeItemsAt(index); - } else { - cacheEntry.mRefCount--; - } -} - void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) { decrementRefcountLocked((void*) patchResource); } @@ -190,38 +153,5 @@ void ResourceCache::deleteResourceReferenceLocked(const void* resource, Resource delete ref; } -/////////////////////////////////////////////////////////////////////////////// -// Bitmap Key -/////////////////////////////////////////////////////////////////////////////// - -void BitmapKey::operator=(const BitmapKey& other) { - this->mRefCount = other.mRefCount; - this->mBitmapDimensions = other.mBitmapDimensions; - this->mPixelRefOrigin = other.mPixelRefOrigin; - this->mPixelRefStableID = other.mPixelRefStableID; -} - -bool BitmapKey::operator==(const BitmapKey& other) const { - return mPixelRefStableID == other.mPixelRefStableID && - mPixelRefOrigin == other.mPixelRefOrigin && - mBitmapDimensions == other.mBitmapDimensions; -} - -bool BitmapKey::operator<(const BitmapKey& other) const { - if (mPixelRefStableID != other.mPixelRefStableID) { - return mPixelRefStableID < other.mPixelRefStableID; - } - if (mPixelRefOrigin.x() != other.mPixelRefOrigin.x()) { - return mPixelRefOrigin.x() < other.mPixelRefOrigin.x(); - } - if (mPixelRefOrigin.y() != other.mPixelRefOrigin.y()) { - return mPixelRefOrigin.y() < other.mPixelRefOrigin.y(); - } - if (mBitmapDimensions.width() != other.mBitmapDimensions.width()) { - return mBitmapDimensions.width() < other.mBitmapDimensions.width(); - } - return mBitmapDimensions.height() < other.mBitmapDimensions.height(); -} - }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h index 6c483fa..4583c8d 100644 --- a/libs/hwui/ResourceCache.h +++ b/libs/hwui/ResourceCache.h @@ -51,37 +51,6 @@ public: ResourceType resourceType; }; -class BitmapKey { -public: - BitmapKey(const SkBitmap& bitmap) - : mRefCount(1) - , mBitmapDimensions(bitmap.dimensions()) - , mPixelRefOrigin(bitmap.pixelRefOrigin()) - , mPixelRefStableID(bitmap.pixelRef()->getStableID()) { } - - void operator=(const BitmapKey& other); - bool operator==(const BitmapKey& other) const; - bool operator<(const BitmapKey& other) const; - -private: - // This constructor is only used by the KeyedVector implementation - BitmapKey() - : mRefCount(-1) - , mBitmapDimensions(SkISize::Make(0,0)) - , mPixelRefOrigin(SkIPoint::Make(0,0)) - , mPixelRefStableID(0) { } - - // reference count of all HWUI object using this bitmap - mutable int mRefCount; - - SkISize mBitmapDimensions; - SkIPoint mPixelRefOrigin; - uint32_t mPixelRefStableID; - - friend class ResourceCache; - friend struct android::key_value_pair_t<BitmapKey, SkBitmap*>; -}; - class ANDROID_API ResourceCache: public Singleton<ResourceCache> { ResourceCache(); ~ResourceCache(); @@ -97,18 +66,10 @@ public: void lock(); void unlock(); - /** - * The cache stores a copy of the provided resource or refs an existing resource - * if the bitmap has previously been inserted and returns the cached copy. - */ - const SkBitmap* insert(const SkBitmap& resource); - void incrementRefcount(const Res_png_9patch* resource); - void decrementRefcount(const SkBitmap* resource); void decrementRefcount(const Res_png_9patch* resource); - void decrementRefcountLocked(const SkBitmap* resource); void decrementRefcountLocked(const Res_png_9patch* resource); void destructor(Res_png_9patch* resource); @@ -134,7 +95,6 @@ private: mutable Mutex mLock; KeyedVector<const void*, ResourceReference*>* mCache; - KeyedVector<BitmapKey, SkBitmap*> mBitmapCache; }; }; // namespace uirenderer diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 3de3086..733e5e0 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -16,36 +16,25 @@ #include "CanvasContext.h" +#include "AnimationContext.h" +#include "Caches.h" +#include "DeferredLayerUpdater.h" #include "EglManager.h" +#include "LayerRenderer.h" +#include "OpenGLRenderer.h" +#include "Properties.h" #include "RenderThread.h" -#include "../AnimationContext.h" -#include "../Caches.h" -#include "../DeferredLayerUpdater.h" -#include "../renderstate/RenderState.h" -#include "../renderstate/Stencil.h" -#include "../LayerRenderer.h" -#include "../OpenGLRenderer.h" +#include "renderstate/RenderState.h" +#include "renderstate/Stencil.h" #include <algorithm> +#include <strings.h> #include <cutils/properties.h> #include <private/hwui/DrawGlInfo.h> -#include <strings.h> #define TRIM_MEMORY_COMPLETE 80 #define TRIM_MEMORY_UI_HIDDEN 20 -#define PROPERTY_SKIP_EMPTY_DAMAGE "debug.hwui.skip_empty_damage" - -static bool sInitialized = false; -static bool sSkipEmptyDamage = true; - -static void initGlobals() { - if (sInitialized) return; - sInitialized = true; - sSkipEmptyDamage = property_get_bool(PROPERTY_SKIP_EMPTY_DAMAGE, - sSkipEmptyDamage); -} - namespace android { namespace uirenderer { namespace renderthread { @@ -58,9 +47,6 @@ CanvasContext::CanvasContext(RenderThread& thread, bool translucent, , mAnimationContext(contextFactory->createAnimationContext(mRenderThread.timeLord())) , mRootRenderNode(rootRenderNode) , mJankTracker(thread.timeLord().frameIntervalNanos()) { - // Done lazily at first draw instead of at library load to avoid - // running pre-zygote fork - initGlobals(); mRenderThread.renderState().registerCanvasContext(this); mProfiler.setDensity(mRenderThread.mainDisplayInfo().density); } @@ -106,8 +92,8 @@ void CanvasContext::setSurface(ANativeWindow* window) { } } -void CanvasContext::swapBuffers() { - if (CC_UNLIKELY(!mEglManager.swapBuffers(mEglSurface))) { +void CanvasContext::swapBuffers(const SkRect& dirty, EGLint width, EGLint height) { + if (CC_UNLIKELY(!mEglManager.swapBuffers(mEglSurface, dirty, width, height))) { setSurface(nullptr); } mHaveNewSurface = false; @@ -185,6 +171,7 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo) { } if (CC_UNLIKELY(!mNativeWindow.get())) { + mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); info.out.canDrawThisFrame = false; return; } @@ -197,6 +184,10 @@ void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo) { NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &runningBehind); info.out.canDrawThisFrame = !runningBehind; + if (!info.out.canDrawThisFrame) { + mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); + } + if (info.out.hasAnimations || !info.out.canDrawThisFrame) { if (!info.out.requiresUiRedraw) { // If animationsNeedsRedraw is set don't bother posting for an RT anim @@ -222,7 +213,7 @@ void CanvasContext::draw() { SkRect dirty; mDamageAccumulator.finish(&dirty); - if (dirty.isEmpty() && sSkipEmptyDamage) { + if (dirty.isEmpty() && Properties::skipEmptyFrames) { mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); return; } @@ -267,7 +258,7 @@ void CanvasContext::draw() { mCurrentFrameInfo->markSwapBuffers(); if (drew) { - swapBuffers(); + swapBuffers(dirty, width, height); } else { mEglManager.cancelFrame(); } @@ -298,8 +289,6 @@ void CanvasContext::doFrame() { prepareTree(info, frameInfo); if (info.out.canDrawThisFrame) { draw(); - } else { - mCurrentFrameInfo->addFlag(FrameInfoFlags::kSkippedFrame); } } diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index f5f1f54..8163b0f 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -29,6 +29,7 @@ #include <cutils/compiler.h> #include <EGL/egl.h> #include <SkBitmap.h> +#include <SkRect.h> #include <utils/Functor.h> #include <utils/Vector.h> @@ -117,7 +118,7 @@ private: friend class android::uirenderer::RenderState; void setSurface(ANativeWindow* window); - void swapBuffers(); + void swapBuffers(const SkRect& dirty, EGLint width, EGLint height); void requireSurface(); void requireGlContext(); diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp index 3afca2f..6255f5e 100644 --- a/libs/hwui/renderthread/EglManager.cpp +++ b/libs/hwui/renderthread/EglManager.cpp @@ -16,9 +16,10 @@ #include "EglManager.h" -#include "../Caches.h" -#include "../renderstate/RenderState.h" +#include "Caches.h" +#include "Properties.h" #include "RenderThread.h" +#include "renderstate/RenderState.h" #include <cutils/log.h> #include <cutils/properties.h> @@ -261,7 +262,8 @@ void EglManager::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) { mInFrame = true; } -bool EglManager::swapBuffers(EGLSurface surface) { +bool EglManager::swapBuffers(EGLSurface surface, const SkRect& dirty, + EGLint width, EGLint height) { mInFrame = false; #if WAIT_FOR_GPU_COMPLETION @@ -271,7 +273,37 @@ bool EglManager::swapBuffers(EGLSurface surface) { } #endif +#ifdef EGL_KHR_swap_buffers_with_damage + if (CC_UNLIKELY(Properties::swapBuffersWithDamage)) { + SkIRect idirty; + dirty.roundOut(&idirty); + /* + * EGL_KHR_swap_buffers_with_damage spec states: + * + * The rectangles are specified relative to the bottom-left of the surface + * and the x and y components of each rectangle specify the bottom-left + * position of that rectangle. + * + * HWUI does everything with 0,0 being top-left, so need to map + * the rect + */ + EGLint y = height - (idirty.y() + idirty.height()); + // layout: {x, y, width, height} + EGLint rects[4] = { idirty.x(), y, idirty.width(), idirty.height() }; + EGLint numrects = dirty.isEmpty() ? 0 : 1; + // TODO: Remove prior to enabling this path by default + ALOGD("Swap buffers with damage %d: %d, %d, %d, %d (src=" + RECT_STRING ")", + dirty.isEmpty() ? 0 : 1, rects[0], rects[1], rects[2], rects[3], + SK_RECT_ARGS(dirty)); + eglSwapBuffersWithDamageKHR(mEglDisplay, surface, rects, numrects); + } else { + eglSwapBuffers(mEglDisplay, surface); + } +#else eglSwapBuffers(mEglDisplay, surface); +#endif + EGLint err = eglGetError(); if (CC_LIKELY(err == EGL_SUCCESS)) { return true; diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h index b1a18a9..0855516 100644 --- a/libs/hwui/renderthread/EglManager.h +++ b/libs/hwui/renderthread/EglManager.h @@ -18,6 +18,7 @@ #include <cutils/compiler.h> #include <EGL/egl.h> +#include <SkRect.h> #include <ui/GraphicBuffer.h> #include <utils/StrongPointer.h> @@ -47,7 +48,7 @@ public: // Returns true if the current surface changed, false if it was already current bool makeCurrent(EGLSurface surface); void beginFrame(EGLSurface surface, EGLint* width, EGLint* height); - bool swapBuffers(EGLSurface surface); + bool swapBuffers(EGLSurface surface, const SkRect& dirty, EGLint width, EGLint height); void cancelFrame(); // Returns true iff the surface is now preserving buffers. diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index c643e1d..17e47b9 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -353,7 +353,6 @@ CREATE_BRIDGE2(overrideProperty, const char* name, const char* value) { } void RenderProxy::overrideProperty(const char* name, const char* value) { - RenderThread& thread = RenderThread::getInstance(); SETUP_TASK(overrideProperty); args->name = name; args->value = value; |