From 5a4690bf26932c0d6940e4af8516d920e09ae81a Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Tue, 14 Jul 2015 12:13:03 -0700 Subject: Clean up unncessary defines LOG_TAG and TRACE_TAG are already defined in the makefile Change-Id: I9e53e3dacbe018441edd74cb7c8c90846defee74 --- libs/hwui/PathCache.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'libs/hwui/PathCache.cpp') diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index 3af640f76365..e36f5f17d29c 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -14,9 +14,6 @@ * limitations under the License. */ -#define LOG_TAG "OpenGLRenderer" -#define ATRACE_TAG ATRACE_TAG_VIEW - #include #include #include -- cgit v1.2.3-59-g8ed1b From 272a685f17cc4828257e521a6f62b7b17870f75e Mon Sep 17 00:00:00 2001 From: John Reck Date: Wed, 29 Jul 2015 16:48:58 -0700 Subject: Replace most usages of utils/Vector.h Change-Id: I540d1b3523244d6c71fc52d6fb30555271c25644 --- libs/hwui/AmbientShadow.cpp | 1 - libs/hwui/Caches.h | 5 ++- libs/hwui/DeferredDisplayList.cpp | 30 +++++++-------- libs/hwui/DeferredDisplayList.h | 9 +++-- libs/hwui/DisplayList.cpp | 10 +++-- libs/hwui/DisplayList.h | 23 ++++++------ libs/hwui/DisplayListCanvas.cpp | 11 +++--- libs/hwui/DisplayListCanvas.h | 4 +- libs/hwui/DisplayListOp.h | 8 ++-- libs/hwui/FontRenderer.cpp | 26 ++++++------- libs/hwui/FontRenderer.h | 14 +++---- libs/hwui/GradientCache.h | 2 - libs/hwui/OpenGLRenderer.cpp | 10 ++--- libs/hwui/OpenGLRenderer.h | 5 ++- libs/hwui/Patch.cpp | 3 +- libs/hwui/Patch.h | 6 +-- libs/hwui/PathCache.cpp | 7 +--- libs/hwui/PathCache.h | 5 ++- libs/hwui/PathTessellator.cpp | 67 +++++++++++++++------------------- libs/hwui/PathTessellator.h | 12 +++--- libs/hwui/Properties.h | 3 -- libs/hwui/RenderNode.cpp | 16 ++++---- libs/hwui/RenderNode.h | 13 ++++--- libs/hwui/ShadowTessellator.cpp | 1 - libs/hwui/TessellationCache.cpp | 6 +-- libs/hwui/TessellationCache.h | 1 - libs/hwui/TextureCache.cpp | 4 +- libs/hwui/TextureCache.h | 5 ++- libs/hwui/Vertex.h | 1 - libs/hwui/renderthread/CanvasContext.h | 1 - libs/hwui/renderthread/RenderProxy.h | 1 - libs/hwui/thread/TaskManager.cpp | 14 +++---- libs/hwui/thread/TaskManager.h | 7 ++-- 33 files changed, 159 insertions(+), 172 deletions(-) (limited to 'libs/hwui/PathCache.cpp') diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp index f8debcb28834..751531e1b57d 100644 --- a/libs/hwui/AmbientShadow.cpp +++ b/libs/hwui/AmbientShadow.cpp @@ -54,7 +54,6 @@ #include #include -#include #include "AmbientShadow.h" #include "ShadowTessellator.h" diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index c617a4d868a2..049d58bcd133 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -43,12 +43,13 @@ #include #include -#include #include #include +#include + namespace android { namespace uirenderer { @@ -201,7 +202,7 @@ private: std::unique_ptr mRegionMesh; mutable Mutex mGarbageLock; - Vector mLayerGarbage; + std::vector mLayerGarbage; bool mInitialized; diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp index e56d2bec7ff2..9fb1e756c00d 100644 --- a/libs/hwui/DeferredDisplayList.cpp +++ b/libs/hwui/DeferredDisplayList.cpp @@ -69,7 +69,7 @@ public: // NOTE: ignore empty bounds special case, since we don't merge across those ops mBounds.unionWith(state->mBounds); mAllOpsOpaque &= opaqueOverBounds; - mOps.add(OpStatePair(op, state)); + mOps.push_back(OpStatePair(op, state)); } bool intersects(const Rect& rect) { @@ -133,7 +133,7 @@ public: inline int count() const { return mOps.size(); } protected: - Vector mOps; + std::vector mOps; Rect mBounds; // union of bounds of contained ops private: bool mAllOpsOpaque; @@ -418,7 +418,7 @@ void DeferredDisplayList::addSaveLayer(OpenGLRenderer& renderer, this, op, op->getFlags(), newSaveCount); storeStateOpBarrier(renderer, op); - mSaveStack.push(newSaveCount); + mSaveStack.push_back(newSaveCount); } /** @@ -433,7 +433,7 @@ void DeferredDisplayList::addSave(OpenGLRenderer& renderer, SaveOp* op, int newS // store and replay the save operation, as it may be needed to correctly playback the clip DEFER_LOGD(" adding save barrier with new save count %d", newSaveCount); storeStateOpBarrier(renderer, op); - mSaveStack.push(newSaveCount); + mSaveStack.push_back(newSaveCount); } } @@ -456,11 +456,11 @@ void DeferredDisplayList::addRestoreToCount(OpenGLRenderer& renderer, StateOp* o resetBatchingState(); } - if (mSaveStack.isEmpty() || newSaveCount > mSaveStack.top()) { + if (mSaveStack.empty() || newSaveCount > mSaveStack.back()) { return; } - while (!mSaveStack.isEmpty() && mSaveStack.top() >= newSaveCount) mSaveStack.pop(); + while (!mSaveStack.empty() && mSaveStack.back() >= newSaveCount) mSaveStack.pop_back(); storeRestoreToCountBarrier(renderer, op, mSaveStack.size() + FLUSH_SAVE_STACK_DEPTH); } @@ -492,7 +492,7 @@ void DeferredDisplayList::addDrawOp(OpenGLRenderer& renderer, DrawOp* op) { // the merge path in those cases deferInfo.mergeable &= !recordingComplexClip(); deferInfo.opaqueOverBounds &= !recordingComplexClip() - && mSaveStack.isEmpty() + && mSaveStack.empty() && !state->mRoundRectClipState; if (CC_LIKELY(mAvoidOverdraw) && mBatches.size() && @@ -507,7 +507,7 @@ void DeferredDisplayList::addDrawOp(OpenGLRenderer& renderer, DrawOp* op) { // TODO: elegant way to reuse batches? DrawBatch* b = new DrawBatch(deferInfo); b->add(op, state, deferInfo.opaqueOverBounds); - mBatches.add(b); + mBatches.push_back(b); return; } @@ -517,12 +517,12 @@ void DeferredDisplayList::addDrawOp(OpenGLRenderer& renderer, DrawOp* op) { // insertion point of a new batch, will hopefully be immediately after similar batch // (eventually, should be similar shader) int insertBatchIndex = mBatches.size(); - if (!mBatches.isEmpty()) { + if (!mBatches.empty()) { if (state->mBounds.isEmpty()) { // don't know the bounds for op, so add to last batch and start from scratch on next op DrawBatch* b = new DrawBatch(deferInfo); b->add(op, state, deferInfo.opaqueOverBounds); - mBatches.add(b); + mBatches.push_back(b); resetBatchingState(); #if DEBUG_DEFER DEFER_LOGD("Warning: Encountered op with empty bounds, resetting batches"); @@ -586,7 +586,7 @@ void DeferredDisplayList::addDrawOp(OpenGLRenderer& renderer, DrawOp* op) { DEFER_LOGD("creating %singBatch %p, bid %x, at %d", deferInfo.mergeable ? "Merg" : "Draw", targetBatch, deferInfo.batchId, insertBatchIndex); - mBatches.insertAt(targetBatch, insertBatchIndex); + mBatches.insert(mBatches.begin() + insertBatchIndex, targetBatch); } targetBatch->add(op, state, deferInfo.opaqueOverBounds); @@ -597,7 +597,7 @@ void DeferredDisplayList::storeStateOpBarrier(OpenGLRenderer& renderer, StateOp* DeferredDisplayState* state = createState(); renderer.storeDisplayState(*state, getStateOpDeferFlags()); - mBatches.add(new StateOpBatch(op, state)); + mBatches.push_back(new StateOpBatch(op, state)); resetBatchingState(); } @@ -610,7 +610,7 @@ void DeferredDisplayList::storeRestoreToCountBarrier(OpenGLRenderer& renderer, S // doesn't have kClip_SaveFlag set DeferredDisplayState* state = createState(); renderer.storeDisplayState(*state, getStateOpDeferFlags()); - mBatches.add(new RestoreToCountBatch(op, state, newSaveCount)); + mBatches.push_back(new RestoreToCountBatch(op, state, newSaveCount)); resetBatchingState(); } @@ -618,7 +618,7 @@ void DeferredDisplayList::storeRestoreToCountBarrier(OpenGLRenderer& renderer, S // Replay / flush ///////////////////////////////////////////////////////////////////////////////// -static void replayBatchList(const Vector& batchList, +static void replayBatchList(const std::vector& batchList, OpenGLRenderer& renderer, Rect& dirty) { for (unsigned int i = 0; i < batchList.size(); i++) { @@ -664,7 +664,7 @@ void DeferredDisplayList::discardDrawingBatches(const unsigned int maxIndex) { // leave deferred state ops alone for simplicity (empty save restore pairs may now exist) if (mBatches[i] && mBatches[i]->purelyDrawBatch()) { delete mBatches[i]; - mBatches.replaceAt(nullptr, i); + mBatches[i] = nullptr; } } mEarliestUnclearedIndex = maxIndex + 1; diff --git a/libs/hwui/DeferredDisplayList.h b/libs/hwui/DeferredDisplayList.h index 160c1ad2d1f6..4f2dca5f3ee1 100644 --- a/libs/hwui/DeferredDisplayList.h +++ b/libs/hwui/DeferredDisplayList.h @@ -19,13 +19,14 @@ #include #include -#include #include #include "Matrix.h" #include "OpenGLRenderer.h" #include "Rect.h" +#include + class SkBitmap; namespace android { @@ -100,7 +101,7 @@ public: kOpBatch_Count, // Add other batch ids before this }; - bool isEmpty() { return mBatches.isEmpty(); } + bool isEmpty() { return mBatches.empty(); } /** * Plays back all of the draw ops recorded into batches to the renderer. @@ -157,10 +158,10 @@ private: * that when an associated restoreToCount is deferred, it can be recorded as a * RestoreToCountBatch */ - Vector mSaveStack; + std::vector mSaveStack; int mComplexClipStackStart; - Vector mBatches; + std::vector mBatches; // Maps batch ids to the most recent *non-merging* batch of that id Batch* mBatchLookup[kOpBatch_Count]; diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index eacfac7d93a0..0af9420533eb 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -40,13 +40,13 @@ void DisplayListData::cleanupResources() { resourceCache.lock(); for (size_t i = 0; i < patchResources.size(); i++) { - resourceCache.decrementRefcountLocked(patchResources.itemAt(i)); + resourceCache.decrementRefcountLocked(patchResources[i]); } resourceCache.unlock(); for (size_t i = 0; i < pathResources.size(); i++) { - const SkPath* path = pathResources.itemAt(i); + const SkPath* path = pathResources[i]; if (path->unique() && Caches::hasInstance()) { Caches::getInstance().pathCache.removeDeferred(path); } @@ -60,8 +60,10 @@ void DisplayListData::cleanupResources() { } size_t DisplayListData::addChild(DrawRenderNodeOp* op) { - mReferenceHolders.push(op->renderNode()); - return mChildren.add(op); + mReferenceHolders.push_back(op->renderNode()); + size_t index = mChildren.size(); + mChildren.push_back(op); + return index; } }; // namespace uirenderer diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index d7615484c975..0bdb8169ea06 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -27,7 +27,6 @@ #include #include #include -#include #include @@ -39,6 +38,8 @@ #include "Matrix.h" #include "RenderProperties.h" +#include + class SkBitmap; class SkPaint; class SkPath; @@ -124,28 +125,28 @@ public: ~DisplayListData(); // pointers to all ops within display list, pointing into allocator data - Vector displayListOps; + std::vector displayListOps; // index of DisplayListOp restore, after which projected descendents should be drawn int projectionReceiveIndex; - Vector bitmapResources; - Vector pathResources; - Vector patchResources; + std::vector bitmapResources; + std::vector pathResources; + std::vector patchResources; std::vector> paints; std::vector> regions; Vector functors; - const Vector& getChunks() const { + const std::vector& getChunks() const { return chunks; } size_t addChild(DrawRenderNodeOp* childOp); - const Vector& children() { return mChildren; } + const std::vector& children() { return mChildren; } void ref(VirtualLightRefBase* prop) { - mReferenceHolders.push(prop); + mReferenceHolders.push_back(prop); } size_t getUsedSize() { @@ -156,12 +157,12 @@ public: } private: - Vector< sp > mReferenceHolders; + std::vector< sp > mReferenceHolders; // list of children display lists for quick, non-drawing traversal - Vector mChildren; + std::vector mChildren; - Vector chunks; + std::vector chunks; // allocator into which all ops were allocated LinearAllocator allocator; diff --git a/libs/hwui/DisplayListCanvas.cpp b/libs/hwui/DisplayListCanvas.cpp index af18e03c60a9..74189aabbc87 100644 --- a/libs/hwui/DisplayListCanvas.cpp +++ b/libs/hwui/DisplayListCanvas.cpp @@ -548,11 +548,12 @@ void DisplayListCanvas::flushTranslate() { } size_t DisplayListCanvas::addOpAndUpdateChunk(DisplayListOp* op) { - int insertIndex = mDisplayListData->displayListOps.add(op); + int insertIndex = mDisplayListData->displayListOps.size(); + mDisplayListData->displayListOps.push_back(op); if (mDeferredBarrierType != kBarrier_None) { // op is first in new chunk - mDisplayListData->chunks.push(); - DisplayListData::Chunk& newChunk = mDisplayListData->chunks.editTop(); + mDisplayListData->chunks.emplace_back(); + DisplayListData::Chunk& newChunk = mDisplayListData->chunks.back(); newChunk.beginOpIndex = insertIndex; newChunk.endOpIndex = insertIndex + 1; newChunk.reorderChildren = (mDeferredBarrierType == kBarrier_OutOfOrder); @@ -562,7 +563,7 @@ size_t DisplayListCanvas::addOpAndUpdateChunk(DisplayListOp* op) { mDeferredBarrierType = kBarrier_None; } else { // standard case - append to existing chunk - mDisplayListData->chunks.editTop().endOpIndex = insertIndex + 1; + mDisplayListData->chunks.back().endOpIndex = insertIndex + 1; } return insertIndex; } @@ -594,7 +595,7 @@ size_t DisplayListCanvas::addRenderNodeOp(DrawRenderNodeOp* op) { int childIndex = mDisplayListData->addChild(op); // update the chunk's child indices - DisplayListData::Chunk& chunk = mDisplayListData->chunks.editTop(); + DisplayListData::Chunk& chunk = mDisplayListData->chunks.back(); chunk.endChildIndex = childIndex + 1; if (op->renderNode()->stagingProperties().isProjectionReceiver()) { diff --git a/libs/hwui/DisplayListCanvas.h b/libs/hwui/DisplayListCanvas.h index 6f2e2b50967e..28954d1bba70 100644 --- a/libs/hwui/DisplayListCanvas.h +++ b/libs/hwui/DisplayListCanvas.h @@ -270,7 +270,7 @@ private: // The points/verbs within the path are refcounted so this copy operation // is inexpensive and maintains the generationID of the original path. const SkPath* cachedPath = new SkPath(*path); - mDisplayListData->pathResources.add(cachedPath); + mDisplayListData->pathResources.push_back(cachedPath); return cachedPath; } @@ -345,7 +345,7 @@ private: } inline const Res_png_9patch* refPatch(const Res_png_9patch* patch) { - mDisplayListData->patchResources.add(patch); + mDisplayListData->patchResources.push_back(patch); mResourceCache.incrementRefcount(patch); return patch; } diff --git a/libs/hwui/DisplayListOp.h b/libs/hwui/DisplayListOp.h index 8b4b4ba2b79e..8ff58d4f64f5 100644 --- a/libs/hwui/DisplayListOp.h +++ b/libs/hwui/DisplayListOp.h @@ -139,7 +139,7 @@ public: * reducing which operations are tagged as mergeable. */ virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty, - const Vector& ops, const Rect& bounds) { + const std::vector& ops, const Rect& bounds) { for (unsigned int i = 0; i < ops.size(); i++) { renderer.restoreDisplayState(*(ops[i].state), true); ops[i].op->applyDraw(renderer, dirty); @@ -648,7 +648,7 @@ public: * the current layer, if any. */ virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty, - const Vector& ops, const Rect& bounds) override { + const std::vector& ops, const Rect& bounds) override { const DeferredDisplayState& firstState = *(ops[0].state); renderer.restoreDisplayState(firstState, true); // restore all but the clip @@ -819,7 +819,7 @@ public: * is also responsible for dirtying the current layer, if any. */ virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty, - const Vector& ops, const Rect& bounds) override { + const std::vector& ops, const Rect& bounds) override { const DeferredDisplayState& firstState = *(ops[0].state); renderer.restoreDisplayState(firstState, true); // restore all but the clip @@ -1358,7 +1358,7 @@ public: } virtual void multiDraw(OpenGLRenderer& renderer, Rect& dirty, - const Vector& ops, const Rect& bounds) override { + const std::vector& ops, const Rect& bounds) override { for (unsigned int i = 0; i < ops.size(); i++) { const DeferredDisplayState& state = *(ops[i].state); DrawOpMode drawOpMode = (i == ops.size() - 1) ? DrawOpMode::kFlush : DrawOpMode::kDefer; diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index 9c2c1192a69d..9be8c7d45bca 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -134,7 +134,7 @@ FontRenderer::FontRenderer() sLogFontRendererCreate = false; } -void clearCacheTextures(Vector& cacheTextures) { +void clearCacheTextures(std::vector& cacheTextures) { for (uint32_t i = 0; i < cacheTextures.size(); i++) { delete cacheTextures[i]; } @@ -171,7 +171,7 @@ void FontRenderer::flushAllAndInvalidate() { mDrawn = false; } -void FontRenderer::flushLargeCaches(Vector& cacheTextures) { +void FontRenderer::flushLargeCaches(std::vector& cacheTextures) { // Start from 1; don't deallocate smallest/default texture for (uint32_t i = 1; i < cacheTextures.size(); i++) { CacheTexture* cacheTexture = cacheTextures[i]; @@ -191,7 +191,7 @@ void FontRenderer::flushLargeCaches() { flushLargeCaches(mRGBACacheTextures); } -CacheTexture* FontRenderer::cacheBitmapInTexture(Vector& cacheTextures, +CacheTexture* FontRenderer::cacheBitmapInTexture(std::vector& cacheTextures, const SkGlyph& glyph, uint32_t* startX, uint32_t* startY) { for (uint32_t i = 0; i < cacheTextures.size(); i++) { if (cacheTextures[i]->fitBitmap(glyph, startX, startY)) { @@ -218,7 +218,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp // choose an appropriate cache texture list for this glyph format SkMask::Format format = static_cast(glyph.fMaskFormat); - Vector* cacheTextures = nullptr; + std::vector* cacheTextures = nullptr; switch (format) { case SkMask::kA8_Format: case SkMask::kBW_Format: @@ -399,17 +399,17 @@ void FontRenderer::initTextTexture() { clearCacheTextures(mRGBACacheTextures); mUploadTexture = false; - mACacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, + mACacheTextures.push_back(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, GL_ALPHA, true)); - mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, + mACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, GL_ALPHA, false)); - mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, + mACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, GL_ALPHA, false)); - mACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight, + mACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight, GL_ALPHA, false)); - mRGBACacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, + mRGBACacheTextures.push_back(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, GL_RGBA, false)); - mRGBACacheTextures.push(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, + mRGBACacheTextures.push_back(createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, GL_RGBA, false)); mCurrentCacheTexture = mACacheTextures[0]; } @@ -425,7 +425,7 @@ void FontRenderer::checkInit() { mInitialized = true; } -void checkTextureUpdateForCache(Caches& caches, Vector& cacheTextures, +void checkTextureUpdateForCache(Caches& caches, std::vector& cacheTextures, bool& resetPixelStore, GLuint& lastTextureId) { for (uint32_t i = 0; i < cacheTextures.size(); i++) { CacheTexture* cacheTexture = cacheTextures[i]; @@ -470,7 +470,7 @@ void FontRenderer::checkTextureUpdate() { mUploadTexture = false; } -void FontRenderer::issueDrawCommand(Vector& cacheTextures) { +void FontRenderer::issueDrawCommand(std::vector& cacheTextures) { if (!mFunctor) return; bool first = true; @@ -739,7 +739,7 @@ void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, flo Blur::vertical(gaussian.get(), intRadius, scratch.get(), *image, width, height); } -static uint32_t calculateCacheSize(const Vector& cacheTextures) { +static uint32_t calculateCacheSize(const std::vector& cacheTextures) { uint32_t size = 0; for (uint32_t i = 0; i < cacheTextures.size(); i++) { CacheTexture* cacheTexture = cacheTextures[i]; diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h index dfb107c99bc5..2954975b1413 100644 --- a/libs/hwui/FontRenderer.h +++ b/libs/hwui/FontRenderer.h @@ -21,16 +21,16 @@ #include "font/CacheTexture.h" #include "font/CachedGlyphInfo.h" #include "font/Font.h" -#include "utils/SortedList.h" #include -#include #include #include #include +#include + #ifdef ANDROID_ENABLE_RENDERSCRIPT #include "RenderScript.h" namespace RSC { @@ -75,7 +75,7 @@ public: FontRenderer(); ~FontRenderer(); - void flushLargeCaches(Vector& cacheTextures); + void flushLargeCaches(std::vector& cacheTextures); void flushLargeCaches(); void setGammaTable(const uint8_t* gammaTable) { @@ -127,7 +127,7 @@ private: CacheTexture* createCacheTexture(int width, int height, GLenum format, bool allocate); void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, uint32_t *retOriginX, uint32_t *retOriginY, bool precaching); - CacheTexture* cacheBitmapInTexture(Vector& cacheTextures, const SkGlyph& glyph, + CacheTexture* cacheBitmapInTexture(std::vector& cacheTextures, const SkGlyph& glyph, uint32_t* startX, uint32_t* startY); void flushAllAndInvalidate(); @@ -136,7 +136,7 @@ private: void initRender(const Rect* clip, Rect* bounds, TextDrawFunctor* functor); void finishRender(); - void issueDrawCommand(Vector& cacheTextures); + void issueDrawCommand(std::vector& cacheTextures); void issueDrawCommand(); void appendMeshQuadNoClip(float x1, float y1, float u1, float v1, float x2, float y2, float u2, float v2, @@ -164,8 +164,8 @@ private: uint32_t mLargeCacheWidth; uint32_t mLargeCacheHeight; - Vector mACacheTextures; - Vector mRGBACacheTextures; + std::vector mACacheTextures; + std::vector mRGBACacheTextures; Font* mCurrentFont; LruCache mActiveFonts; diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h index 08319ea1ec9b..7534c5d11164 100644 --- a/libs/hwui/GradientCache.h +++ b/libs/hwui/GradientCache.h @@ -25,7 +25,6 @@ #include #include -#include namespace android { namespace uirenderer { @@ -183,7 +182,6 @@ private: bool mUseFloatTexture; bool mHasNpot; - Vector mGarbage; mutable Mutex mLock; }; // class GradientCache diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index c260f5fe79d3..8e04bdf3b8ad 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -419,7 +419,7 @@ void OpenGLRenderer::updateLayers() { // Note: it is very important to update the layers in order for (int i = 0; i < count; i++) { - Layer* layer = mLayerUpdates.itemAt(i).get(); + Layer* layer = mLayerUpdates[i].get(); updateLayer(layer, false); } @@ -438,7 +438,7 @@ void OpenGLRenderer::flushLayers() { // Note: it is very important to update the layers in order for (int i = 0; i < count; i++) { - mLayerUpdates.itemAt(i)->flush(); + mLayerUpdates[i]->flush(); } mLayerUpdates.clear(); @@ -455,7 +455,7 @@ void OpenGLRenderer::pushLayerUpdate(Layer* layer) { // the insertion order. The linear search is not an issue since // this list is usually very short (typically one item, at most a few) for (int i = mLayerUpdates.size() - 1; i >= 0; i--) { - if (mLayerUpdates.itemAt(i) == layer) { + if (mLayerUpdates[i] == layer) { return; } } @@ -466,8 +466,8 @@ void OpenGLRenderer::pushLayerUpdate(Layer* layer) { void OpenGLRenderer::cancelLayerUpdate(Layer* layer) { if (layer) { for (int i = mLayerUpdates.size() - 1; i >= 0; i--) { - if (mLayerUpdates.itemAt(i) == layer) { - mLayerUpdates.removeAt(i); + if (mLayerUpdates[i] == layer) { + mLayerUpdates.erase(mLayerUpdates.begin() + i); break; } } diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 402f6edd475d..390f6207f4ea 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -44,12 +44,13 @@ #include #include #include -#include #include #include +#include + class SkShader; namespace android { @@ -855,7 +856,7 @@ private: // List of rectangles to clear after saveLayer() is invoked std::vector mLayers; // List of layers to update at the beginning of a frame - Vector< sp > mLayerUpdates; + std::vector< sp > mLayerUpdates; // See PROPERTY_DISABLE_SCISSOR_OPTIMIZATION in // Properties.h diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp index 15d2ae94aeaa..500f9e95381c 100644 --- a/libs/hwui/Patch.cpp +++ b/libs/hwui/Patch.cpp @@ -206,8 +206,7 @@ void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, f // Record all non empty quads if (hasEmptyQuads) { - Rect bounds(x1, y1, x2, y2); - quads.add(bounds); + quads.emplace_back(x1, y1, x2, y2); } mUvMapper.map(u1, v1, u2, v2); diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h index b63bd24456d3..f04416ccabf9 100644 --- a/libs/hwui/Patch.h +++ b/libs/hwui/Patch.h @@ -21,13 +21,13 @@ #include -#include - #include #include "Rect.h" #include "UvMapper.h" +#include + namespace android { namespace uirenderer { @@ -52,7 +52,7 @@ public: uint32_t verticesCount = 0; uint32_t indexCount = 0; bool hasEmptyQuads = false; - Vector quads; + std::vector quads; GLintptr positionOffset = 0; GLintptr textureOffset = 0; diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index e36f5f17d29c..f503e5d6e8ba 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -338,7 +338,7 @@ void PathCache::PathProcessor::onProcess(const sp >& task) { void PathCache::removeDeferred(const SkPath* path) { Mutex::Autolock l(mLock); - mGarbage.push(path->getGenerationID()); + mGarbage.push_back(path->getGenerationID()); } void PathCache::clearGarbage() { @@ -346,10 +346,7 @@ void PathCache::clearGarbage() { { // scope for the mutex Mutex::Autolock l(mLock); - size_t count = mGarbage.size(); - for (size_t i = 0; i < count; i++) { - const uint32_t generationID = mGarbage.itemAt(i); - + for (const uint32_t generationID : mGarbage) { LruCache::Iterator iter(mCache); while (iter.next()) { const PathDescription& key = iter.key(); diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h index 70148631db34..31f8d3553375 100644 --- a/libs/hwui/PathCache.h +++ b/libs/hwui/PathCache.h @@ -28,7 +28,8 @@ #include #include #include -#include + +#include class SkBitmap; class SkCanvas; @@ -307,7 +308,7 @@ private: sp mProcessor; - Vector mGarbage; + std::vector mGarbage; mutable Mutex mLock; }; // class PathCache diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp index 5294be887c93..8fa187c1e530 100644 --- a/libs/hwui/PathTessellator.cpp +++ b/libs/hwui/PathTessellator.cpp @@ -177,7 +177,8 @@ public: } }; -void getFillVerticesFromPerimeter(const Vector& perimeter, VertexBuffer& vertexBuffer) { +void getFillVerticesFromPerimeter(const std::vector& perimeter, + VertexBuffer& vertexBuffer) { Vertex* buffer = vertexBuffer.alloc(perimeter.size()); int currentIndex = 0; @@ -201,8 +202,8 @@ void getFillVerticesFromPerimeter(const Vector& perimeter, VertexBuffer& * Uses an additional 2 vertices at the end to wrap around, closing the tri-strip * (for a total of perimeter.size() * 2 + 2 vertices) */ -void getStrokeVerticesFromPerimeter(const PaintInfo& paintInfo, const Vector& perimeter, - VertexBuffer& vertexBuffer) { +void getStrokeVerticesFromPerimeter(const PaintInfo& paintInfo, + const std::vector& perimeter, VertexBuffer& vertexBuffer) { Vertex* buffer = vertexBuffer.alloc(perimeter.size() * 2 + 2); int currentIndex = 0; @@ -260,7 +261,7 @@ static inline void storeBeginEnd(const PaintInfo& paintInfo, const Vertex& cente * 2 - can zig-zag across 'extra' vertices at either end, to create round caps */ void getStrokeVerticesFromUnclosedVertices(const PaintInfo& paintInfo, - const Vector& vertices, VertexBuffer& vertexBuffer) { + const std::vector& vertices, VertexBuffer& vertexBuffer) { const int extra = paintInfo.capExtraDivisions(); const int allocSize = (vertices.size() + extra) * 2; Vertex* buffer = vertexBuffer.alloc(allocSize); @@ -339,8 +340,9 @@ void getStrokeVerticesFromUnclosedVertices(const PaintInfo& paintInfo, * * 3 - zig zag back and forth inside the shape to fill it (using perimeter.size() vertices) */ -void getFillVerticesFromPerimeterAA(const PaintInfo& paintInfo, const Vector& perimeter, - VertexBuffer& vertexBuffer, float maxAlpha = 1.0f) { +void getFillVerticesFromPerimeterAA(const PaintInfo& paintInfo, + const std::vector& perimeter, VertexBuffer& vertexBuffer, + float maxAlpha = 1.0f) { AlphaVertex* buffer = vertexBuffer.alloc(perimeter.size() * 3 + 2); // generate alpha points - fill Alpha vertex gaps in between each point with @@ -398,7 +400,7 @@ void getFillVerticesFromPerimeterAA(const PaintInfo& paintInfo, const Vector& vertices, +inline static void storeCapAA(const PaintInfo& paintInfo, const std::vector& vertices, AlphaVertex* buffer, bool isFirst, Vector2 normal, int offset) { const int extra = paintInfo.capExtraDivisions(); const int extraOffset = (extra + 1) / 2; @@ -423,8 +425,8 @@ inline static void storeCapAA(const PaintInfo& paintInfo, const Vector& } // determine referencePoint, the center point for the 4 primary cap vertices - const Vertex* point = isFirst ? vertices.begin() : (vertices.end() - 1); - Vector2 referencePoint = {point->x, point->y}; + const Vertex& point = isFirst ? vertices.front() : vertices.back(); + Vector2 referencePoint = {point.x, point.y}; if (paintInfo.cap == SkPaint::kSquare_Cap) { // To account for square cap, move the primary cap vertices (that create the AA edge) by the // stroke offset vector (rotated to be parallel to the stroke) @@ -569,7 +571,7 @@ or, for rounded caps: = 2 + 6 * pts + 6 * roundDivs */ void getStrokeVerticesFromUnclosedVerticesAA(const PaintInfo& paintInfo, - const Vector& vertices, VertexBuffer& vertexBuffer) { + const std::vector& vertices, VertexBuffer& vertexBuffer) { const int extra = paintInfo.capExtraDivisions(); const int allocSize = 6 * vertices.size() + 2 + 6 * extra; @@ -642,8 +644,8 @@ void getStrokeVerticesFromUnclosedVerticesAA(const PaintInfo& paintInfo, } -void getStrokeVerticesFromPerimeterAA(const PaintInfo& paintInfo, const Vector& perimeter, - VertexBuffer& vertexBuffer) { +void getStrokeVerticesFromPerimeterAA(const PaintInfo& paintInfo, + const std::vector& perimeter, VertexBuffer& vertexBuffer) { AlphaVertex* buffer = vertexBuffer.alloc(6 * perimeter.size() + 8); int offset = 2 * perimeter.size() + 3; @@ -721,7 +723,7 @@ void PathTessellator::tessellatePath(const SkPath &path, const SkPaint* paint, const PaintInfo paintInfo(paint, transform); - Vector tempVertices; + std::vector tempVertices; float threshInvScaleX = paintInfo.inverseScaleX; float threshInvScaleY = paintInfo.inverseScaleY; if (paintInfo.style == SkPaint::kStroke_Style) { @@ -816,7 +818,7 @@ void PathTessellator::tessellatePoints(const float* points, int count, const SkP } // calculate outline - Vector outlineVertices; + std::vector outlineVertices; PathApproximationInfo approximationInfo(paintInfo.inverseScaleX, paintInfo.inverseScaleY, OUTLINE_REFINE_THRESHOLD); approximatePathOutlineVertices(path, true, approximationInfo, outlineVertices); @@ -858,10 +860,8 @@ void PathTessellator::tessellateLines(const float* points, int count, const SkPa vertexBuffer.alloc(numLines * lineAllocSize + (numLines - 1) * 2); } - Vector tempVertices; - tempVertices.push(); - tempVertices.push(); - Vertex* tempVerticesData = tempVertices.editArray(); + std::vector tempVertices(2); + Vertex* tempVerticesData = &tempVertices.front(); Rect bounds; bounds.set(points[0], points[1], points[0], points[1]); for (int i = 0; i < count; i += 4) { @@ -897,18 +897,11 @@ void PathTessellator::tessellateLines(const float* points, int count, const SkPa /////////////////////////////////////////////////////////////////////////////// bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, float threshold, - Vector& outputVertices) { + std::vector& outputVertices) { PathApproximationInfo approximationInfo(1.0f, 1.0f, threshold); return approximatePathOutlineVertices(path, true, approximationInfo, outputVertices); } -void pushToVector(Vector& vertices, float x, float y) { - // TODO: make this not yuck - vertices.push(); - Vertex* newVertex = &(vertices.editArray()[vertices.size() - 1]); - Vertex::set(newVertex, x, y); -} - class ClockwiseEnforcer { public: void addPoint(const SkPoint& point) { @@ -924,15 +917,15 @@ public: lastX = x; lastY = y; } - void reverseVectorIfNotClockwise(Vector& vertices) { + void reverseVectorIfNotClockwise(std::vector& vertices) { if (sum < 0) { // negative sum implies CounterClockwise const int size = vertices.size(); for (int i = 0; i < size / 2; i++) { Vertex tmp = vertices[i]; int k = size - 1 - i; - vertices.replaceAt(vertices[k], i); - vertices.replaceAt(tmp, k); + vertices[i] = vertices[k]; + vertices[k] = tmp; } } } @@ -944,7 +937,7 @@ private: }; bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool forceClose, - const PathApproximationInfo& approximationInfo, Vector& outputVertices) { + const PathApproximationInfo& approximationInfo, std::vector& outputVertices) { ATRACE_CALL(); // TODO: to support joins other than sharp miter, join vertices should be labelled in the @@ -956,7 +949,7 @@ bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool fo while (SkPath::kDone_Verb != (v = iter.next(pts))) { switch (v) { case SkPath::kMove_Verb: - pushToVector(outputVertices, pts[0].x(), pts[0].y()); + outputVertices.push_back(Vertex{pts[0].x(), pts[0].y()}); ALOGV("Move to pos %f %f", pts[0].x(), pts[0].y()); clockwiseEnforcer.addPoint(pts[0]); break; @@ -966,7 +959,7 @@ bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool fo break; case SkPath::kLine_Verb: ALOGV("kLine_Verb %f %f -> %f %f", pts[0].x(), pts[0].y(), pts[1].x(), pts[1].y()); - pushToVector(outputVertices, pts[1].x(), pts[1].y()); + outputVertices.push_back(Vertex{pts[1].x(), pts[1].y()}); clockwiseEnforcer.addPoint(pts[1]); break; case SkPath::kQuad_Verb: @@ -1017,7 +1010,7 @@ bool PathTessellator::approximatePathOutlineVertices(const SkPath& path, bool fo int size = outputVertices.size(); if (size >= 2 && outputVertices[0].x == outputVertices[size - 1].x && outputVertices[0].y == outputVertices[size - 1].y) { - outputVertices.pop(); + outputVertices.pop_back(); wasClosed = true; } @@ -1045,7 +1038,7 @@ void PathTessellator::recursiveCubicBezierVertices( float p1x, float p1y, float c1x, float c1y, float p2x, float p2y, float c2x, float c2y, const PathApproximationInfo& approximationInfo, - Vector& outputVertices, int depth) { + std::vector& outputVertices, int depth) { float dx = p2x - p1x; float dy = p2y - p1y; float d1 = fabs((c1x - p2x) * dy - (c1y - p2y) * dx); @@ -1055,7 +1048,7 @@ void PathTessellator::recursiveCubicBezierVertices( if (depth >= MAX_DEPTH || d * d <= getThreshold(approximationInfo, dx, dy)) { // below thresh, draw line by adding endpoint - pushToVector(outputVertices, p2x, p2y); + outputVertices.push_back(Vertex{p2x, p2y}); } else { float p1c1x = (p1x + c1x) * 0.5f; float p1c1y = (p1y + c1y) * 0.5f; @@ -1090,7 +1083,7 @@ void PathTessellator::recursiveQuadraticBezierVertices( float bx, float by, float cx, float cy, const PathApproximationInfo& approximationInfo, - Vector& outputVertices, int depth) { + std::vector& outputVertices, int depth) { float dx = bx - ax; float dy = by - ay; // d is the cross product of vector (B-A) and (C-B). @@ -1099,7 +1092,7 @@ void PathTessellator::recursiveQuadraticBezierVertices( if (depth >= MAX_DEPTH || d * d <= getThreshold(approximationInfo, dx, dy)) { // below thresh, draw line by adding endpoint - pushToVector(outputVertices, bx, by); + outputVertices.push_back(Vertex{bx, by}); } else { float acx = (ax + cx) * 0.5f; float bcx = (bx + cx) * 0.5f; diff --git a/libs/hwui/PathTessellator.h b/libs/hwui/PathTessellator.h index 16c8b36a6a9d..b66e83252fb3 100644 --- a/libs/hwui/PathTessellator.h +++ b/libs/hwui/PathTessellator.h @@ -17,13 +17,13 @@ #ifndef ANDROID_HWUI_PATH_TESSELLATOR_H #define ANDROID_HWUI_PATH_TESSELLATOR_H -#include - #include "Matrix.h" #include "Rect.h" #include "Vertex.h" #include "VertexBuffer.h" +#include + namespace android { namespace uirenderer { @@ -109,11 +109,11 @@ public: * @param outputVertices An empty Vector which will be populated with the output */ static bool approximatePathOutlineVertices(const SkPath &path, float threshold, - Vector &outputVertices); + std::vector &outputVertices); private: static bool approximatePathOutlineVertices(const SkPath &path, bool forceClose, - const PathApproximationInfo& approximationInfo, Vector &outputVertices); + const PathApproximationInfo& approximationInfo, std::vector &outputVertices); /* endpoints a & b, @@ -124,7 +124,7 @@ private: float bx, float by, float cx, float cy, const PathApproximationInfo& approximationInfo, - Vector &outputVertices, int depth = 0); + std::vector &outputVertices, int depth = 0); /* endpoints p1, p2 @@ -136,7 +136,7 @@ private: float p2x, float p2y, float c2x, float c2y, const PathApproximationInfo& approximationInfo, - Vector &outputVertices, int depth = 0); + std::vector &outputVertices, int depth = 0); }; }; // namespace uirenderer diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 5aef2a568798..1a70d7c20f03 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -36,9 +36,6 @@ namespace uirenderer { // If turned on, text is interpreted as glyphs instead of UTF-16 #define RENDER_TEXT_AS_GLYPHS 1 -// Indicates whether to remove the biggest layers first, or the smaller ones -#define LAYER_REMOVE_BIGGEST_FIRST 0 - // Textures used by layers must have dimensions multiples of this number #define LAYER_SIZE 64 diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 3717aec43cbf..af8aaa20342e 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -528,7 +528,7 @@ void RenderNode::computeOrdering() { void RenderNode::computeOrderingImpl( DrawRenderNodeOp* opState, const SkPath* outlineOfProjectionSurface, - Vector* compositedChildrenOfProjectionSurface, + std::vector* compositedChildrenOfProjectionSurface, const mat4* transformFromProjectionSurface) { mProjectedNodes.clear(); if (mDisplayListData == nullptr || mDisplayListData->isEmpty()) return; @@ -542,7 +542,7 @@ void RenderNode::computeOrderingImpl( // composited projectee, flag for out of order draw, save matrix, and store in proj surface opState->mSkipInOrderDraw = true; opState->mTransformFromCompositingAncestor.load(localTransformFromProjectionSurface); - compositedChildrenOfProjectionSurface->add(opState); + compositedChildrenOfProjectionSurface->push_back(opState); } else { // standard in order draw opState->mSkipInOrderDraw = false; @@ -556,7 +556,7 @@ void RenderNode::computeOrderingImpl( RenderNode* child = childOp->mRenderNode; const SkPath* projectionOutline = nullptr; - Vector* projectionChildren = nullptr; + std::vector* projectionChildren = nullptr; const mat4* projectionTransform = nullptr; if (isProjectionReceiver && !child->properties().getProjectBackwards()) { // if receiving projections, collect projecting descendant @@ -638,7 +638,7 @@ void RenderNode::replay(ReplayStateStruct& replayStruct, const int level) { } void RenderNode::buildZSortedChildList(const DisplayListData::Chunk& chunk, - Vector& zTranslatedNodes) { + std::vector& zTranslatedNodes) { if (chunk.beginChildIndex == chunk.endChildIndex) return; for (unsigned int i = chunk.beginChildIndex; i < chunk.endChildIndex; i++) { @@ -647,7 +647,7 @@ void RenderNode::buildZSortedChildList(const DisplayListData::Chunk& chunk, float childZ = child->properties().getZ(); if (!MathUtils::isZero(childZ) && chunk.reorderChildren) { - zTranslatedNodes.add(ZDrawRenderNodeOpPair(childZ, childOp)); + zTranslatedNodes.push_back(ZDrawRenderNodeOpPair(childZ, childOp)); childOp->mSkipInOrderDraw = true; } else if (!child->properties().getProjectBackwards()) { // regular, in order drawing DisplayList @@ -719,7 +719,7 @@ void RenderNode::issueDrawShadowOperation(const Matrix4& transformFromParent, T& template void RenderNode::issueOperationsOf3dChildren(ChildrenSelectMode mode, - const Matrix4& initialTransform, const Vector& zTranslatedNodes, + const Matrix4& initialTransform, const std::vector& zTranslatedNodes, OpenGLRenderer& renderer, T& handler) { const int size = zTranslatedNodes.size(); if (size == 0 @@ -896,7 +896,7 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { for (size_t chunkIndex = 0; chunkIndex < mDisplayListData->getChunks().size(); chunkIndex++) { const DisplayListData::Chunk& chunk = mDisplayListData->getChunks()[chunkIndex]; - Vector zTranslatedNodes; + std::vector zTranslatedNodes; buildZSortedChildList(chunk, zTranslatedNodes); issueOperationsOf3dChildren(kNegativeZChildren, @@ -910,7 +910,7 @@ void RenderNode::issueOperations(OpenGLRenderer& renderer, T& handler) { #endif handler(op, saveCountOffset, properties().getClipToBounds()); - if (CC_UNLIKELY(!mProjectedNodes.isEmpty() && projectionReceiveIndex >= 0 && + if (CC_UNLIKELY(!mProjectedNodes.empty() && projectionReceiveIndex >= 0 && opIndex == static_cast(projectionReceiveIndex))) { issueOperationsOfProjectedChildren(renderer, handler); } diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index 4063d4bd53ce..db72287c69c1 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -22,7 +22,6 @@ #include #include #include -#include #include @@ -34,6 +33,8 @@ #include "DisplayList.h" #include "RenderProperties.h" +#include + class SkBitmap; class SkPaint; class SkPath; @@ -176,7 +177,7 @@ public: private: typedef key_value_pair_t ZDrawRenderNodeOpPair; - static size_t findNonNegativeIndex(const Vector& nodes) { + static size_t findNonNegativeIndex(const std::vector& nodes) { for (size_t i = 0; i < nodes.size(); i++) { if (nodes[i].key >= 0.0f) return i; } @@ -190,21 +191,21 @@ private: void computeOrderingImpl(DrawRenderNodeOp* opState, const SkPath* outlineOfProjectionSurface, - Vector* compositedChildrenOfProjectionSurface, + std::vector* compositedChildrenOfProjectionSurface, const mat4* transformFromProjectionSurface); template inline void setViewProperties(OpenGLRenderer& renderer, T& handler); void buildZSortedChildList(const DisplayListData::Chunk& chunk, - Vector& zTranslatedNodes); + std::vector& zTranslatedNodes); template inline void issueDrawShadowOperation(const Matrix4& transformFromParent, T& handler); template inline void issueOperationsOf3dChildren(ChildrenSelectMode mode, - const Matrix4& initialTransform, const Vector& zTranslatedNodes, + const Matrix4& initialTransform, const std::vector& zTranslatedNodes, OpenGLRenderer& renderer, T& handler); template @@ -267,7 +268,7 @@ private: */ // for projection surfaces, contains a list of all children items - Vector mProjectedNodes; + std::vector mProjectedNodes; // How many references our parent(s) have to us. Typically this should alternate // between 2 and 1 (when a staging push happens we inc first then dec) diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp index b6271f63a606..220936551a60 100644 --- a/libs/hwui/ShadowTessellator.cpp +++ b/libs/hwui/ShadowTessellator.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include "AmbientShadow.h" diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp index 17cb3a7fd6fd..01f5e2dba214 100644 --- a/libs/hwui/TessellationCache.cpp +++ b/libs/hwui/TessellationCache.cpp @@ -225,13 +225,13 @@ static void tessellateShadows( VertexBuffer& ambientBuffer, VertexBuffer& spotBuffer) { // tessellate caster outline into a 2d polygon - Vector casterVertices2d; + std::vector casterVertices2d; const float casterRefinementThreshold = 2.0f; PathTessellator::approximatePathOutlineVertices(*casterPerimeter, casterRefinementThreshold, casterVertices2d); // Shadow requires CCW for now. TODO: remove potential double-reverse - reverseVertexArray(casterVertices2d.editArray(), casterVertices2d.size()); + reverseVertexArray(&casterVertices2d.front(), casterVertices2d.size()); if (casterVertices2d.size() == 0) return; @@ -250,7 +250,7 @@ static void tessellateShadows( // map the centroid of the caster into 3d Vector2 centroid = ShadowTessellator::centroid2d( - reinterpret_cast(casterVertices2d.array()), + reinterpret_cast(&casterVertices2d.front()), casterVertexCount); Vector3 centroid3d = {centroid.x, centroid.y, 0}; mapPointFakeZ(centroid3d, casterTransformXY, casterTransformZ); diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h index 3efeaf64d486..b54666b7d595 100644 --- a/libs/hwui/TessellationCache.h +++ b/libs/hwui/TessellationCache.h @@ -19,7 +19,6 @@ #include #include -#include #include "Debug.h" #include "utils/Macros.h" diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index c4467f1856ff..16f6f4ba4bb6 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -216,14 +216,14 @@ Texture* TextureCache::get(const SkBitmap* bitmap, AtlasUsageType atlasUsageType void TextureCache::releaseTexture(uint32_t pixelRefStableID) { Mutex::Autolock _l(mLock); - mGarbage.push(pixelRefStableID); + mGarbage.push_back(pixelRefStableID); } void TextureCache::clearGarbage() { Mutex::Autolock _l(mLock); size_t count = mGarbage.size(); for (size_t i = 0; i < count; i++) { - uint32_t pixelRefId = mGarbage.itemAt(i); + uint32_t pixelRefId = mGarbage[i]; mCache.remove(pixelRefId); } mGarbage.clear(); diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index 7a7ee5aeb554..ebd1885e75e1 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -21,10 +21,11 @@ #include #include -#include #include "Debug.h" +#include + namespace android { namespace uirenderer { @@ -165,7 +166,7 @@ private: bool mDebugEnabled; - Vector mGarbage; + std::vector mGarbage; mutable Mutex mLock; AssetAtlas* mAssetAtlas; diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h index 11d0c4bef84f..c1bf980658b2 100644 --- a/libs/hwui/Vertex.h +++ b/libs/hwui/Vertex.h @@ -37,7 +37,6 @@ struct Vertex { */ static float GeometryFudgeFactor() { return 0.0656f; } - float x, y; static inline void set(Vertex* vertex, float x, float y) { diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h index f2fa9cdcbefd..88c18a52b872 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -31,7 +31,6 @@ #include #include #include -#include #include #include diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 5febbe0ab26c..0d2c7be5b317 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -27,7 +27,6 @@ #include #include #include -#include #include "../Caches.h" #include "../IContextFactory.h" diff --git a/libs/hwui/thread/TaskManager.cpp b/libs/hwui/thread/TaskManager.cpp index e9dde294b2aa..a07845ecf659 100644 --- a/libs/hwui/thread/TaskManager.cpp +++ b/libs/hwui/thread/TaskManager.cpp @@ -39,7 +39,7 @@ TaskManager::TaskManager() { for (int i = 0; i < workerCount; i++) { String8 name; name.appendFormat("hwuiTask%d", i + 1); - mThreads.add(new WorkerThread(name)); + mThreads.push_back(new WorkerThread(name)); } } @@ -89,15 +89,14 @@ status_t TaskManager::WorkerThread::readyToRun() { bool TaskManager::WorkerThread::threadLoop() { mSignal.wait(); - Vector tasks; + std::vector tasks; { Mutex::Autolock l(mLock); - tasks = mTasks; - mTasks.clear(); + tasks.swap(mTasks); } for (size_t i = 0; i < tasks.size(); i++) { - const TaskWrapper& task = tasks.itemAt(i); + const TaskWrapper& task = tasks[i]; task.mProcessor->process(task.mTask); } @@ -111,14 +110,13 @@ bool TaskManager::WorkerThread::addTask(TaskWrapper task) { return false; } - ssize_t index; { Mutex::Autolock l(mLock); - index = mTasks.add(task); + mTasks.push_back(task); } mSignal.signal(); - return index >= 0; + return true; } size_t TaskManager::WorkerThread::getTaskCount() const { diff --git a/libs/hwui/thread/TaskManager.h b/libs/hwui/thread/TaskManager.h index 10e8b9e0bead..d0eb3049ae37 100644 --- a/libs/hwui/thread/TaskManager.h +++ b/libs/hwui/thread/TaskManager.h @@ -20,10 +20,11 @@ #include #include #include -#include #include "Signal.h" +#include + namespace android { namespace uirenderer { @@ -89,7 +90,7 @@ private: // Lock for the list of tasks mutable Mutex mLock; - Vector mTasks; + std::vector mTasks; // Signal used to wake up the thread when a new // task is available in the list @@ -98,7 +99,7 @@ private: const String8 mName; }; - Vector > mThreads; + std::vector > mThreads; }; }; // namespace uirenderer -- cgit v1.2.3-59-g8ed1b From 11718bc17bcfc56dfb9f4362eebf640b025c4415 Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Tue, 22 Sep 2015 11:50:13 -0700 Subject: Remove shader based gamma approach Also fixes some INIT_LOGD logs Change-Id: I212a71a1e7b366aea41f7c3c8cc169d509d6e4a2 --- libs/hwui/GammaFontRenderer.cpp | 48 -------------------------------- libs/hwui/GammaFontRenderer.h | 61 ----------------------------------------- libs/hwui/PathCache.cpp | 4 +-- libs/hwui/Program.h | 17 +++--------- libs/hwui/ProgramCache.cpp | 48 +++++--------------------------- libs/hwui/Properties.h | 2 +- libs/hwui/TessellationCache.cpp | 4 +-- 7 files changed, 16 insertions(+), 168 deletions(-) (limited to 'libs/hwui/PathCache.cpp') diff --git a/libs/hwui/GammaFontRenderer.cpp b/libs/hwui/GammaFontRenderer.cpp index 0bcd83a1a050..6c3d04e7400e 100644 --- a/libs/hwui/GammaFontRenderer.cpp +++ b/libs/hwui/GammaFontRenderer.cpp @@ -43,10 +43,6 @@ GammaFontRenderer* GammaFontRenderer::createRenderer() { if (property_get(PROPERTY_TEXT_GAMMA_METHOD, property, DEFAULT_TEXT_GAMMA_METHOD) > 0) { if (!strcasecmp(property, "lookup")) { return new LookupGammaFontRenderer(); - } else if (!strcasecmp(property, "shader")) { - return new ShaderGammaFontRenderer(false); - } else if (!strcasecmp(property, "shader3")) { - return new ShaderGammaFontRenderer(true); } } @@ -90,50 +86,6 @@ GammaFontRenderer::GammaFontRenderer() { GammaFontRenderer::~GammaFontRenderer() { } -/////////////////////////////////////////////////////////////////////////////// -// Shader-based renderer -/////////////////////////////////////////////////////////////////////////////// - -ShaderGammaFontRenderer::ShaderGammaFontRenderer(bool multiGamma) - : GammaFontRenderer() { - INIT_LOGD("Creating shader gamma font renderer"); - mRenderer = nullptr; - mMultiGamma = multiGamma; -} - -void ShaderGammaFontRenderer::describe(ProgramDescription& description, - const SkPaint* paint) const { - if (paint->getShader() == nullptr) { - if (mMultiGamma) { - const int l = luminance(paint); - - if (l <= mBlackThreshold) { - description.hasGammaCorrection = true; - description.gamma = mGamma; - } else if (l >= mWhiteThreshold) { - description.hasGammaCorrection = true; - description.gamma = 1.0f / mGamma; - } - } else { - description.hasGammaCorrection = true; - description.gamma = 1.0f / mGamma; - } - } -} - -void ShaderGammaFontRenderer::setupProgram(ProgramDescription& description, - Program& program) const { - if (description.hasGammaCorrection) { - glUniform1f(program.getUniform("gamma"), description.gamma); - } -} - -void ShaderGammaFontRenderer::endPrecaching() { - if (mRenderer) { - mRenderer->endPrecaching(); - } -} - /////////////////////////////////////////////////////////////////////////////// // Lookup-based renderer /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h index ca55bf1e74e0..03f25106de38 100644 --- a/libs/hwui/GammaFontRenderer.h +++ b/libs/hwui/GammaFontRenderer.h @@ -37,9 +37,6 @@ public: virtual uint32_t getFontRendererCount() const = 0; virtual uint32_t getFontRendererSize(uint32_t fontRenderer, GLenum format) const = 0; - virtual void describe(ProgramDescription& description, const SkPaint* paint) const = 0; - virtual void setupProgram(ProgramDescription& description, Program& program) const = 0; - virtual void endPrecaching() = 0; static GammaFontRenderer* createRenderer(); @@ -53,52 +50,6 @@ protected: float mGamma; }; -class ShaderGammaFontRenderer: public GammaFontRenderer { -public: - ~ShaderGammaFontRenderer() { - delete mRenderer; - } - - void clear() override { - delete mRenderer; - mRenderer = nullptr; - } - - void flush() override { - if (mRenderer) { - mRenderer->flushLargeCaches(); - } - } - - FontRenderer& getFontRenderer(const SkPaint* paint) override { - if (!mRenderer) { - mRenderer = new FontRenderer; - } - return *mRenderer; - } - - uint32_t getFontRendererCount() const override { - return 1; - } - - uint32_t getFontRendererSize(uint32_t fontRenderer, GLenum format) const override { - return mRenderer ? mRenderer->getCacheSize(format) : 0; - } - - void describe(ProgramDescription& description, const SkPaint* paint) const override; - void setupProgram(ProgramDescription& description, Program& program) const override; - - void endPrecaching() override; - -private: - ShaderGammaFontRenderer(bool multiGamma); - - FontRenderer* mRenderer; - bool mMultiGamma; - - friend class GammaFontRenderer; -}; - class LookupGammaFontRenderer: public GammaFontRenderer { public: ~LookupGammaFontRenderer() { @@ -132,12 +83,6 @@ public: return mRenderer ? mRenderer->getCacheSize(format) : 0; } - void describe(ProgramDescription& description, const SkPaint* paint) const override { - } - - void setupProgram(ProgramDescription& description, Program& program) const override { - } - void endPrecaching() override; private: @@ -168,12 +113,6 @@ public: return mRenderers[fontRenderer]->getCacheSize(format); } - void describe(ProgramDescription& description, const SkPaint* paint) const override { - } - - void setupProgram(ProgramDescription& description, Program& program) const override { - } - void endPrecaching() override; private: diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index f503e5d6e8ba..4031f2e13f39 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -138,10 +138,10 @@ PathCache::PathCache(): mSize(0), mMaxSize(MB(DEFAULT_PATH_CACHE_SIZE)) { char property[PROPERTY_VALUE_MAX]; if (property_get(PROPERTY_PATH_CACHE_SIZE, property, nullptr) > 0) { - INIT_LOGD(" Setting %s cache size to %sMB", name, property); + INIT_LOGD(" Setting path cache size to %sMB", property); mMaxSize = MB(atof(property)); } else { - INIT_LOGD(" Using default %s cache size of %.2fMB", name, DEFAULT_PATH_CACHE_SIZE); + INIT_LOGD(" Using default path cache size of %.2fMB", DEFAULT_PATH_CACHE_SIZE); } mCache.setOnEntryRemovedListener(this); diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h index b09c207f6e45..e5200a516777 100644 --- a/libs/hwui/Program.h +++ b/libs/hwui/Program.h @@ -78,14 +78,12 @@ namespace uirenderer { #define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38 #define PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT 39 -#define PROGRAM_HAS_GAMMA_CORRECTION 40 +#define PROGRAM_IS_SIMPLE_GRADIENT 40 -#define PROGRAM_IS_SIMPLE_GRADIENT 41 +#define PROGRAM_HAS_COLORS 41 -#define PROGRAM_HAS_COLORS 42 - -#define PROGRAM_HAS_DEBUG_HIGHLIGHT 43 -#define PROGRAM_HAS_ROUND_RECT_CLIP 44 +#define PROGRAM_HAS_DEBUG_HIGHLIGHT 42 +#define PROGRAM_HAS_ROUND_RECT_CLIP 43 /////////////////////////////////////////////////////////////////////////////// // Types @@ -157,9 +155,6 @@ struct ProgramDescription { SkXfermode::Mode framebufferMode; bool swapSrcDst; - bool hasGammaCorrection; - float gamma; - bool hasDebugHighlight; bool hasRoundRectClip; @@ -199,9 +194,6 @@ struct ProgramDescription { framebufferMode = SkXfermode::kClear_Mode; swapSrcDst = false; - hasGammaCorrection = false; - gamma = 2.2f; - hasDebugHighlight = false; hasRoundRectClip = false; } @@ -266,7 +258,6 @@ struct ProgramDescription { if (useShadowAlphaInterp) key |= programid(0x1) << PROGRAM_USE_SHADOW_ALPHA_INTERP_SHIFT; if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT; if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT; - if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION; if (isSimpleGradient) key |= programid(0x1) << PROGRAM_IS_SIMPLE_GRADIENT; if (hasColors) key |= programid(0x1) << PROGRAM_HAS_COLORS; if (hasDebugHighlight) key |= programid(0x1) << PROGRAM_HAS_DEBUG_HIGHLIGHT; diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index b25a4ac9558d..05be48822fb2 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -167,8 +167,6 @@ const char* gFS_Uniforms_ColorOp[3] = { // PorterDuff "uniform vec4 colorBlend;\n" }; -const char* gFS_Uniforms_Gamma = - "uniform float gamma;\n"; const char* gFS_Uniforms_HasRoundRectClip = "uniform vec4 roundRectInnerRectLTRB;\n" @@ -204,18 +202,10 @@ const char* gFS_Fast_SingleA8Texture = "\nvoid main(void) {\n" " gl_FragColor = texture2D(baseSampler, outTexCoords);\n" "}\n\n"; -const char* gFS_Fast_SingleA8Texture_ApplyGamma = - "\nvoid main(void) {\n" - " gl_FragColor = vec4(0.0, 0.0, 0.0, pow(texture2D(baseSampler, outTexCoords).a, gamma));\n" - "}\n\n"; const char* gFS_Fast_SingleModulateA8Texture = "\nvoid main(void) {\n" " gl_FragColor = color * texture2D(baseSampler, outTexCoords).a;\n" "}\n\n"; -const char* gFS_Fast_SingleModulateA8Texture_ApplyGamma = - "\nvoid main(void) {\n" - " gl_FragColor = color * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n" - "}\n\n"; const char* gFS_Fast_SingleGradient[2] = { "\nvoid main(void) {\n" " gl_FragColor = %s + texture2D(gradientSampler, linear);\n" @@ -250,13 +240,11 @@ const char* gFS_Main_FetchTexture[2] = { // Modulate " fragColor = color * texture2D(baseSampler, outTexCoords);\n" }; -const char* gFS_Main_FetchA8Texture[4] = { +const char* gFS_Main_FetchA8Texture[2] = { // Don't modulate " fragColor = texture2D(baseSampler, outTexCoords);\n", - " fragColor = texture2D(baseSampler, outTexCoords);\n", // Modulate " fragColor = color * texture2D(baseSampler, outTexCoords).a;\n", - " fragColor = color * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n" }; const char* gFS_Main_FetchGradient[6] = { // Linear @@ -284,38 +272,29 @@ const char* gFS_Main_BlendShadersBG = " fragColor = blendShaders(gradientColor, bitmapColor)"; const char* gFS_Main_BlendShadersGB = " fragColor = blendShaders(bitmapColor, gradientColor)"; -const char* gFS_Main_BlendShaders_Modulate[6] = { +const char* gFS_Main_BlendShaders_Modulate[3] = { // Don't modulate ";\n", - ";\n", // Modulate " * color.a;\n", - " * color.a;\n", // Modulate with alpha 8 texture " * texture2D(baseSampler, outTexCoords).a;\n", - " * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n" }; -const char* gFS_Main_GradientShader_Modulate[6] = { +const char* gFS_Main_GradientShader_Modulate[3] = { // Don't modulate " fragColor = gradientColor;\n", - " fragColor = gradientColor;\n", // Modulate " fragColor = gradientColor * color.a;\n", - " fragColor = gradientColor * color.a;\n", // Modulate with alpha 8 texture " fragColor = gradientColor * texture2D(baseSampler, outTexCoords).a;\n", - " fragColor = gradientColor * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n" }; -const char* gFS_Main_BitmapShader_Modulate[6] = { +const char* gFS_Main_BitmapShader_Modulate[3] = { // Don't modulate " fragColor = bitmapColor;\n", - " fragColor = bitmapColor;\n", // Modulate " fragColor = bitmapColor * color.a;\n", - " fragColor = bitmapColor * color.a;\n", // Modulate with alpha 8 texture " fragColor = bitmapColor * texture2D(baseSampler, outTexCoords).a;\n", - " fragColor = bitmapColor * pow(texture2D(baseSampler, outTexCoords).a, gamma);\n" }; const char* gFS_Main_FragColor = " gl_FragColor = fragColor;\n"; @@ -540,7 +519,6 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description static bool shaderOp(const ProgramDescription& description, String8& shader, const int modulateOp, const char** snippets) { int op = description.hasAlpha8Texture ? MODULATE_OP_MODULATE_A8 : modulateOp; - op = op * 2 + description.hasGammaCorrection; shader.append(snippets[op]); return description.hasAlpha8Texture; } @@ -596,9 +574,6 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti shader.appendFormat(gFS_Uniforms_GradientSampler[description.isSimpleGradient], gFS_Uniforms_Dither); } - if (description.hasGammaCorrection) { - shader.append(gFS_Uniforms_Gamma); - } if (description.hasRoundRectClip) { shader.append(gFS_Uniforms_HasRoundRectClip); } @@ -633,17 +608,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti fast = true; } else if (singleA8Texture) { if (!description.modulate) { - if (description.hasGammaCorrection) { - shader.append(gFS_Fast_SingleA8Texture_ApplyGamma); - } else { - shader.append(gFS_Fast_SingleA8Texture); - } + shader.append(gFS_Fast_SingleA8Texture); } else { - if (description.hasGammaCorrection) { - shader.append(gFS_Fast_SingleModulateA8Texture_ApplyGamma); - } else { - shader.append(gFS_Fast_SingleModulateA8Texture); - } + shader.append(gFS_Fast_SingleModulateA8Texture); } fast = true; } else if (singleGradient) { @@ -693,8 +660,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (description.hasTexture || description.hasExternalTexture) { if (description.hasAlpha8Texture) { if (!description.hasGradient && !description.hasBitmap) { - shader.append(gFS_Main_FetchA8Texture[modulateOp * 2 + - description.hasGammaCorrection]); + shader.append(gFS_Main_FetchA8Texture[modulateOp]); } } else { shader.append(gFS_Main_FetchTexture[modulateOp]); diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 76028482ba86..98834b8f561d 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -242,7 +242,7 @@ enum DebugLevel { #define DEFAULT_RENDER_BUFFER_CACHE_SIZE 2.0f #define DEFAULT_PATH_CACHE_SIZE 4.0f #define DEFAULT_VERTEX_CACHE_SIZE 1.0f -#define DEFAULT_PATCH_CACHE_SIZE 128 // in kB +#define DEFAULT_PATCH_CACHE_SIZE 128.0f // in kB #define DEFAULT_GRADIENT_CACHE_SIZE 0.5f #define DEFAULT_DROP_SHADOW_CACHE_SIZE 2.0f #define DEFAULT_FBO_CACHE_SIZE 0 diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp index 01f5e2dba214..12a3e76c9387 100644 --- a/libs/hwui/TessellationCache.cpp +++ b/libs/hwui/TessellationCache.cpp @@ -312,10 +312,10 @@ TessellationCache::TessellationCache() , mShadowCache(LruCache*>::kUnlimitedCapacity) { char property[PROPERTY_VALUE_MAX]; if (property_get(PROPERTY_VERTEX_CACHE_SIZE, property, nullptr) > 0) { - INIT_LOGD(" Setting %s cache size to %sMB", name, property); + INIT_LOGD(" Setting tessellation cache size to %sMB", property); setMaxSize(MB(atof(property))); } else { - INIT_LOGD(" Using default %s cache size of %.2fMB", name, DEFAULT_VERTEX_CACHE_SIZE); + INIT_LOGD(" Using default tessellation cache size of %.2fMB", DEFAULT_VERTEX_CACHE_SIZE); } mCache.setOnEntryRemovedListener(&mBufferRemovedListener); -- cgit v1.2.3-59-g8ed1b From 6b50780363d3bb8db600c770183fa07677509ae8 Mon Sep 17 00:00:00 2001 From: John Reck Date: Tue, 3 Nov 2015 10:09:59 -0800 Subject: Remove almost-all android::Singleton users Bug: 25426213 Change-Id: I88e6206e8915cce95c3a8a8a82a4bb8fbf668141 --- libs/hwui/Caches.cpp | 1 + libs/hwui/Caches.h | 1 - libs/hwui/Extensions.cpp | 1 + libs/hwui/Extensions.h | 6 ------ libs/hwui/GradientCache.cpp | 2 ++ libs/hwui/PathCache.cpp | 2 ++ libs/hwui/Properties.cpp | 6 +++++- libs/hwui/Properties.h | 2 -- libs/hwui/RenderBufferCache.cpp | 6 ++++-- libs/hwui/renderthread/RenderProxy.cpp | 5 +---- libs/hwui/renderthread/RenderProxy.h | 3 --- libs/hwui/renderthread/RenderThread.cpp | 29 +++++++++++++++++++---------- libs/hwui/renderthread/RenderThread.h | 12 ++++++++---- 13 files changed, 43 insertions(+), 33 deletions(-) (limited to 'libs/hwui/PathCache.cpp') diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 7c63e316ba38..94a11f131229 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -23,6 +23,7 @@ #include "ShadowTessellator.h" #include "utils/GLUtils.h" +#include #include #include diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index 61e958d42148..330dc2951ec9 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -43,7 +43,6 @@ #include #include -#include #include diff --git a/libs/hwui/Extensions.cpp b/libs/hwui/Extensions.cpp index 06c8a21b019b..6dd29ad8c703 100644 --- a/libs/hwui/Extensions.cpp +++ b/libs/hwui/Extensions.cpp @@ -20,6 +20,7 @@ #include "Properties.h" #include "utils/StringUtils.h" +#include #include #include diff --git a/libs/hwui/Extensions.h b/libs/hwui/Extensions.h index 0a30d162f2e8..6689b88f17e3 100644 --- a/libs/hwui/Extensions.h +++ b/libs/hwui/Extensions.h @@ -19,12 +19,6 @@ #include -#include -#include -#include - -#include - namespace android { namespace uirenderer { diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp index aa105f9fec0a..8c4645092c97 100644 --- a/libs/hwui/GradientCache.cpp +++ b/libs/hwui/GradientCache.cpp @@ -21,6 +21,8 @@ #include "GradientCache.h" #include "Properties.h" +#include + namespace android { namespace uirenderer { diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index 4031f2e13f39..fd9ab1847f0d 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -30,6 +30,8 @@ #include "thread/Signal.h" #include "thread/TaskProcessor.h" +#include + namespace android { namespace uirenderer { diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index c0c61db0f5d1..e81818679f3e 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -17,8 +17,12 @@ #include "Debug.h" -#include +#include #include +#include + +#include +#include namespace android { namespace uirenderer { diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 74cd74bde176..1293c786a0bd 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -18,8 +18,6 @@ #define ANDROID_HWUI_PROPERTIES_H #include -#include -#include /** * This file contains the list of system properties used to configure diff --git a/libs/hwui/RenderBufferCache.cpp b/libs/hwui/RenderBufferCache.cpp index 8beed2540e1c..11d7a6af3a6a 100644 --- a/libs/hwui/RenderBufferCache.cpp +++ b/libs/hwui/RenderBufferCache.cpp @@ -14,12 +14,14 @@ * limitations under the License. */ -#include - #include "Debug.h" #include "Properties.h" #include "RenderBufferCache.h" +#include + +#include + namespace android { namespace uirenderer { diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 15ccd6ac5b6b..a1107f029691 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -563,10 +563,7 @@ void RenderProxy::post(RenderTask* task) { void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) { void* retval; task->setReturnPtr(&retval); - SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition); - AutoMutex _lock(mSyncMutex); - mRenderThread.queue(&syncTask); - mSyncCondition.wait(mSyncMutex); + mRenderThread.queueAndWait(task); return retval; } diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index 338fab650876..d0e601e09be6 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -117,9 +117,6 @@ private: DrawFrameTask mDrawFrameTask; - Mutex mSyncMutex; - Condition mSyncCondition; - void destroyContext(); void post(RenderTask* task); diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 8fcd10967e17..526a84861d98 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -28,9 +28,6 @@ #include namespace android { -using namespace uirenderer::renderthread; -ANDROID_SINGLETON_STATIC_INSTANCE(RenderThread); - namespace uirenderer { namespace renderthread { @@ -136,7 +133,22 @@ public: } }; -RenderThread::RenderThread() : Thread(true), Singleton() +static bool gHasRenderThreadInstance = false; + +bool RenderThread::hasInstance() { + return gHasRenderThreadInstance; +} + +RenderThread& RenderThread::getInstance() { + // This is a pointer because otherwise __cxa_finalize + // will try to delete it like a Good Citizen but that causes us to crash + // because we don't want to delete the RenderThread normally. + static RenderThread* sInstance = new RenderThread(); + gHasRenderThreadInstance = true; + return *sInstance; +} + +RenderThread::RenderThread() : Thread(true) , mNextWakeup(LLONG_MAX) , mDisplayEventReceiver(nullptr) , mVsyncRequested(false) @@ -313,13 +325,10 @@ void RenderThread::queue(RenderTask* task) { } void RenderThread::queueAndWait(RenderTask* task) { - Mutex mutex; - Condition condition; - SignalingRenderTask syncTask(task, &mutex, &condition); - - AutoMutex _lock(mutex); + SignalingRenderTask syncTask(task, &mSyncMutex, &mSyncCondition); + AutoMutex _lock(mSyncMutex); queue(&syncTask); - condition.wait(mutex); + mSyncCondition.wait(mSyncMutex); } void RenderThread::queueAtFront(RenderTask* task) { diff --git a/libs/hwui/renderthread/RenderThread.h b/libs/hwui/renderthread/RenderThread.h index f3444a85a336..d8c7e61f34eb 100644 --- a/libs/hwui/renderthread/RenderThread.h +++ b/libs/hwui/renderthread/RenderThread.h @@ -25,11 +25,11 @@ #include #include #include -#include -#include #include +#include #include +#include #include namespace android { @@ -72,7 +72,7 @@ protected: ~IFrameCallback() {} }; -class ANDROID_API RenderThread : public Thread, protected Singleton { +class ANDROID_API RenderThread : public Thread { public: // RenderThread takes complete ownership of tasks that are queued // and will delete them after they are run @@ -100,7 +100,6 @@ protected: virtual bool threadLoop() override; private: - friend class Singleton; friend class DispatchFrameCallbacks; friend class RenderProxy; friend class android::uirenderer::TestUtils; @@ -108,6 +107,9 @@ private: RenderThread(); virtual ~RenderThread(); + static bool hasInstance(); + static RenderThread& getInstance(); + void initThreadLocals(); void initializeDisplayEventReceiver(); static int displayEventReceiverCallback(int fd, int events, void* data); @@ -125,6 +127,8 @@ private: nsecs_t mNextWakeup; TaskQueue mQueue; + Mutex mSyncMutex; + Condition mSyncCondition; DisplayInfo mDisplayInfo; -- cgit v1.2.3-59-g8ed1b From 38e0c32852e3b9d8ca4a9d3791577f52536419cb Mon Sep 17 00:00:00 2001 From: John Reck Date: Tue, 10 Nov 2015 12:19:17 -0800 Subject: Track texture memory globally Also mostly consolidates texture creation Change-Id: Ifea01303afda531dcec99b8fe2a0f64cf2f24420 --- libs/hwui/Android.mk | 2 + libs/hwui/AssetAtlas.cpp | 57 +++--- libs/hwui/AssetAtlas.h | 31 ++-- libs/hwui/BakedOpDispatcher.cpp | 14 +- libs/hwui/BakedOpRenderer.cpp | 6 +- libs/hwui/GpuMemoryTracker.cpp | 140 +++++++++++++++ libs/hwui/GpuMemoryTracker.h | 76 ++++++++ libs/hwui/GradientCache.cpp | 24 +-- libs/hwui/GradientCache.h | 3 +- libs/hwui/Layer.cpp | 35 ++-- libs/hwui/Layer.h | 17 +- libs/hwui/LayerCache.cpp | 1 - libs/hwui/OpenGLRenderer.cpp | 18 +- libs/hwui/PathCache.cpp | 33 +--- libs/hwui/PathCache.h | 4 +- libs/hwui/SkiaShader.cpp | 6 +- libs/hwui/TextDropShadowCache.cpp | 9 +- libs/hwui/Texture.cpp | 208 +++++++++++++++++++++- libs/hwui/Texture.h | 85 +++++++-- libs/hwui/TextureCache.cpp | 9 +- libs/hwui/TextureCache.h | 1 + libs/hwui/font/CacheTexture.cpp | 28 +-- libs/hwui/font/CacheTexture.h | 7 +- libs/hwui/renderstate/OffscreenBufferPool.cpp | 31 ++-- libs/hwui/renderstate/OffscreenBufferPool.h | 10 +- libs/hwui/renderstate/RenderState.cpp | 8 +- libs/hwui/renderstate/TextureState.cpp | 128 ------------- libs/hwui/renderstate/TextureState.h | 7 - libs/hwui/renderthread/CanvasContext.cpp | 3 + libs/hwui/tests/common/TestUtils.h | 4 + libs/hwui/tests/macrobench/main.cpp | 1 + libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp | 70 ++++++++ libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp | 12 +- libs/hwui/tests/unit/StringUtilsTests.cpp | 15 ++ libs/hwui/utils/StringUtils.h | 17 ++ 35 files changed, 743 insertions(+), 377 deletions(-) create mode 100644 libs/hwui/GpuMemoryTracker.cpp create mode 100644 libs/hwui/GpuMemoryTracker.h create mode 100644 libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp (limited to 'libs/hwui/PathCache.cpp') diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index bbfc0221666c..cdd891fa5644 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -53,6 +53,7 @@ hwui_src_files := \ FrameInfoVisualizer.cpp \ GammaFontRenderer.cpp \ GlopBuilder.cpp \ + GpuMemoryTracker.cpp \ GradientCache.cpp \ Image.cpp \ Interpolator.cpp \ @@ -228,6 +229,7 @@ LOCAL_SRC_FILES += \ tests/unit/DamageAccumulatorTests.cpp \ tests/unit/DeviceInfoTests.cpp \ tests/unit/FatVectorTests.cpp \ + tests/unit/GpuMemoryTrackerTests.cpp \ tests/unit/LayerUpdateQueueTests.cpp \ tests/unit/LinearAllocatorTests.cpp \ tests/unit/VectorDrawableTests.cpp \ diff --git a/libs/hwui/AssetAtlas.cpp b/libs/hwui/AssetAtlas.cpp index 41411a98a4bf..6afff1b7158e 100644 --- a/libs/hwui/AssetAtlas.cpp +++ b/libs/hwui/AssetAtlas.cpp @@ -39,40 +39,22 @@ void AssetAtlas::init(sp buffer, int64_t* map, int count) { if (!mTexture) { Caches& caches = Caches::getInstance(); mTexture = new Texture(caches); - mTexture->width = buffer->getWidth(); - mTexture->height = buffer->getHeight(); + mTexture->wrap(mImage->getTexture(), + buffer->getWidth(), buffer->getHeight(), GL_RGBA); createEntries(caches, map, count); } } else { ALOGW("Could not create atlas image"); - delete mImage; - mImage = nullptr; + terminate(); } - - updateTextureId(); } void AssetAtlas::terminate() { - if (mImage) { - delete mImage; - mImage = nullptr; - updateTextureId(); - } -} - - -void AssetAtlas::updateTextureId() { - mTexture->id = mImage ? mImage->getTexture() : 0; - if (mTexture->id) { - // Texture ID changed, force-set to defaults to sync the wrapper & GL - // state objects - mTexture->setWrap(GL_CLAMP_TO_EDGE, false, true); - mTexture->setFilter(GL_NEAREST, false, true); - } - for (size_t i = 0; i < mEntries.size(); i++) { - AssetAtlas::Entry* entry = mEntries.valueAt(i); - entry->texture->id = mTexture->id; - } + delete mImage; + mImage = nullptr; + delete mTexture; + mTexture = nullptr; + mEntries.clear(); } /////////////////////////////////////////////////////////////////////////////// @@ -80,13 +62,13 @@ void AssetAtlas::updateTextureId() { /////////////////////////////////////////////////////////////////////////////// AssetAtlas::Entry* AssetAtlas::getEntry(const SkPixelRef* pixelRef) const { - ssize_t index = mEntries.indexOfKey(pixelRef); - return index >= 0 ? mEntries.valueAt(index) : nullptr; + auto result = mEntries.find(pixelRef); + return result != mEntries.end() ? result->second.get() : nullptr; } Texture* AssetAtlas::getEntryTexture(const SkPixelRef* pixelRef) const { - ssize_t index = mEntries.indexOfKey(pixelRef); - return index >= 0 ? mEntries.valueAt(index)->texture : nullptr; + auto result = mEntries.find(pixelRef); + return result != mEntries.end() ? result->second->texture : nullptr; } /** @@ -94,7 +76,8 @@ Texture* AssetAtlas::getEntryTexture(const SkPixelRef* pixelRef) const { * instead of applying the changes to the virtual textures. */ struct DelegateTexture: public Texture { - DelegateTexture(Caches& caches, Texture* delegate): Texture(caches), mDelegate(delegate) { } + DelegateTexture(Caches& caches, Texture* delegate) + : Texture(caches), mDelegate(delegate) { } virtual void setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false, GLenum renderTarget = GL_TEXTURE_2D) override { @@ -111,8 +94,8 @@ private: }; // struct DelegateTexture void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) { - const float width = float(mTexture->width); - const float height = float(mTexture->height); + const float width = float(mTexture->width()); + const float height = float(mTexture->height()); for (int i = 0; i < count; ) { SkPixelRef* pixelRef = reinterpret_cast(map[i++]); @@ -133,13 +116,13 @@ void AssetAtlas::createEntries(Caches& caches, int64_t* map, int count) { Texture* texture = new DelegateTexture(caches, mTexture); texture->blend = !SkAlphaTypeIsOpaque(pixelRef->info().alphaType()); - texture->width = pixelRef->info().width(); - texture->height = pixelRef->info().height(); + texture->wrap(mTexture->id(), pixelRef->info().width(), + pixelRef->info().height(), mTexture->format()); - Entry* entry = new Entry(pixelRef, texture, mapper, *this); + std::unique_ptr entry(new Entry(pixelRef, texture, mapper, *this)); texture->uvMapper = &entry->uvMapper; - mEntries.add(entry->pixelRef, entry); + mEntries.emplace(entry->pixelRef, std::move(entry)); } } diff --git a/libs/hwui/AssetAtlas.h b/libs/hwui/AssetAtlas.h index a037725b1c6c..75400ff494c3 100644 --- a/libs/hwui/AssetAtlas.h +++ b/libs/hwui/AssetAtlas.h @@ -17,18 +17,16 @@ #ifndef ANDROID_HWUI_ASSET_ATLAS_H #define ANDROID_HWUI_ASSET_ATLAS_H -#include - -#include - -#include +#include "Texture.h" +#include "UvMapper.h" #include - +#include +#include #include -#include "Texture.h" -#include "UvMapper.h" +#include +#include namespace android { namespace uirenderer { @@ -71,6 +69,10 @@ public: return texture->blend ? &atlas.mBlendKey : &atlas.mOpaqueKey; } + ~Entry() { + delete texture; + } + private: /** * The pixel ref that generated this atlas entry. @@ -90,10 +92,6 @@ public: , atlas(atlas) { } - ~Entry() { - delete texture; - } - friend class AssetAtlas; }; @@ -127,7 +125,7 @@ public: * Can return 0 if the atlas is not initialized. */ uint32_t getWidth() const { - return mTexture ? mTexture->width : 0; + return mTexture ? mTexture->width() : 0; } /** @@ -135,7 +133,7 @@ public: * Can return 0 if the atlas is not initialized. */ uint32_t getHeight() const { - return mTexture ? mTexture->height : 0; + return mTexture ? mTexture->height() : 0; } /** @@ -143,7 +141,7 @@ public: * Can return 0 if the atlas is not initialized. */ GLuint getTexture() const { - return mTexture ? mTexture->id : 0; + return mTexture ? mTexture->id() : 0; } /** @@ -160,7 +158,6 @@ public: private: void createEntries(Caches& caches, int64_t* map, int count); - void updateTextureId(); Texture* mTexture; Image* mImage; @@ -168,7 +165,7 @@ private: const bool mBlendKey; const bool mOpaqueKey; - KeyedVector mEntries; + std::unordered_map> mEntries; }; // class AssetAtlas }; // namespace uirenderer diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp index 5b34f6b79199..6b0c1499336f 100644 --- a/libs/hwui/BakedOpDispatcher.cpp +++ b/libs/hwui/BakedOpDispatcher.cpp @@ -217,7 +217,7 @@ static void renderTextShadow(BakedOpRenderer& renderer, FontRenderer& fontRender .setMeshTexturedUnitQuad(nullptr) .setFillShadowTexturePaint(*texture, textShadow.color, *op.paint, state.alpha) .setTransform(state.computedState.transform, TransformFlags::None) - .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height)) + .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width(), sy + texture->height())) .build(); renderer.renderGlop(state, glop); } @@ -337,7 +337,7 @@ static void renderConvexPath(BakedOpRenderer& renderer, const BakedOpState& stat static void renderPathTexture(BakedOpRenderer& renderer, const BakedOpState& state, PathTexture& texture, const RecordedOp& op) { - Rect dest(texture.width, texture.height); + Rect dest(texture.width(), texture.height()); dest.translate(texture.left - texture.offset, texture.top - texture.offset); Glop glop; @@ -399,7 +399,7 @@ void BakedOpDispatcher::onBitmapOp(BakedOpRenderer& renderer, const BitmapOp& op .setMeshTexturedUnitQuad(texture->uvMapper) .setFillTexturePaint(*texture, textureFillFlags, op.paint, state.alpha) .setTransform(state.computedState.transform, TransformFlags::None) - .setModelViewMapUnitToRectSnap(Rect(texture->width, texture->height)) + .setModelViewMapUnitToRectSnap(Rect(texture->width(), texture->height())) .build(); renderer.renderGlop(state, glop); } @@ -483,10 +483,10 @@ void BakedOpDispatcher::onBitmapRectOp(BakedOpRenderer& renderer, const BitmapRe if (!texture) return; const AutoTexture autoCleanup(texture); - Rect uv(std::max(0.0f, op.src.left / texture->width), - std::max(0.0f, op.src.top / texture->height), - std::min(1.0f, op.src.right / texture->width), - std::min(1.0f, op.src.bottom / texture->height)); + Rect uv(std::max(0.0f, op.src.left / texture->width()), + std::max(0.0f, op.src.top / texture->height()), + std::min(1.0f, op.src.right / texture->width()), + std::min(1.0f, op.src.bottom / texture->height())); const int textureFillFlags = (op.bitmap->colorType() == kAlpha_8_SkColorType) ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None; diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp index 42fb66fe9845..4fbff0d107ba 100644 --- a/libs/hwui/BakedOpRenderer.cpp +++ b/libs/hwui/BakedOpRenderer.cpp @@ -48,7 +48,7 @@ void BakedOpRenderer::startRepaintLayer(OffscreenBuffer* offscreenBuffer, const // attach the texture to the FBO glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, - offscreenBuffer->texture.id, 0); + offscreenBuffer->texture.id(), 0); LOG_ALWAYS_FATAL_IF(GLUtils::dumpGLErrors(), "startLayer FAILED"); LOG_ALWAYS_FATAL_IF(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE, "framebuffer incomplete!"); @@ -84,7 +84,7 @@ OffscreenBuffer* BakedOpRenderer::copyToLayer(const Rect& area) { area.getWidth(), area.getHeight()); if (!area.isEmpty()) { mCaches.textureState().activateTexture(0); - mCaches.textureState().bindTexture(buffer->texture.id); + mCaches.textureState().bindTexture(buffer->texture.id()); glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, area.left, mRenderTarget.viewportHeight - area.bottom, @@ -272,7 +272,7 @@ void BakedOpRenderer::prepareRender(const Rect* dirtyBounds, const ClipBase* cli OffscreenBuffer* layer = mRenderTarget.offscreenBuffer; mRenderTarget.stencil = mCaches.renderBufferCache.get( Stencil::getLayerStencilFormat(), - layer->texture.width, layer->texture.height); + layer->texture.width(), layer->texture.height()); // stencil is bound + allocated - associate it with current FBO glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, mRenderTarget.stencil->getName()); diff --git a/libs/hwui/GpuMemoryTracker.cpp b/libs/hwui/GpuMemoryTracker.cpp new file mode 100644 index 000000000000..4fb57019264d --- /dev/null +++ b/libs/hwui/GpuMemoryTracker.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "utils/StringUtils.h" +#include "Texture.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace android { +namespace uirenderer { + +pthread_t gGpuThread = 0; + +#define NUM_TYPES static_cast(GpuObjectType::TypeCount) + +const char* TYPE_NAMES[] = { + "Texture", + "OffscreenBuffer", + "Layer", +}; + +struct TypeStats { + int totalSize = 0; + int count = 0; +}; + +static std::array gObjectStats; +static std::unordered_set gObjectSet; + +void GpuMemoryTracker::notifySizeChanged(int newSize) { + int delta = newSize - mSize; + mSize = newSize; + gObjectStats[static_cast(mType)].totalSize += delta; +} + +void GpuMemoryTracker::startTrackingObject() { + auto result = gObjectSet.insert(this); + LOG_ALWAYS_FATAL_IF(!result.second, + "startTrackingObject() on %p failed, already being tracked!", this); + gObjectStats[static_cast(mType)].count++; +} + +void GpuMemoryTracker::stopTrackingObject() { + size_t removed = gObjectSet.erase(this); + LOG_ALWAYS_FATAL_IF(removed != 1, + "stopTrackingObject removed %zd, is %p not being tracked?", + removed, this); + gObjectStats[static_cast(mType)].count--; +} + +void GpuMemoryTracker::onGLContextCreated() { + LOG_ALWAYS_FATAL_IF(gGpuThread != 0, "We already have a GL thread? " + "current = %lu, gl thread = %lu", pthread_self(), gGpuThread); + gGpuThread = pthread_self(); +} + +void GpuMemoryTracker::onGLContextDestroyed() { + gGpuThread = 0; + if (CC_UNLIKELY(gObjectSet.size() > 0)) { + std::stringstream os; + dump(os); + ALOGE("%s", os.str().c_str()); + LOG_ALWAYS_FATAL("Leaked %zd GPU objects!", gObjectSet.size()); + } +} + +void GpuMemoryTracker::dump() { + std::stringstream strout; + dump(strout); + ALOGD("%s", strout.str().c_str()); +} + +void GpuMemoryTracker::dump(std::ostream& stream) { + for (int type = 0; type < NUM_TYPES; type++) { + const TypeStats& stats = gObjectStats[type]; + stream << TYPE_NAMES[type]; + stream << " is using " << SizePrinter{stats.totalSize}; + stream << ", count = " << stats.count; + stream << std::endl; + } +} + +int GpuMemoryTracker::getInstanceCount(GpuObjectType type) { + return gObjectStats[static_cast(type)].count; +} + +int GpuMemoryTracker::getTotalSize(GpuObjectType type) { + return gObjectStats[static_cast(type)].totalSize; +} + +void GpuMemoryTracker::onFrameCompleted() { + if (ATRACE_ENABLED()) { + char buf[128]; + for (int type = 0; type < NUM_TYPES; type++) { + snprintf(buf, 128, "hwui_%s", TYPE_NAMES[type]); + const TypeStats& stats = gObjectStats[type]; + ATRACE_INT(buf, stats.totalSize); + snprintf(buf, 128, "hwui_%s_count", TYPE_NAMES[type]); + ATRACE_INT(buf, stats.count); + } + } + + std::vector freeList; + for (const auto& obj : gObjectSet) { + if (obj->objectType() == GpuObjectType::Texture) { + const Texture* texture = static_cast(obj); + if (texture->cleanup) { + ALOGE("Leaked texture marked for cleanup! id=%u, size %ux%u", + texture->id(), texture->width(), texture->height()); + freeList.push_back(texture); + } + } + } + for (auto& texture : freeList) { + const_cast(texture)->deleteTexture(); + delete texture; + } +} + +} // namespace uirenderer +} // namespace android; diff --git a/libs/hwui/GpuMemoryTracker.h b/libs/hwui/GpuMemoryTracker.h new file mode 100644 index 000000000000..851aeae8352c --- /dev/null +++ b/libs/hwui/GpuMemoryTracker.h @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include +#include + +namespace android { +namespace uirenderer { + +extern pthread_t gGpuThread; + +#define ASSERT_GPU_THREAD() LOG_ALWAYS_FATAL_IF( \ + !pthread_equal(gGpuThread, pthread_self()), \ + "Error, %p of type %d (size=%d) used on wrong thread! cur thread %lu " \ + "!= gpu thread %lu", this, static_cast(mType), mSize, \ + pthread_self(), gGpuThread) + +enum class GpuObjectType { + Texture = 0, + OffscreenBuffer, + Layer, + + TypeCount, +}; + +class GpuMemoryTracker { +public: + GpuObjectType objectType() { return mType; } + int objectSize() { return mSize; } + + static void onGLContextCreated(); + static void onGLContextDestroyed(); + static void dump(); + static void dump(std::ostream& stream); + static int getInstanceCount(GpuObjectType type); + static int getTotalSize(GpuObjectType type); + static void onFrameCompleted(); + +protected: + GpuMemoryTracker(GpuObjectType type) : mType(type) { + ASSERT_GPU_THREAD(); + startTrackingObject(); + } + + ~GpuMemoryTracker() { + notifySizeChanged(0); + stopTrackingObject(); + } + + void notifySizeChanged(int newSize); + +private: + void startTrackingObject(); + void stopTrackingObject(); + + int mSize = 0; + GpuObjectType mType; +}; + +} // namespace uirenderer +} // namespace android; diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp index 8c4645092c97..522aa96132dd 100644 --- a/libs/hwui/GradientCache.cpp +++ b/libs/hwui/GradientCache.cpp @@ -110,9 +110,7 @@ void GradientCache::setMaxSize(uint32_t maxSize) { void GradientCache::operator()(GradientCacheEntry&, Texture*& texture) { if (texture) { - const uint32_t size = texture->width * texture->height * bytesPerPixel(); - mSize -= size; - + mSize -= texture->objectSize(); texture->deleteTexture(); delete texture; } @@ -167,18 +165,16 @@ Texture* GradientCache::addLinearGradient(GradientCacheEntry& gradient, getGradientInfo(colors, count, info); Texture* texture = new Texture(Caches::getInstance()); - texture->width = info.width; - texture->height = 2; texture->blend = info.hasAlpha; texture->generation = 1; // Asume the cache is always big enough - const uint32_t size = texture->width * texture->height * bytesPerPixel(); + const uint32_t size = info.width * 2 * bytesPerPixel(); while (getSize() + size > mMaxSize) { mCache.removeOldest(); } - generateTexture(colors, positions, texture); + generateTexture(colors, positions, info.width, 2, texture); mSize += size; mCache.put(gradient, texture); @@ -231,10 +227,10 @@ void GradientCache::mixFloats(GradientColor& start, GradientColor& end, float am dst += 4 * sizeof(float); } -void GradientCache::generateTexture(uint32_t* colors, float* positions, Texture* texture) { - const uint32_t width = texture->width; +void GradientCache::generateTexture(uint32_t* colors, float* positions, + const uint32_t width, const uint32_t height, Texture* texture) { const GLsizei rowBytes = width * bytesPerPixel(); - uint8_t pixels[rowBytes * texture->height]; + uint8_t pixels[rowBytes * height]; static ChannelSplitter gSplitters[] = { &android::uirenderer::GradientCache::splitToBytes, @@ -277,17 +273,13 @@ void GradientCache::generateTexture(uint32_t* colors, float* positions, Texture* memcpy(pixels + rowBytes, pixels, rowBytes); - glGenTextures(1, &texture->id); - Caches::getInstance().textureState().bindTexture(texture->id); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); if (mUseFloatTexture) { // We have to use GL_RGBA16F because GL_RGBA32F does not support filtering - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, texture->height, 0, - GL_RGBA, GL_FLOAT, pixels); + texture->upload(width, height, GL_RGBA16F, GL_RGBA, GL_FLOAT, pixels); } else { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, texture->height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, pixels); + texture->upload(width, height, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, pixels); } texture->setFilter(GL_LINEAR); diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h index 7534c5d11164..b762ca7d5e5c 100644 --- a/libs/hwui/GradientCache.h +++ b/libs/hwui/GradientCache.h @@ -143,7 +143,8 @@ private: Texture* addLinearGradient(GradientCacheEntry& gradient, uint32_t* colors, float* positions, int count); - void generateTexture(uint32_t* colors, float* positions, Texture* texture); + void generateTexture(uint32_t* colors, float* positions, + const uint32_t width, const uint32_t height, Texture* texture); struct GradientInfo { uint32_t width; diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index 0fe20ad1b662..7a74b9825d80 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -36,7 +36,8 @@ namespace android { namespace uirenderer { Layer::Layer(Type layerType, RenderState& renderState, uint32_t layerWidth, uint32_t layerHeight) - : state(State::Uncached) + : GpuMemoryTracker(GpuObjectType::Layer) + , state(State::Uncached) , caches(Caches::getInstance()) , renderState(renderState) , texture(caches) @@ -45,8 +46,8 @@ Layer::Layer(Type layerType, RenderState& renderState, uint32_t layerWidth, uint // preserves the old inc/dec ref locations. This should be changed... incStrong(nullptr); renderTarget = GL_TEXTURE_2D; - texture.width = layerWidth; - texture.height = layerHeight; + texture.mWidth = layerWidth; + texture.mHeight = layerHeight; renderState.registerLayer(this); } @@ -54,10 +55,10 @@ Layer::~Layer() { renderState.unregisterLayer(this); SkSafeUnref(colorFilter); - if (stencil || fbo || texture.id) { + if (stencil || fbo || texture.mId) { renderState.requireGLContext(); removeFbo(); - deleteTexture(); + texture.deleteTexture(); } delete[] mesh; @@ -65,7 +66,7 @@ Layer::~Layer() { void Layer::onGlContextLost() { removeFbo(); - deleteTexture(); + texture.deleteTexture(); } uint32_t Layer::computeIdealWidth(uint32_t layerWidth) { @@ -179,8 +180,8 @@ void Layer::setColorFilter(SkColorFilter* filter) { } void Layer::bindTexture() const { - if (texture.id) { - caches.textureState().bindTexture(renderTarget, texture.id); + if (texture.mId) { + caches.textureState().bindTexture(renderTarget, texture.mId); } } @@ -191,28 +192,22 @@ void Layer::bindStencilRenderBuffer() const { } void Layer::generateTexture() { - if (!texture.id) { - glGenTextures(1, &texture.id); - } -} - -void Layer::deleteTexture() { - if (texture.id) { - texture.deleteTexture(); - texture.id = 0; + if (!texture.mId) { + glGenTextures(1, &texture.mId); } } void Layer::clearTexture() { - caches.textureState().unbindTexture(texture.id); - texture.id = 0; + caches.textureState().unbindTexture(texture.mId); + texture.mId = 0; } void Layer::allocateTexture() { #if DEBUG_LAYERS ALOGD(" Allocate layer: %dx%d", getWidth(), getHeight()); #endif - if (texture.id) { + if (texture.mId) { + texture.updateSize(getWidth(), getHeight(), GL_RGBA); glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glTexImage2D(renderTarget, 0, GL_RGBA, getWidth(), getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index e90f055b667b..e00ae66997a5 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -24,6 +24,7 @@ #include #include +#include #include @@ -54,7 +55,7 @@ struct DeferStateStruct; /** * A layer has dimensions and is backed by an OpenGL texture or FBO. */ -class Layer : public VirtualLightRefBase { +class Layer : public VirtualLightRefBase, GpuMemoryTracker { public: enum class Type { Texture, @@ -94,8 +95,8 @@ public: regionRect.set(bounds.leftTop().x, bounds.leftTop().y, bounds.rightBottom().x, bounds.rightBottom().y); - const float texX = 1.0f / float(texture.width); - const float texY = 1.0f / float(texture.height); + const float texX = 1.0f / float(texture.mWidth); + const float texY = 1.0f / float(texture.mHeight); const float height = layer.getHeight(); texCoords.set( regionRect.left * texX, (height - regionRect.top) * texY, @@ -112,11 +113,11 @@ public: void updateDeferred(RenderNode* renderNode, int left, int top, int right, int bottom); inline uint32_t getWidth() const { - return texture.width; + return texture.mWidth; } inline uint32_t getHeight() const { - return texture.height; + return texture.mHeight; } /** @@ -131,8 +132,7 @@ public: bool resize(const uint32_t width, const uint32_t height); void setSize(uint32_t width, uint32_t height) { - texture.width = width; - texture.height = height; + texture.updateSize(width, height, texture.format()); } ANDROID_API void setPaint(const SkPaint* paint); @@ -201,7 +201,7 @@ public: } inline GLuint getTextureId() const { - return texture.id; + return texture.id(); } inline Texture& getTexture() { @@ -263,7 +263,6 @@ public: void bindTexture() const; void generateTexture(); void allocateTexture(); - void deleteTexture(); /** * When the caller frees the texture itself, the caller diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index b117754347ed..f5681ce712d5 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -112,7 +112,6 @@ Layer* LayerCache::get(RenderState& renderState, const uint32_t width, const uin layer->bindTexture(); layer->setFilter(GL_NEAREST); layer->setWrap(GL_CLAMP_TO_EDGE, false); - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); #if DEBUG_LAYERS dump(); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 92b758de8200..0cd763df78d1 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include "OpenGLRenderer.h" #include "DeferredDisplayList.h" @@ -200,6 +201,7 @@ bool OpenGLRenderer::finish() { #if DEBUG_MEMORY_USAGE mCaches.dumpMemoryUsage(); + GPUMemoryTracker::dump(); #else if (Properties::debugLevel & kDebugMemory) { mCaches.dumpMemoryUsage(); @@ -1497,7 +1499,7 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, const SkPaint* paint) { .setMeshTexturedUnitQuad(texture->uvMapper) .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha) .setTransform(*currentSnapshot(), TransformFlags::None) - .setModelViewMapUnitToRectSnap(Rect(texture->width, texture->height)) + .setModelViewMapUnitToRectSnap(Rect(texture->width(), texture->height())) .build(); renderGlop(glop); } @@ -1601,10 +1603,10 @@ void OpenGLRenderer::drawBitmap(const SkBitmap* bitmap, Rect src, Rect dst, cons if (!texture) return; const AutoTexture autoCleanup(texture); - Rect uv(std::max(0.0f, src.left / texture->width), - std::max(0.0f, src.top / texture->height), - std::min(1.0f, src.right / texture->width), - std::min(1.0f, src.bottom / texture->height)); + Rect uv(std::max(0.0f, src.left / texture->width()), + std::max(0.0f, src.top / texture->height()), + std::min(1.0f, src.right / texture->width()), + std::min(1.0f, src.bottom / texture->height())); const int textureFillFlags = (bitmap->colorType() == kAlpha_8_SkColorType) ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None; @@ -1977,7 +1979,7 @@ void OpenGLRenderer::drawTextShadow(const SkPaint* paint, const char* text, .setMeshTexturedUnitQuad(nullptr) .setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha) .setTransform(*currentSnapshot(), TransformFlags::None) - .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height)) + .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width(), sy + texture->height())) .build(); renderGlop(glop); } @@ -2316,7 +2318,7 @@ Texture* OpenGLRenderer::getTexture(const SkBitmap* bitmap) { void OpenGLRenderer::drawPathTexture(PathTexture* texture, float x, float y, const SkPaint* paint) { - if (quickRejectSetupScissor(x, y, x + texture->width, y + texture->height)) { + if (quickRejectSetupScissor(x, y, x + texture->width(), y + texture->height())) { return; } @@ -2326,7 +2328,7 @@ void OpenGLRenderer::drawPathTexture(PathTexture* texture, float x, float y, .setMeshTexturedUnitQuad(nullptr) .setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha) .setTransform(*currentSnapshot(), TransformFlags::None) - .setModelViewMapUnitToRect(Rect(x, y, x + texture->width, y + texture->height)) + .setModelViewMapUnitToRect(Rect(x, y, x + texture->width(), y + texture->height())) .build(); renderGlop(glop); } diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index 06ea55ad2eac..bfabc1d4d94c 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -185,7 +185,7 @@ void PathCache::operator()(PathDescription& entry, PathTexture*& texture) { void PathCache::removeTexture(PathTexture* texture) { if (texture) { - const uint32_t size = texture->width * texture->height; + const uint32_t size = texture->width() * texture->height(); // If there is a pending task we must wait for it to return // before attempting our cleanup @@ -209,9 +209,7 @@ void PathCache::removeTexture(PathTexture* texture) { ALOGD("Shape deleted, size = %d", size); } - if (texture->id) { - Caches::getInstance().textureState().deleteTexture(texture->id); - } + texture->deleteTexture(); delete texture; } } @@ -248,8 +246,7 @@ PathTexture* PathCache::addTexture(const PathDescription& entry, const SkPath *p drawPath(path, paint, bitmap, left, top, offset, width, height); PathTexture* texture = new PathTexture(Caches::getInstance(), - left, top, offset, width, height, - path->getGenerationID()); + left, top, offset, path->getGenerationID()); generateTexture(entry, &bitmap, texture); return texture; @@ -262,7 +259,7 @@ void PathCache::generateTexture(const PathDescription& entry, SkBitmap* bitmap, // Note here that we upload to a texture even if it's bigger than mMaxSize. // Such an entry in mCache will only be temporary, since it will be evicted // immediately on trim, or on any other Path entering the cache. - uint32_t size = texture->width * texture->height; + uint32_t size = texture->width() * texture->height(); mSize += size; PATH_LOGD("PathCache::get/create: name, size, mSize = %d, %d, %d", texture->id, size, mSize); @@ -280,24 +277,8 @@ void PathCache::clear() { void PathCache::generateTexture(SkBitmap& bitmap, Texture* texture) { ATRACE_NAME("Upload Path Texture"); - SkAutoLockPixels alp(bitmap); - if (!bitmap.readyToDraw()) { - ALOGE("Cannot generate texture from bitmap"); - return; - } - - glGenTextures(1, &texture->id); - - Caches::getInstance().textureState().bindTexture(texture->id); - // Textures are Alpha8 - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - - texture->blend = true; - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0, - GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.getPixels()); - + texture->upload(bitmap); texture->setFilter(GL_LINEAR); - texture->setWrap(GL_CLAMP_TO_EDGE); } /////////////////////////////////////////////////////////////////////////////// @@ -320,16 +301,12 @@ void PathCache::PathProcessor::onProcess(const sp >& task) { texture->left = left; texture->top = top; texture->offset = offset; - texture->width = width; - texture->height = height; if (width <= mMaxTextureSize && height <= mMaxTextureSize) { SkBitmap* bitmap = new SkBitmap(); drawPath(&t->path, &t->paint, *bitmap, left, top, offset, width, height); t->setResult(bitmap); } else { - texture->width = 0; - texture->height = 0; t->setResult(nullptr); } } diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h index 302e9f856904..18f380fe3f7a 100644 --- a/libs/hwui/PathCache.h +++ b/libs/hwui/PathCache.h @@ -61,13 +61,11 @@ class Caches; */ struct PathTexture: public Texture { PathTexture(Caches& caches, float left, float top, - float offset, int width, int height, int generation) + float offset, int generation) : Texture(caches) , left(left) , top(top) , offset(offset) { - this->width = width; - this->height = height; this->generation = generation; } PathTexture(Caches& caches, int generation) diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index 83652c6de21f..6f4a6839be4e 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -57,7 +57,7 @@ static inline void bindUniformColor(int slot, FloatColor color) { } static inline void bindTexture(Caches* caches, Texture* texture, GLenum wrapS, GLenum wrapT) { - caches->textureState().bindTexture(texture->id); + caches->textureState().bindTexture(texture->id()); texture->setWrapST(wrapS, wrapT); } @@ -219,8 +219,8 @@ bool tryStoreBitmap(Caches& caches, const SkShader& shader, const Matrix4& model outData->bitmapSampler = (*textureUnit)++; - const float width = outData->bitmapTexture->width; - const float height = outData->bitmapTexture->height; + const float width = outData->bitmapTexture->width(); + const float height = outData->bitmapTexture->height(); description->hasBitmap = true; if (!caches.extensions().hasNPot() diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp index 51f16523966b..f1e28b7dfa40 100644 --- a/libs/hwui/TextDropShadowCache.cpp +++ b/libs/hwui/TextDropShadowCache.cpp @@ -187,13 +187,10 @@ ShadowTexture* TextDropShadowCache::get(const SkPaint* paint, const char* glyphs texture = new ShadowTexture(caches); texture->left = shadow.penX; texture->top = shadow.penY; - texture->width = shadow.width; - texture->height = shadow.height; texture->generation = 0; texture->blend = true; const uint32_t size = shadow.width * shadow.height; - texture->bitmapSize = size; // Don't even try to cache a bitmap that's bigger than the cache if (size < mMaxSize) { @@ -202,15 +199,11 @@ ShadowTexture* TextDropShadowCache::get(const SkPaint* paint, const char* glyphs } } - glGenTextures(1, &texture->id); - - caches.textureState().bindTexture(texture->id); // Textures are Alpha8 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, texture->width, texture->height, 0, + texture->upload(GL_ALPHA, shadow.width, shadow.height, GL_ALPHA, GL_UNSIGNED_BYTE, shadow.image); - texture->setFilter(GL_LINEAR); texture->setWrap(GL_CLAMP_TO_EDGE); diff --git a/libs/hwui/Texture.cpp b/libs/hwui/Texture.cpp index 5195b457af2b..8a6b28d86f27 100644 --- a/libs/hwui/Texture.cpp +++ b/libs/hwui/Texture.cpp @@ -14,14 +14,29 @@ * limitations under the License. */ -#include - #include "Caches.h" #include "Texture.h" +#include "utils/TraceUtils.h" + +#include + +#include namespace android { namespace uirenderer { +static int bytesPerPixel(GLint glFormat) { + switch (glFormat) { + case GL_ALPHA: + return 1; + case GL_RGB: + return 3; + case GL_RGBA: + default: + return 4; + } +} + void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force, GLenum renderTarget) { @@ -32,7 +47,7 @@ void Texture::setWrapST(GLenum wrapS, GLenum wrapT, bool bindTexture, bool force mWrapT = wrapT; if (bindTexture) { - mCaches.textureState().bindTexture(renderTarget, id); + mCaches.textureState().bindTexture(renderTarget, mId); } glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS); @@ -50,7 +65,7 @@ void Texture::setFilterMinMag(GLenum min, GLenum mag, bool bindTexture, bool for mMagFilter = mag; if (bindTexture) { - mCaches.textureState().bindTexture(renderTarget, id); + mCaches.textureState().bindTexture(renderTarget, mId); } if (mipMap && min == GL_LINEAR) min = GL_LINEAR_MIPMAP_LINEAR; @@ -60,8 +75,189 @@ void Texture::setFilterMinMag(GLenum min, GLenum mag, bool bindTexture, bool for } } -void Texture::deleteTexture() const { - mCaches.textureState().deleteTexture(id); +void Texture::deleteTexture() { + mCaches.textureState().deleteTexture(mId); + mId = 0; +} + +bool Texture::updateSize(uint32_t width, uint32_t height, GLint format) { + if (mWidth == width && mHeight == height && mFormat == format) { + return false; + } + mWidth = width; + mHeight = height; + mFormat = format; + notifySizeChanged(mWidth * mHeight * bytesPerPixel(mFormat)); + return true; +} + +void Texture::upload(GLint internalformat, uint32_t width, uint32_t height, + GLenum format, GLenum type, const void* pixels) { + bool needsAlloc = updateSize(width, height, internalformat); + if (!needsAlloc && !pixels) { + return; + } + mCaches.textureState().activateTexture(0); + if (!mId) { + glGenTextures(1, &mId); + needsAlloc = true; + } + mCaches.textureState().bindTexture(GL_TEXTURE_2D, mId); + if (needsAlloc) { + glTexImage2D(GL_TEXTURE_2D, 0, mFormat, mWidth, mHeight, 0, + format, type, pixels); + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, mFormat, mWidth, mHeight, 0, + format, type, pixels); + } +} + +static void uploadToTexture(bool resize, GLenum format, GLenum type, GLsizei stride, GLsizei bpp, + GLsizei width, GLsizei height, const GLvoid * data) { + + glPixelStorei(GL_UNPACK_ALIGNMENT, bpp); + const bool useStride = stride != width + && Caches::getInstance().extensions().hasUnpackRowLength(); + if ((stride == width) || useStride) { + if (useStride) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, stride); + } + + if (resize) { + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data); + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data); + } + + if (useStride) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + } + } else { + // With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer + // if the stride doesn't match the width + + GLvoid * temp = (GLvoid *) malloc(width * height * bpp); + if (!temp) return; + + uint8_t * pDst = (uint8_t *)temp; + uint8_t * pSrc = (uint8_t *)data; + for (GLsizei i = 0; i < height; i++) { + memcpy(pDst, pSrc, width * bpp); + pDst += width * bpp; + pSrc += stride * bpp; + } + + if (resize) { + glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, temp); + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, temp); + } + + free(temp); + } +} + +static void uploadSkBitmapToTexture(const SkBitmap& bitmap, + bool resize, GLenum format, GLenum type) { + uploadToTexture(resize, format, type, bitmap.rowBytesAsPixels(), bitmap.bytesPerPixel(), + bitmap.width(), bitmap.height(), bitmap.getPixels()); +} + +static void colorTypeToGlFormatAndType(SkColorType colorType, + GLint* outFormat, GLint* outType) { + switch (colorType) { + case kAlpha_8_SkColorType: + *outFormat = GL_ALPHA; + *outType = GL_UNSIGNED_BYTE; + break; + case kRGB_565_SkColorType: + *outFormat = GL_RGB; + *outType = GL_UNSIGNED_SHORT_5_6_5; + break; + // ARGB_4444 and Index_8 are both upconverted to RGBA_8888 + case kARGB_4444_SkColorType: + case kIndex_8_SkColorType: + case kN32_SkColorType: + *outFormat = GL_RGBA; + *outType = GL_UNSIGNED_BYTE; + break; + default: + LOG_ALWAYS_FATAL("Unsupported bitmap colorType: %d", colorType); + break; + } +} + +void Texture::upload(const SkBitmap& bitmap) { + SkAutoLockPixels alp(bitmap); + + if (!bitmap.readyToDraw()) { + ALOGE("Cannot generate texture from bitmap"); + return; + } + + ATRACE_FORMAT("Upload %ux%u Texture", bitmap.width(), bitmap.height()); + + // We could also enable mipmapping if both bitmap dimensions are powers + // of 2 but we'd have to deal with size changes. Let's keep this simple + const bool canMipMap = mCaches.extensions().hasNPot(); + + // If the texture had mipmap enabled but not anymore, + // force a glTexImage2D to discard the mipmap levels + bool needsAlloc = canMipMap && mipMap && !bitmap.hasHardwareMipMap(); + + if (!mId) { + glGenTextures(1, &mId); + needsAlloc = true; + } + + GLint format, type; + colorTypeToGlFormatAndType(bitmap.colorType(), &format, &type); + + if (updateSize(bitmap.width(), bitmap.height(), format)) { + needsAlloc = true; + } + + blend = !bitmap.isOpaque(); + mCaches.textureState().bindTexture(mId); + + if (CC_UNLIKELY(bitmap.colorType() == kARGB_4444_SkColorType + || bitmap.colorType() == kIndex_8_SkColorType)) { + SkBitmap rgbaBitmap; + rgbaBitmap.allocPixels(SkImageInfo::MakeN32(mWidth, mHeight, + bitmap.alphaType())); + rgbaBitmap.eraseColor(0); + + SkCanvas canvas(rgbaBitmap); + canvas.drawBitmap(bitmap, 0.0f, 0.0f, nullptr); + + uploadSkBitmapToTexture(rgbaBitmap, needsAlloc, format, type); + } else { + uploadSkBitmapToTexture(bitmap, needsAlloc, format, type); + } + + if (canMipMap) { + mipMap = bitmap.hasHardwareMipMap(); + if (mipMap) { + glGenerateMipmap(GL_TEXTURE_2D); + } + } + + if (mFirstFilter) { + setFilter(GL_NEAREST); + } + + if (mFirstWrap) { + setWrap(GL_CLAMP_TO_EDGE); + } +} + +void Texture::wrap(GLuint id, uint32_t width, uint32_t height, GLint format) { + mId = id; + mWidth = width; + mHeight = height; + mFormat = format; + // We're wrapping an existing texture, so don't double count this memory + notifySizeChanged(0); } }; // namespace uirenderer diff --git a/libs/hwui/Texture.h b/libs/hwui/Texture.h index 1c544b929e64..4e8e6dcf1a77 100644 --- a/libs/hwui/Texture.h +++ b/libs/hwui/Texture.h @@ -17,20 +17,27 @@ #ifndef ANDROID_HWUI_TEXTURE_H #define ANDROID_HWUI_TEXTURE_H +#include "GpuMemoryTracker.h" + #include +#include namespace android { namespace uirenderer { class Caches; class UvMapper; +class Layer; /** * Represents an OpenGL texture. */ -class Texture { +class Texture : public GpuMemoryTracker { public: - Texture(Caches& caches) : mCaches(caches) { } + Texture(Caches& caches) + : GpuMemoryTracker(GpuObjectType::Texture) + , mCaches(caches) + { } virtual ~Texture() { } @@ -53,28 +60,63 @@ public: /** * Convenience method to call glDeleteTextures() on this texture's id. */ - void deleteTexture() const; + void deleteTexture(); /** - * Name of the texture. + * Sets the width, height, and format of the texture along with allocating + * the texture ID. Does nothing if the width, height, and format are already + * the requested values. + * + * The image data is undefined after calling this. */ - GLuint id = 0; + void resize(uint32_t width, uint32_t height, GLint format) { + upload(format, width, height, format, GL_UNSIGNED_BYTE, nullptr); + } + /** - * Generation of the backing bitmap, + * Updates this Texture with the contents of the provided SkBitmap, + * also setting the appropriate width, height, and format. It is not necessary + * to call resize() prior to this. + * + * Note this does not set the generation from the SkBitmap. */ - uint32_t generation = 0; + void upload(const SkBitmap& source); + /** - * Indicates whether the texture requires blending. + * Basically glTexImage2D/glTexSubImage2D. */ - bool blend = false; + void upload(GLint internalformat, uint32_t width, uint32_t height, + GLenum format, GLenum type, const void* pixels); + /** - * Width of the backing bitmap. + * Wraps an existing texture. */ - uint32_t width = 0; + void wrap(GLuint id, uint32_t width, uint32_t height, GLint format); + + GLuint id() const { + return mId; + } + + uint32_t width() const { + return mWidth; + } + + uint32_t height() const { + return mHeight; + } + + GLint format() const { + return mFormat; + } + /** - * Height of the backing bitmap. + * Generation of the backing bitmap, */ - uint32_t height = 0; + uint32_t generation = 0; + /** + * Indicates whether the texture requires blending. + */ + bool blend = false; /** * Indicates whether this texture should be cleaned up after use. */ @@ -100,6 +142,19 @@ public: void* isInUse = nullptr; private: + // TODO: Temporarily grant private access to Layer, remove once + // Layer can be de-tangled from being a dual-purpose render target + // and external texture wrapper + friend class Layer; + + // Returns true if the size changed, false if it was the same + bool updateSize(uint32_t width, uint32_t height, GLint format); + + GLuint mId = 0; + uint32_t mWidth = 0; + uint32_t mHeight = 0; + GLint mFormat = 0; + /** * Last wrap modes set on this texture. */ @@ -120,7 +175,7 @@ private: class AutoTexture { public: - AutoTexture(const Texture* texture) + AutoTexture(Texture* texture) : texture(texture) {} ~AutoTexture() { if (texture && texture->cleanup) { @@ -129,7 +184,7 @@ public: } } - const Texture *const texture; + Texture* const texture; }; // class AutoTexture }; // namespace uirenderer diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index 21901cf4414b..31bfa3a1ada4 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -166,7 +166,8 @@ Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap, AtlasUsageType a if (canCache) { texture = new Texture(Caches::getInstance()); texture->bitmapSize = size; - Caches::getInstance().textureState().generateTexture(bitmap, texture, false); + texture->generation = bitmap->getGenerationID(); + texture->upload(*bitmap); mSize += size; TEXTURE_LOGD("TextureCache::get: create texture(%p): name, size, mSize = %d, %d, %d", @@ -179,7 +180,8 @@ Texture* TextureCache::getCachedTexture(const SkBitmap* bitmap, AtlasUsageType a } else if (!texture->isInUse && bitmap->getGenerationID() != texture->generation) { // Texture was in the cache but is dirty, re-upload // TODO: Re-adjust the cache size if the bitmap's dimensions have changed - Caches::getInstance().textureState().generateTexture(bitmap, texture, true); + texture->upload(*bitmap); + texture->generation = bitmap->getGenerationID(); } return texture; @@ -204,7 +206,8 @@ Texture* TextureCache::get(const SkBitmap* bitmap, AtlasUsageType atlasUsageType const uint32_t size = bitmap->rowBytes() * bitmap->height(); texture = new Texture(Caches::getInstance()); texture->bitmapSize = size; - Caches::getInstance().textureState().generateTexture(bitmap, texture, false); + texture->upload(*bitmap); + texture->generation = bitmap->getGenerationID(); texture->cleanup = true; } diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index 191c8a81fec6..463450c81714 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -25,6 +25,7 @@ #include "Debug.h" #include +#include namespace android { namespace uirenderer { diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp index d2685daa1711..8ba4761c1b2e 100644 --- a/libs/hwui/font/CacheTexture.cpp +++ b/libs/hwui/font/CacheTexture.cpp @@ -111,11 +111,11 @@ CacheBlock* CacheBlock::removeBlock(CacheBlock* head, CacheBlock* blockToRemove) CacheTexture::CacheTexture(uint16_t width, uint16_t height, GLenum format, uint32_t maxQuadCount) : mTexture(Caches::getInstance()) + , mWidth(width) + , mHeight(height) , mFormat(format) , mMaxQuadCount(maxQuadCount) , mCaches(Caches::getInstance()) { - mTexture.width = width; - mTexture.height = height; mTexture.blend = true; mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, @@ -160,10 +160,7 @@ void CacheTexture::releasePixelBuffer() { delete mPixelBuffer; mPixelBuffer = nullptr; } - if (mTexture.id) { - mCaches.textureState().deleteTexture(mTexture.id); - mTexture.id = 0; - } + mTexture.deleteTexture(); mDirty = false; mCurrentQuad = 0; } @@ -183,22 +180,9 @@ void CacheTexture::allocatePixelBuffer() { mPixelBuffer = PixelBuffer::create(mFormat, getWidth(), getHeight()); } - if (!mTexture.id) { - glGenTextures(1, &mTexture.id); - - mCaches.textureState().bindTexture(mTexture.id); - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - // Initialize texture dimensions - glTexImage2D(GL_TEXTURE_2D, 0, mFormat, getWidth(), getHeight(), 0, - mFormat, GL_UNSIGNED_BYTE, nullptr); - - const GLenum filtering = getLinearFiltering() ? GL_LINEAR : GL_NEAREST; - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering); - - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - } + mTexture.resize(mWidth, mHeight, mFormat); + mTexture.setFilter(getLinearFiltering() ? GL_LINEAR : GL_NEAREST); + mTexture.setWrap(GL_CLAMP_TO_EDGE); } bool CacheTexture::upload() { diff --git a/libs/hwui/font/CacheTexture.h b/libs/hwui/font/CacheTexture.h index 6dabc768ce6b..5510666eef86 100644 --- a/libs/hwui/font/CacheTexture.h +++ b/libs/hwui/font/CacheTexture.h @@ -92,11 +92,11 @@ public: bool fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY); inline uint16_t getWidth() const { - return mTexture.width; + return mWidth; } inline uint16_t getHeight() const { - return mTexture.height; + return mHeight; } inline GLenum getFormat() const { @@ -122,7 +122,7 @@ public: GLuint getTextureId() { allocatePixelBuffer(); - return mTexture.id; + return mTexture.id(); } inline bool isDirty() const { @@ -183,6 +183,7 @@ private: PixelBuffer* mPixelBuffer = nullptr; Texture mTexture; + uint32_t mWidth, mHeight; GLenum mFormat; bool mLinearFiltering = false; bool mDirty = false; diff --git a/libs/hwui/renderstate/OffscreenBufferPool.cpp b/libs/hwui/renderstate/OffscreenBufferPool.cpp index 227b6409b893..98c94dfab1c5 100644 --- a/libs/hwui/renderstate/OffscreenBufferPool.cpp +++ b/libs/hwui/renderstate/OffscreenBufferPool.cpp @@ -34,29 +34,22 @@ namespace uirenderer { OffscreenBuffer::OffscreenBuffer(RenderState& renderState, Caches& caches, uint32_t viewportWidth, uint32_t viewportHeight) - : renderState(renderState) + : GpuMemoryTracker(GpuObjectType::OffscreenBuffer) + , renderState(renderState) , viewportWidth(viewportWidth) , viewportHeight(viewportHeight) , texture(caches) { - texture.width = computeIdealDimension(viewportWidth); - texture.height = computeIdealDimension(viewportHeight); + uint32_t width = computeIdealDimension(viewportWidth); + uint32_t height = computeIdealDimension(viewportHeight); + texture.resize(width, height, GL_RGBA); texture.blend = true; - - caches.textureState().activateTexture(0); - glGenTextures(1, &texture.id); - caches.textureState().bindTexture(GL_TEXTURE_2D, texture.id); - - texture.setWrap(GL_CLAMP_TO_EDGE, false, false, GL_TEXTURE_2D); + texture.setWrap(GL_CLAMP_TO_EDGE); // not setting filter on texture, since it's set when drawing, based on transform - - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texture.width, texture.height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, nullptr); } Rect OffscreenBuffer::getTextureCoordinates() { - const float texX = 1.0f / float(texture.width); - const float texY = 1.0f / float(texture.height); + const float texX = 1.0f / static_cast(texture.width()); + const float texY = 1.0f / static_cast(texture.height()); return Rect(0, viewportHeight * texY, viewportWidth * texX, 0); } @@ -69,8 +62,8 @@ void OffscreenBuffer::updateMeshFromRegion() { size_t count; const android::Rect* rects = safeRegion.getArray(&count); - const float texX = 1.0f / float(texture.width); - const float texY = 1.0f / float(texture.height); + const float texX = 1.0f / float(texture.width()); + const float texY = 1.0f / float(texture.height()); FatVector meshVector(count * 4); // uses heap if more than 64 vertices needed TextureVertex* mesh = &meshVector[0]; @@ -157,8 +150,8 @@ OffscreenBuffer* OffscreenBufferPool::get(RenderState& renderState, OffscreenBuffer* OffscreenBufferPool::resize(OffscreenBuffer* layer, const uint32_t width, const uint32_t height) { RenderState& renderState = layer->renderState; - if (layer->texture.width == OffscreenBuffer::computeIdealDimension(width) - && layer->texture.height == OffscreenBuffer::computeIdealDimension(height)) { + if (layer->texture.width() == OffscreenBuffer::computeIdealDimension(width) + && layer->texture.height() == OffscreenBuffer::computeIdealDimension(height)) { // resize in place layer->viewportWidth = width; layer->viewportHeight = height; diff --git a/libs/hwui/renderstate/OffscreenBufferPool.h b/libs/hwui/renderstate/OffscreenBufferPool.h index 2d8d5295e1f8..94155efcbb0a 100644 --- a/libs/hwui/renderstate/OffscreenBufferPool.h +++ b/libs/hwui/renderstate/OffscreenBufferPool.h @@ -17,10 +17,10 @@ #ifndef ANDROID_HWUI_OFFSCREEN_BUFFER_POOL_H #define ANDROID_HWUI_OFFSCREEN_BUFFER_POOL_H +#include #include "Caches.h" #include "Texture.h" #include "utils/Macros.h" - #include #include @@ -40,7 +40,7 @@ class RenderState; * viewport bounds, since textures are always allocated with width / height as a multiple of 64, for * the purpose of improving reuse. */ -class OffscreenBuffer { +class OffscreenBuffer : GpuMemoryTracker { public: OffscreenBuffer(RenderState& renderState, Caches& caches, uint32_t viewportWidth, uint32_t viewportHeight); @@ -58,7 +58,7 @@ public: static uint32_t computeIdealDimension(uint32_t dimension); - uint32_t getSizeInBytes() { return texture.width * texture.height * 4; } + uint32_t getSizeInBytes() { return texture.objectSize(); } RenderState& renderState; @@ -124,8 +124,8 @@ private: Entry(OffscreenBuffer* layer) : layer(layer) - , width(layer->texture.width) - , height(layer->texture.height) { + , width(layer->texture.width()) + , height(layer->texture.height()) { } static int compare(const Entry& lhs, const Entry& rhs); diff --git a/libs/hwui/renderstate/RenderState.cpp b/libs/hwui/renderstate/RenderState.cpp index 4fa820058fb2..4a1e8fcfedf2 100644 --- a/libs/hwui/renderstate/RenderState.cpp +++ b/libs/hwui/renderstate/RenderState.cpp @@ -13,12 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +#include #include "renderstate/RenderState.h" #include "renderthread/CanvasContext.h" #include "renderthread/EglManager.h" #include "utils/GLUtils.h" - #include namespace android { @@ -40,6 +40,8 @@ RenderState::~RenderState() { void RenderState::onGLContextCreated() { LOG_ALWAYS_FATAL_IF(mBlend || mMeshState || mScissor || mStencil, "State object lifecycle not managed correctly"); + GpuMemoryTracker::onGLContextCreated(); + mBlend = new Blend(); mMeshState = new MeshState(); mScissor = new Scissor(); @@ -106,6 +108,8 @@ void RenderState::onGLContextDestroyed() { mScissor = nullptr; delete mStencil; mStencil = nullptr; + + GpuMemoryTracker::onGLContextDestroyed(); } void RenderState::flush(Caches::FlushMode mode) { @@ -310,7 +314,7 @@ void RenderState::render(const Glop& glop, const Matrix4& orthoMatrix) { texture.texture->setFilter(texture.filter, true, false, texture.target); } - mCaches->textureState().bindTexture(texture.target, texture.texture->id); + mCaches->textureState().bindTexture(texture.target, texture.texture->id()); meshState().enableTexCoordsVertexArray(); meshState().bindTexCoordsVertexPointer(force, vertices.texCoord, vertices.stride); diff --git a/libs/hwui/renderstate/TextureState.cpp b/libs/hwui/renderstate/TextureState.cpp index 1f50f712c267..26ebdee06c08 100644 --- a/libs/hwui/renderstate/TextureState.cpp +++ b/libs/hwui/renderstate/TextureState.cpp @@ -34,134 +34,6 @@ const GLenum kTextureUnits[] = { GL_TEXTURE3 }; -static void uploadToTexture(bool resize, GLenum format, GLenum type, GLsizei stride, GLsizei bpp, - GLsizei width, GLsizei height, const GLvoid * data) { - - glPixelStorei(GL_UNPACK_ALIGNMENT, bpp); - const bool useStride = stride != width - && Caches::getInstance().extensions().hasUnpackRowLength(); - if ((stride == width) || useStride) { - if (useStride) { - glPixelStorei(GL_UNPACK_ROW_LENGTH, stride); - } - - if (resize) { - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, data); - } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, data); - } - - if (useStride) { - glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); - } - } else { - // With OpenGL ES 2.0 we need to copy the bitmap in a temporary buffer - // if the stride doesn't match the width - - GLvoid * temp = (GLvoid *) malloc(width * height * bpp); - if (!temp) return; - - uint8_t * pDst = (uint8_t *)temp; - uint8_t * pSrc = (uint8_t *)data; - for (GLsizei i = 0; i < height; i++) { - memcpy(pDst, pSrc, width * bpp); - pDst += width * bpp; - pSrc += stride * bpp; - } - - if (resize) { - glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, type, temp); - } else { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, temp); - } - - free(temp); - } -} - -static void uploadSkBitmapToTexture(const SkBitmap& bitmap, - bool resize, GLenum format, GLenum type) { - uploadToTexture(resize, format, type, bitmap.rowBytesAsPixels(), bitmap.bytesPerPixel(), - bitmap.width(), bitmap.height(), bitmap.getPixels()); -} - -void TextureState::generateTexture(const SkBitmap* bitmap, Texture* texture, bool regenerate) { - SkAutoLockPixels alp(*bitmap); - - if (!bitmap->readyToDraw()) { - ALOGE("Cannot generate texture from bitmap"); - return; - } - - ATRACE_FORMAT("Upload %ux%u Texture", bitmap->width(), bitmap->height()); - - // We could also enable mipmapping if both bitmap dimensions are powers - // of 2 but we'd have to deal with size changes. Let's keep this simple - const bool canMipMap = Caches::getInstance().extensions().hasNPot(); - - // If the texture had mipmap enabled but not anymore, - // force a glTexImage2D to discard the mipmap levels - const bool resize = !regenerate || bitmap->width() != int(texture->width) || - bitmap->height() != int(texture->height) || - (regenerate && canMipMap && texture->mipMap && !bitmap->hasHardwareMipMap()); - - if (!regenerate) { - glGenTextures(1, &texture->id); - } - - texture->generation = bitmap->getGenerationID(); - texture->width = bitmap->width(); - texture->height = bitmap->height(); - - bindTexture(texture->id); - - switch (bitmap->colorType()) { - case kAlpha_8_SkColorType: - uploadSkBitmapToTexture(*bitmap, resize, GL_ALPHA, GL_UNSIGNED_BYTE); - texture->blend = true; - break; - case kRGB_565_SkColorType: - uploadSkBitmapToTexture(*bitmap, resize, GL_RGB, GL_UNSIGNED_SHORT_5_6_5); - texture->blend = false; - break; - case kN32_SkColorType: - uploadSkBitmapToTexture(*bitmap, resize, GL_RGBA, GL_UNSIGNED_BYTE); - // Do this after calling getPixels() to make sure Skia's deferred - // decoding happened - texture->blend = !bitmap->isOpaque(); - break; - case kARGB_4444_SkColorType: - case kIndex_8_SkColorType: { - SkBitmap rgbaBitmap; - rgbaBitmap.allocPixels(SkImageInfo::MakeN32(texture->width, texture->height, - bitmap->alphaType())); - rgbaBitmap.eraseColor(0); - - SkCanvas canvas(rgbaBitmap); - canvas.drawBitmap(*bitmap, 0.0f, 0.0f, nullptr); - - uploadSkBitmapToTexture(rgbaBitmap, resize, GL_RGBA, GL_UNSIGNED_BYTE); - texture->blend = !bitmap->isOpaque(); - break; - } - default: - ALOGW("Unsupported bitmap colorType: %d", bitmap->colorType()); - break; - } - - if (canMipMap) { - texture->mipMap = bitmap->hasHardwareMipMap(); - if (texture->mipMap) { - glGenerateMipmap(GL_TEXTURE_2D); - } - } - - if (!regenerate) { - texture->setFilter(GL_NEAREST); - texture->setWrap(GL_CLAMP_TO_EDGE); - } -} - TextureState::TextureState() : mTextureUnit(0) { glActiveTexture(kTextureUnits[0]); diff --git a/libs/hwui/renderstate/TextureState.h b/libs/hwui/renderstate/TextureState.h index 3a2b85ae2886..ec94d7e9e267 100644 --- a/libs/hwui/renderstate/TextureState.h +++ b/libs/hwui/renderstate/TextureState.h @@ -76,13 +76,6 @@ public: */ void unbindTexture(GLuint texture); - /** - * Generates the texture from a bitmap into the specified texture structure. - * - * @param regenerate If true, the bitmap data is reuploaded into the texture, but - * no new texture is generated. - */ - void generateTexture(const SkBitmap* bitmap, Texture* texture, bool regenerate); private: // total number of texture units available for use static const int kTextureUnitsCount = 4; diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 644f3565216b..968135b4fd6c 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include "CanvasContext.h" #include "AnimationContext.h" @@ -497,6 +498,8 @@ void CanvasContext::draw() { mJankTracker.addFrame(*mCurrentFrameInfo); mRenderThread.jankTracker().addFrame(*mCurrentFrameInfo); + + GpuMemoryTracker::onFrameCompleted(); } // Called by choreographer to do an RT-driven animation diff --git a/libs/hwui/tests/common/TestUtils.h b/libs/hwui/tests/common/TestUtils.h index edde31e502e0..42cd0ced0cac 100644 --- a/libs/hwui/tests/common/TestUtils.h +++ b/libs/hwui/tests/common/TestUtils.h @@ -197,6 +197,10 @@ public: renderthread::RenderThread::getInstance().queueAndWait(&task); } + static bool isRenderThreadRunning() { + return renderthread::RenderThread::hasInstance(); + } + static SkColor interpolateColor(float fraction, SkColor start, SkColor end); static void drawTextToCanvas(TestCanvas* canvas, const char* text, diff --git a/libs/hwui/tests/macrobench/main.cpp b/libs/hwui/tests/macrobench/main.cpp index 1616a95857d8..02a39501e647 100644 --- a/libs/hwui/tests/macrobench/main.cpp +++ b/libs/hwui/tests/macrobench/main.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include diff --git a/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp b/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp new file mode 100644 index 000000000000..aa1dcb2ea51b --- /dev/null +++ b/libs/hwui/tests/unit/GpuMemoryTrackerTests.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +#include +#include + +#include "renderthread/EglManager.h" +#include "renderthread/RenderThread.h" +#include "tests/common/TestUtils.h" + +#include + +using namespace android; +using namespace android::uirenderer; +using namespace android::uirenderer::renderthread; + +class TestGPUObject : public GpuMemoryTracker { +public: + TestGPUObject() : GpuMemoryTracker(GpuObjectType::Texture) {} + + void changeSize(int newSize) { + notifySizeChanged(newSize); + } +}; + +// Other tests may have created a renderthread and EGL context. +// This will destroy the EGLContext on RenderThread if it exists so that the +// current thread can spoof being a GPU thread +static void destroyEglContext() { + if (TestUtils::isRenderThreadRunning()) { + TestUtils::runOnRenderThread([](RenderThread& thread) { + thread.eglManager().destroy(); + }); + } +} + +TEST(GpuMemoryTracker, sizeCheck) { + destroyEglContext(); + + GpuMemoryTracker::onGLContextCreated(); + ASSERT_EQ(0, GpuMemoryTracker::getTotalSize(GpuObjectType::Texture)); + ASSERT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::Texture)); + { + TestGPUObject myObj; + ASSERT_EQ(1, GpuMemoryTracker::getInstanceCount(GpuObjectType::Texture)); + myObj.changeSize(500); + ASSERT_EQ(500, GpuMemoryTracker::getTotalSize(GpuObjectType::Texture)); + myObj.changeSize(1000); + ASSERT_EQ(1000, GpuMemoryTracker::getTotalSize(GpuObjectType::Texture)); + myObj.changeSize(300); + ASSERT_EQ(300, GpuMemoryTracker::getTotalSize(GpuObjectType::Texture)); + } + ASSERT_EQ(0, GpuMemoryTracker::getTotalSize(GpuObjectType::Texture)); + ASSERT_EQ(0, GpuMemoryTracker::getInstanceCount(GpuObjectType::Texture)); + GpuMemoryTracker::onGLContextDestroyed(); +} diff --git a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp index e96e9ba55361..5278730a3c9e 100644 --- a/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp +++ b/libs/hwui/tests/unit/OffscreenBufferPoolTests.cpp @@ -36,8 +36,8 @@ TEST(OffscreenBuffer, construct) { EXPECT_EQ(49u, layer.viewportWidth); EXPECT_EQ(149u, layer.viewportHeight); - EXPECT_EQ(64u, layer.texture.width); - EXPECT_EQ(192u, layer.texture.height); + EXPECT_EQ(64u, layer.texture.width()); + EXPECT_EQ(192u, layer.texture.height()); EXPECT_EQ(64u * 192u * 4u, layer.getSizeInBytes()); }); @@ -100,8 +100,8 @@ TEST(OffscreenBufferPool, resize) { ASSERT_EQ(layer, pool.resize(layer, 60u, 55u)); EXPECT_EQ(60u, layer->viewportWidth); EXPECT_EQ(55u, layer->viewportHeight); - EXPECT_EQ(64u, layer->texture.width); - EXPECT_EQ(64u, layer->texture.height); + EXPECT_EQ(64u, layer->texture.width()); + EXPECT_EQ(64u, layer->texture.height()); // resized to use different object in pool auto layer2 = pool.get(thread.renderState(), 128u, 128u); @@ -110,8 +110,8 @@ TEST(OffscreenBufferPool, resize) { ASSERT_EQ(layer2, pool.resize(layer, 120u, 125u)); EXPECT_EQ(120u, layer2->viewportWidth); EXPECT_EQ(125u, layer2->viewportHeight); - EXPECT_EQ(128u, layer2->texture.width); - EXPECT_EQ(128u, layer2->texture.height); + EXPECT_EQ(128u, layer2->texture.width()); + EXPECT_EQ(128u, layer2->texture.height()); // original allocation now only thing in pool EXPECT_EQ(1u, pool.getCount()); diff --git a/libs/hwui/tests/unit/StringUtilsTests.cpp b/libs/hwui/tests/unit/StringUtilsTests.cpp index 6b2e265a61ff..b60e96c756ec 100644 --- a/libs/hwui/tests/unit/StringUtilsTests.cpp +++ b/libs/hwui/tests/unit/StringUtilsTests.cpp @@ -36,3 +36,18 @@ TEST(StringUtils, advancedBuildSet) { EXPECT_TRUE(collection.has("GL_ext1")); EXPECT_FALSE(collection.has("GL_ext")); // string present, but not in list } + +TEST(StringUtils, sizePrinter) { + std::stringstream os; + os << SizePrinter{500}; + EXPECT_EQ("500.00B", os.str()); + os.str(""); + os << SizePrinter{46080}; + EXPECT_EQ("45.00KiB", os.str()); + os.str(""); + os << SizePrinter{5 * 1024 * 1024 + 520 * 1024}; + EXPECT_EQ("5.51MiB", os.str()); + os.str(""); + os << SizePrinter{2147483647}; + EXPECT_EQ("2048.00MiB", os.str()); +} diff --git a/libs/hwui/utils/StringUtils.h b/libs/hwui/utils/StringUtils.h index 055869f73c26..05a3d5931e5d 100644 --- a/libs/hwui/utils/StringUtils.h +++ b/libs/hwui/utils/StringUtils.h @@ -18,6 +18,8 @@ #include #include +#include +#include namespace android { namespace uirenderer { @@ -34,6 +36,21 @@ public: static unordered_string_set split(const char* spacedList); }; +struct SizePrinter { + int bytes; + friend std::ostream& operator<<(std::ostream& stream, const SizePrinter& d) { + static const char* SUFFIXES[] = {"B", "KiB", "MiB"}; + size_t suffix = 0; + double temp = d.bytes; + while (temp > 1000 && suffix < 2) { + temp /= 1024.0; + suffix++; + } + stream << std::fixed << std::setprecision(2) << temp << SUFFIXES[suffix]; + return stream; + } +}; + } /* namespace uirenderer */ } /* namespace android */ -- cgit v1.2.3-59-g8ed1b From 48a8f431fa52ae2ee25ffba9d20676f03bb710ff Mon Sep 17 00:00:00 2001 From: Chris Craik Date: Fri, 5 Feb 2016 15:59:29 -0800 Subject: Move several property queries to Properties class bug:17478770 This removes a lot of redundant property query code, and puts the queries all in one place, so defining them automatically will be simpler in the future. Change-Id: I0428550e6081f07bc6554ffdf73b22284325abb8 --- libs/hwui/FboCache.cpp | 11 ++--------- libs/hwui/GradientCache.cpp | 17 +---------------- libs/hwui/GradientCache.h | 6 +----- libs/hwui/PatchCache.cpp | 12 ++---------- libs/hwui/PatchCache.h | 2 +- libs/hwui/PathCache.cpp | 15 ++++----------- libs/hwui/PathCache.h | 2 +- libs/hwui/Properties.cpp | 25 +++++++++++++++++++++++-- libs/hwui/Properties.h | 9 +++++++++ libs/hwui/RenderBufferCache.cpp | 18 +++--------------- libs/hwui/RenderBufferCache.h | 4 ---- libs/hwui/TessellationCache.cpp | 18 +----------------- libs/hwui/TessellationCache.h | 8 +------- libs/hwui/TextDropShadowCache.cpp | 38 ++++++++------------------------------ libs/hwui/TextDropShadowCache.h | 10 ++-------- libs/hwui/TextureCache.cpp | 32 ++------------------------------ libs/hwui/TextureCache.h | 13 ++----------- 17 files changed, 63 insertions(+), 177 deletions(-) (limited to 'libs/hwui/PathCache.cpp') diff --git a/libs/hwui/FboCache.cpp b/libs/hwui/FboCache.cpp index cca3cb7a98f1..b2181b60054f 100644 --- a/libs/hwui/FboCache.cpp +++ b/libs/hwui/FboCache.cpp @@ -27,15 +27,8 @@ namespace uirenderer { // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// -FboCache::FboCache(): mMaxSize(DEFAULT_FBO_CACHE_SIZE) { - char property[PROPERTY_VALUE_MAX]; - if (property_get(PROPERTY_FBO_CACHE_SIZE, property, nullptr) > 0) { - INIT_LOGD(" Setting fbo cache size to %s", property); - mMaxSize = atoi(property); - } else { - INIT_LOGD(" Using default fbo cache size of %d", DEFAULT_FBO_CACHE_SIZE); - } -} +FboCache::FboCache() + : mMaxSize(Properties::fboCacheSize) {} FboCache::~FboCache() { clear(); diff --git a/libs/hwui/GradientCache.cpp b/libs/hwui/GradientCache.cpp index e899ac71ff36..044c7cb65718 100644 --- a/libs/hwui/GradientCache.cpp +++ b/libs/hwui/GradientCache.cpp @@ -65,17 +65,9 @@ int GradientCacheEntry::compare(const GradientCacheEntry& lhs, const GradientCac GradientCache::GradientCache(Extensions& extensions) : mCache(LruCache::kUnlimitedCapacity) , mSize(0) - , mMaxSize(MB(DEFAULT_GRADIENT_CACHE_SIZE)) + , mMaxSize(Properties::gradientCacheSize) , mUseFloatTexture(extensions.hasFloatTextures()) , mHasNpot(extensions.hasNPot()){ - char property[PROPERTY_VALUE_MAX]; - if (property_get(PROPERTY_GRADIENT_CACHE_SIZE, property, nullptr) > 0) { - INIT_LOGD(" Setting gradient cache size to %sMB", property); - setMaxSize(MB(atof(property))); - } else { - INIT_LOGD(" Using default gradient cache size of %.2fMB", DEFAULT_GRADIENT_CACHE_SIZE); - } - glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); mCache.setOnEntryRemovedListener(this); @@ -97,13 +89,6 @@ uint32_t GradientCache::getMaxSize() { return mMaxSize; } -void GradientCache::setMaxSize(uint32_t maxSize) { - mMaxSize = maxSize; - while (mSize > mMaxSize) { - mCache.removeOldest(); - } -} - /////////////////////////////////////////////////////////////////////////////// // Callbacks /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/GradientCache.h b/libs/hwui/GradientCache.h index b762ca7d5e5c..dccd45072522 100644 --- a/libs/hwui/GradientCache.h +++ b/libs/hwui/GradientCache.h @@ -122,10 +122,6 @@ public: */ void clear(); - /** - * Sets the maximum size of the cache in bytes. - */ - void setMaxSize(uint32_t maxSize); /** * Returns the maximum size of the cache in bytes. */ @@ -177,7 +173,7 @@ private: LruCache mCache; uint32_t mSize; - uint32_t mMaxSize; + const uint32_t mMaxSize; GLint mMaxTextureSize; bool mUseFloatTexture; diff --git a/libs/hwui/PatchCache.cpp b/libs/hwui/PatchCache.cpp index 98812805259e..bd6feb9fc762 100644 --- a/libs/hwui/PatchCache.cpp +++ b/libs/hwui/PatchCache.cpp @@ -32,20 +32,12 @@ namespace uirenderer { PatchCache::PatchCache(RenderState& renderState) : mRenderState(renderState) + , mMaxSize(Properties::patchCacheSize) , mSize(0) , mCache(LruCache::kUnlimitedCapacity) , mMeshBuffer(0) , mFreeBlocks(nullptr) - , mGenerationId(0) { - char property[PROPERTY_VALUE_MAX]; - if (property_get(PROPERTY_PATCH_CACHE_SIZE, property, nullptr) > 0) { - INIT_LOGD(" Setting patch cache size to %skB", property); - mMaxSize = KB(atoi(property)); - } else { - INIT_LOGD(" Using default patch cache size of %.2fkB", DEFAULT_PATCH_CACHE_SIZE); - mMaxSize = KB(DEFAULT_PATCH_CACHE_SIZE); - } -} + , mGenerationId(0) {} PatchCache::~PatchCache() { clear(); diff --git a/libs/hwui/PatchCache.h b/libs/hwui/PatchCache.h index 387f79acf0ec..66ef6a0279ba 100644 --- a/libs/hwui/PatchCache.h +++ b/libs/hwui/PatchCache.h @@ -169,7 +169,7 @@ private: #endif RenderState& mRenderState; - uint32_t mMaxSize; + const uint32_t mMaxSize; uint32_t mSize; LruCache mCache; diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index bfabc1d4d94c..8f914acc5c76 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -135,17 +135,10 @@ static void drawPath(const SkPath *path, const SkPaint* paint, SkBitmap& bitmap, // Cache constructor/destructor /////////////////////////////////////////////////////////////////////////////// -PathCache::PathCache(): - mCache(LruCache::kUnlimitedCapacity), - mSize(0), mMaxSize(MB(DEFAULT_PATH_CACHE_SIZE)) { - char property[PROPERTY_VALUE_MAX]; - if (property_get(PROPERTY_PATH_CACHE_SIZE, property, nullptr) > 0) { - INIT_LOGD(" Setting path cache size to %sMB", property); - mMaxSize = MB(atof(property)); - } else { - INIT_LOGD(" Using default path cache size of %.2fMB", DEFAULT_PATH_CACHE_SIZE); - } - +PathCache::PathCache() + : mCache(LruCache::kUnlimitedCapacity) + , mSize(0) + , mMaxSize(Properties::pathCacheSize) { mCache.setOnEntryRemovedListener(this); GLint maxTextureSize; diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h index 18f380fe3f7a..d2633aa427c5 100644 --- a/libs/hwui/PathCache.h +++ b/libs/hwui/PathCache.h @@ -300,7 +300,7 @@ private: LruCache mCache; uint32_t mSize; - uint32_t mMaxSize; + const uint32_t mMaxSize; GLuint mMaxTextureSize; bool mDebugEnabled; diff --git a/libs/hwui/Properties.cpp b/libs/hwui/Properties.cpp index 083aeb7ed585..bbd8c7226ab2 100644 --- a/libs/hwui/Properties.cpp +++ b/libs/hwui/Properties.cpp @@ -37,7 +37,18 @@ bool Properties::useBufferAge = true; bool Properties::enablePartialUpdates = true; float Properties::textGamma = DEFAULT_TEXT_GAMMA; -int Properties::layerPoolSize = DEFAULT_LAYER_CACHE_SIZE; + +int Properties::fboCacheSize = DEFAULT_FBO_CACHE_SIZE; +int Properties::gradientCacheSize = MB(DEFAULT_GRADIENT_CACHE_SIZE); +int Properties::layerPoolSize = MB(DEFAULT_LAYER_CACHE_SIZE); +int Properties::patchCacheSize = KB(DEFAULT_PATCH_CACHE_SIZE); +int Properties::pathCacheSize = MB(DEFAULT_PATH_CACHE_SIZE); +int Properties::renderBufferCacheSize = MB(DEFAULT_RENDER_BUFFER_CACHE_SIZE); +int Properties::tessellationCacheSize = MB(DEFAULT_VERTEX_CACHE_SIZE); +int Properties::textDropShadowCacheSize = MB(DEFAULT_DROP_SHADOW_CACHE_SIZE); +int Properties::textureCacheSize = MB(DEFAULT_TEXTURE_CACHE_SIZE); + +float Properties::textureCacheFlushRate = DEFAULT_TEXTURE_CACHE_FLUSH_RATE; DebugLevel Properties::debugLevel = kDebugDisabled; OverdrawColorSet Properties::overdrawColorSet = OverdrawColorSet::Default; @@ -79,7 +90,6 @@ bool Properties::load() { bool prevDebugOverdraw = debugOverdraw; StencilClipDebug prevDebugStencilClip = debugStencilClip; - debugOverdraw = false; if (property_get(PROPERTY_DEBUG_OVERDRAW, property, nullptr) > 0) { INIT_LOGD(" Overdraw debug enabled: %s", property); @@ -133,7 +143,18 @@ bool Properties::load() { enablePartialUpdates = property_get_bool(PROPERTY_ENABLE_PARTIAL_UPDATES, true); textGamma = property_get_float(PROPERTY_TEXT_GAMMA, DEFAULT_TEXT_GAMMA); + + fboCacheSize = property_get_int(PROPERTY_FBO_CACHE_SIZE, DEFAULT_FBO_CACHE_SIZE); + gradientCacheSize = MB(property_get_float(PROPERTY_GRADIENT_CACHE_SIZE, DEFAULT_GRADIENT_CACHE_SIZE)); layerPoolSize = MB(property_get_float(PROPERTY_LAYER_CACHE_SIZE, DEFAULT_LAYER_CACHE_SIZE)); + patchCacheSize = KB(property_get_float(PROPERTY_PATCH_CACHE_SIZE, DEFAULT_PATCH_CACHE_SIZE)); + pathCacheSize = MB(property_get_float(PROPERTY_PATH_CACHE_SIZE, DEFAULT_PATH_CACHE_SIZE)); + renderBufferCacheSize = MB(property_get_float(PROPERTY_RENDER_BUFFER_CACHE_SIZE, DEFAULT_RENDER_BUFFER_CACHE_SIZE)); + tessellationCacheSize = MB(property_get_float(PROPERTY_VERTEX_CACHE_SIZE, DEFAULT_VERTEX_CACHE_SIZE)); + textDropShadowCacheSize = MB(property_get_float(PROPERTY_DROP_SHADOW_CACHE_SIZE, DEFAULT_DROP_SHADOW_CACHE_SIZE)); + textureCacheSize = MB(property_get_float(PROPERTY_TEXTURE_CACHE_SIZE, DEFAULT_TEXTURE_CACHE_SIZE)); + textureCacheFlushRate = std::max(0.0f, std::min(1.0f, + property_get_float(PROPERTY_TEXTURE_CACHE_FLUSH_RATE, DEFAULT_TEXTURE_CACHE_FLUSH_RATE))); return (prevDebugLayersUpdates != debugLayersUpdates) || (prevDebugOverdraw != debugOverdraw) diff --git a/libs/hwui/Properties.h b/libs/hwui/Properties.h index 88f1dbc98926..3e111516ac63 100644 --- a/libs/hwui/Properties.h +++ b/libs/hwui/Properties.h @@ -267,7 +267,16 @@ public: static float textGamma; + static int fboCacheSize; + static int gradientCacheSize; static int layerPoolSize; + static int patchCacheSize; + static int pathCacheSize; + static int renderBufferCacheSize; + static int tessellationCacheSize; + static int textDropShadowCacheSize; + static int textureCacheSize; + static float textureCacheFlushRate; static DebugLevel debugLevel; static OverdrawColorSet overdrawColorSet; diff --git a/libs/hwui/RenderBufferCache.cpp b/libs/hwui/RenderBufferCache.cpp index 11d7a6af3a6a..1ac57cdbac0c 100644 --- a/libs/hwui/RenderBufferCache.cpp +++ b/libs/hwui/RenderBufferCache.cpp @@ -40,16 +40,9 @@ namespace uirenderer { // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// -RenderBufferCache::RenderBufferCache(): mSize(0), mMaxSize(MB(DEFAULT_RENDER_BUFFER_CACHE_SIZE)) { - char property[PROPERTY_VALUE_MAX]; - if (property_get(PROPERTY_RENDER_BUFFER_CACHE_SIZE, property, nullptr) > 0) { - INIT_LOGD(" Setting render buffer cache size to %sMB", property); - setMaxSize(MB(atof(property))); - } else { - INIT_LOGD(" Using default render buffer cache size of %.2fMB", - DEFAULT_RENDER_BUFFER_CACHE_SIZE); - } -} +RenderBufferCache::RenderBufferCache() + : mSize(0) + , mMaxSize(Properties::renderBufferCacheSize) {} RenderBufferCache::~RenderBufferCache() { clear(); @@ -67,11 +60,6 @@ uint32_t RenderBufferCache::getMaxSize() { return mMaxSize; } -void RenderBufferCache::setMaxSize(uint32_t maxSize) { - clear(); - mMaxSize = maxSize; -} - /////////////////////////////////////////////////////////////////////////////// // Caching /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/RenderBufferCache.h b/libs/hwui/RenderBufferCache.h index 7f59ec1c48b1..f77f4c95b5ba 100644 --- a/libs/hwui/RenderBufferCache.h +++ b/libs/hwui/RenderBufferCache.h @@ -63,10 +63,6 @@ public: */ void clear(); - /** - * Sets the maximum size of the cache in bytes. - */ - void setMaxSize(uint32_t maxSize); /** * Returns the maximum size of the cache in bytes. */ diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp index fd9fb852171c..14c8f3926e31 100644 --- a/libs/hwui/TessellationCache.cpp +++ b/libs/hwui/TessellationCache.cpp @@ -265,18 +265,9 @@ public: /////////////////////////////////////////////////////////////////////////////// TessellationCache::TessellationCache() - : mSize(0) - , mMaxSize(MB(DEFAULT_VERTEX_CACHE_SIZE)) + : mMaxSize(Properties::tessellationCacheSize) , mCache(LruCache::kUnlimitedCapacity) , mShadowCache(LruCache*>::kUnlimitedCapacity) { - char property[PROPERTY_VALUE_MAX]; - if (property_get(PROPERTY_VERTEX_CACHE_SIZE, property, nullptr) > 0) { - INIT_LOGD(" Setting tessellation cache size to %sMB", property); - setMaxSize(MB(atof(property))); - } else { - INIT_LOGD(" Using default tessellation cache size of %.2fMB", DEFAULT_VERTEX_CACHE_SIZE); - } - mCache.setOnEntryRemovedListener(&mBufferRemovedListener); mShadowCache.setOnEntryRemovedListener(&mBufferPairRemovedListener); mDebugEnabled = Properties::debugLevel & kDebugCaches; @@ -303,13 +294,6 @@ uint32_t TessellationCache::getMaxSize() { return mMaxSize; } -void TessellationCache::setMaxSize(uint32_t maxSize) { - mMaxSize = maxSize; - while (mSize > mMaxSize) { - mCache.removeOldest(); - } -} - /////////////////////////////////////////////////////////////////////////////// // Caching /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h index 6dcc8120cf48..0bd6365db60f 100644 --- a/libs/hwui/TessellationCache.h +++ b/libs/hwui/TessellationCache.h @@ -131,11 +131,6 @@ public: * Clears the cache. This causes all TessellationBuffers to be deleted. */ void clear(); - - /** - * Sets the maximum size of the cache in bytes. - */ - void setMaxSize(uint32_t maxSize); /** * Returns the maximum size of the cache in bytes. */ @@ -198,8 +193,7 @@ private: Buffer* getOrCreateBuffer(const Description& entry, Tessellator tessellator); - uint32_t mSize; - uint32_t mMaxSize; + const uint32_t mMaxSize; bool mDebugEnabled; diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp index 1707468f169d..fe4b3d7507b2 100644 --- a/libs/hwui/TextDropShadowCache.cpp +++ b/libs/hwui/TextDropShadowCache.cpp @@ -93,36 +93,21 @@ int ShadowText::compare(const ShadowText& lhs, const ShadowText& rhs) { // Constructors/destructor /////////////////////////////////////////////////////////////////////////////// -TextDropShadowCache::TextDropShadowCache(): - mCache(LruCache::kUnlimitedCapacity), - mSize(0), mMaxSize(MB(DEFAULT_DROP_SHADOW_CACHE_SIZE)) { - char property[PROPERTY_VALUE_MAX]; - if (property_get(PROPERTY_DROP_SHADOW_CACHE_SIZE, property, nullptr) > 0) { - INIT_LOGD(" Setting drop shadow cache size to %sMB", property); - setMaxSize(MB(atof(property))); - } else { - INIT_LOGD(" Using default drop shadow cache size of %.2fMB", - DEFAULT_DROP_SHADOW_CACHE_SIZE); - } - - init(); -} +TextDropShadowCache::TextDropShadowCache() + : TextDropShadowCache(Properties::textDropShadowCacheSize) {} -TextDropShadowCache::TextDropShadowCache(uint32_t maxByteSize): - mCache(LruCache::kUnlimitedCapacity), - mSize(0), mMaxSize(maxByteSize) { - init(); +TextDropShadowCache::TextDropShadowCache(uint32_t maxByteSize) + : mCache(LruCache::kUnlimitedCapacity) + , mSize(0) + , mMaxSize(maxByteSize) { + mCache.setOnEntryRemovedListener(this); + mDebugEnabled = Properties::debugLevel & kDebugMoreCaches; } TextDropShadowCache::~TextDropShadowCache() { mCache.clear(); } -void TextDropShadowCache::init() { - mCache.setOnEntryRemovedListener(this); - mDebugEnabled = Properties::debugLevel & kDebugMoreCaches; -} - /////////////////////////////////////////////////////////////////////////////// // Size management /////////////////////////////////////////////////////////////////////////////// @@ -135,13 +120,6 @@ uint32_t TextDropShadowCache::getMaxSize() { return mMaxSize; } -void TextDropShadowCache::setMaxSize(uint32_t maxSize) { - mMaxSize = maxSize; - while (mSize > mMaxSize) { - mCache.removeOldest(); - } -} - /////////////////////////////////////////////////////////////////////////////// // Callbacks /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h index c4f3c5d96786..cf647882e5a7 100644 --- a/libs/hwui/TextDropShadowCache.h +++ b/libs/hwui/TextDropShadowCache.h @@ -147,10 +147,6 @@ public: mRenderer = &fontRenderer; } - /** - * Sets the maximum size of the cache in bytes. - */ - void setMaxSize(uint32_t maxSize); /** * Returns the maximum size of the cache in bytes. */ @@ -161,13 +157,11 @@ public: uint32_t getSize(); private: - void init(); - LruCache mCache; uint32_t mSize; - uint32_t mMaxSize; - FontRenderer* mRenderer; + const uint32_t mMaxSize; + FontRenderer* mRenderer = nullptr; bool mDebugEnabled; }; // class TextDropShadowCache diff --git a/libs/hwui/TextureCache.cpp b/libs/hwui/TextureCache.cpp index 31bfa3a1ada4..ade8600ab78b 100644 --- a/libs/hwui/TextureCache.cpp +++ b/libs/hwui/TextureCache.cpp @@ -35,26 +35,9 @@ namespace uirenderer { TextureCache::TextureCache() : mCache(LruCache::kUnlimitedCapacity) , mSize(0) - , mMaxSize(MB(DEFAULT_TEXTURE_CACHE_SIZE)) - , mFlushRate(DEFAULT_TEXTURE_CACHE_FLUSH_RATE) + , mMaxSize(Properties::textureCacheSize) + , mFlushRate(Properties::textureCacheFlushRate) , mAssetAtlas(nullptr) { - char property[PROPERTY_VALUE_MAX]; - if (property_get(PROPERTY_TEXTURE_CACHE_SIZE, property, nullptr) > 0) { - INIT_LOGD(" Setting texture cache size to %sMB", property); - setMaxSize(MB(atof(property))); - } else { - INIT_LOGD(" Using default texture cache size of %.2fMB", DEFAULT_TEXTURE_CACHE_SIZE); - } - - if (property_get(PROPERTY_TEXTURE_CACHE_FLUSH_RATE, property, nullptr) > 0) { - float flushRate = atof(property); - INIT_LOGD(" Setting texture cache flush rate to %.2f%%", flushRate * 100.0f); - setFlushRate(flushRate); - } else { - INIT_LOGD(" Using default texture cache flush rate of %.2f%%", - DEFAULT_TEXTURE_CACHE_FLUSH_RATE * 100.0f); - } - mCache.setOnEntryRemovedListener(this); glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize); @@ -79,17 +62,6 @@ uint32_t TextureCache::getMaxSize() { return mMaxSize; } -void TextureCache::setMaxSize(uint32_t maxSize) { - mMaxSize = maxSize; - while (mSize > mMaxSize) { - mCache.removeOldest(); - } -} - -void TextureCache::setFlushRate(float flushRate) { - mFlushRate = std::max(0.0f, std::min(1.0f, flushRate)); -} - /////////////////////////////////////////////////////////////////////////////// // Callbacks /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/TextureCache.h b/libs/hwui/TextureCache.h index 463450c81714..a4317cee73fd 100644 --- a/libs/hwui/TextureCache.h +++ b/libs/hwui/TextureCache.h @@ -108,10 +108,6 @@ public: */ void clear(); - /** - * Sets the maximum size of the cache in bytes. - */ - void setMaxSize(uint32_t maxSize); /** * Returns the maximum size of the cache in bytes. */ @@ -126,11 +122,6 @@ public: * is defined by the flush rate. */ void flush(); - /** - * Indicates the percentage of the cache to retain when a - * memory trim is requested (see Caches::flush). - */ - void setFlushRate(float flushRate); void setAssetAtlas(AssetAtlas* assetAtlas); @@ -148,10 +139,10 @@ private: LruCache mCache; uint32_t mSize; - uint32_t mMaxSize; + const uint32_t mMaxSize; GLint mMaxTextureSize; - float mFlushRate; + const float mFlushRate; bool mDebugEnabled; -- cgit v1.2.3-59-g8ed1b From 7224e2b624daea67b5653285c9640f170c096bdb Mon Sep 17 00:00:00 2001 From: sergeyv Date: Thu, 7 Apr 2016 18:06:53 -0700 Subject: Stop comparing Descriptions with memcmp bug:27894959 Change-Id: I379c11381c08f6f77577a914638b32415768f26e --- libs/hwui/PathCache.cpp | 69 +++++++++++++++++++++++++++++++++-------- libs/hwui/PathCache.h | 21 ++++++------- libs/hwui/TessellationCache.cpp | 40 +++++++++++++++++++----- libs/hwui/TessellationCache.h | 16 +++++----- libs/hwui/utils/Macros.h | 10 +++--- 5 files changed, 110 insertions(+), 46 deletions(-) (limited to 'libs/hwui/PathCache.cpp') diff --git a/libs/hwui/PathCache.cpp b/libs/hwui/PathCache.cpp index 8f914acc5c76..a8ace8c10edd 100644 --- a/libs/hwui/PathCache.cpp +++ b/libs/hwui/PathCache.cpp @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -35,18 +36,34 @@ namespace android { namespace uirenderer { +template +static bool compareWidthHeight(const T& lhs, const T& rhs) { + return (lhs.mWidth == rhs.mWidth) && (lhs.mHeight == rhs.mHeight); +} + +static bool compareRoundRects(const PathDescription::Shape::RoundRect& lhs, + const PathDescription::Shape::RoundRect& rhs) { + return compareWidthHeight(lhs, rhs) && lhs.mRx == rhs.mRx && lhs.mRy == rhs.mRy; +} + +static bool compareArcs(const PathDescription::Shape::Arc& lhs, const PathDescription::Shape::Arc& rhs) { + return compareWidthHeight(lhs, rhs) && lhs.mStartAngle == rhs.mStartAngle && + lhs.mSweepAngle == rhs.mSweepAngle && lhs.mUseCenter == rhs.mUseCenter; +} + /////////////////////////////////////////////////////////////////////////////// // Cache entries /////////////////////////////////////////////////////////////////////////////// PathDescription::PathDescription() - : type(kShapeNone) + : type(ShapeType::None) , join(SkPaint::kDefault_Join) , cap(SkPaint::kDefault_Cap) , style(SkPaint::kFill_Style) , miter(4.0f) , strokeWidth(1.0f) , pathEffect(nullptr) { + // Shape bits should be set to zeroes, because they are used for hash calculation. memset(&shape, 0, sizeof(Shape)); } @@ -58,11 +75,12 @@ PathDescription::PathDescription(ShapeType type, const SkPaint* paint) , miter(paint->getStrokeMiter()) , strokeWidth(paint->getStrokeWidth()) , pathEffect(paint->getPathEffect()) { + // Shape bits should be set to zeroes, because they are used for hash calculation. memset(&shape, 0, sizeof(Shape)); } hash_t PathDescription::hash() const { - uint32_t hash = JenkinsHashMix(0, type); + uint32_t hash = JenkinsHashMix(0, static_cast(type)); hash = JenkinsHashMix(hash, join); hash = JenkinsHashMix(hash, cap); hash = JenkinsHashMix(hash, style); @@ -73,6 +91,32 @@ hash_t PathDescription::hash() const { return JenkinsHashWhiten(hash); } +bool PathDescription::operator==(const PathDescription& rhs) const { + if (type != rhs.type) return false; + if (join != rhs.join) return false; + if (cap != rhs.cap) return false; + if (style != rhs.style) return false; + if (miter != rhs.miter) return false; + if (strokeWidth != rhs.strokeWidth) return false; + if (pathEffect != rhs.pathEffect) return false; + switch (type) { + case ShapeType::None: + return 0; + case ShapeType::Rect: + return compareWidthHeight(shape.rect, rhs.shape.rect); + case ShapeType::RoundRect: + return compareRoundRects(shape.roundRect, rhs.shape.roundRect); + case ShapeType::Circle: + return shape.circle.mRadius == rhs.shape.circle.mRadius; + case ShapeType::Oval: + return compareWidthHeight(shape.oval, rhs.shape.oval); + case ShapeType::Arc: + return compareArcs(shape.arc, rhs.shape.arc); + case ShapeType::Path: + return shape.path.mGenerationID == rhs.shape.path.mGenerationID; + } +} + /////////////////////////////////////////////////////////////////////////////// // Utilities /////////////////////////////////////////////////////////////////////////////// @@ -322,7 +366,7 @@ void PathCache::clearGarbage() { LruCache::Iterator iter(mCache); while (iter.next()) { const PathDescription& key = iter.key(); - if (key.type == kShapePath && key.shape.path.mGenerationID == generationID) { + if (key.type == ShapeType::Path && key.shape.path.mGenerationID == generationID) { pathsToRemove.push(key); } } @@ -336,7 +380,7 @@ void PathCache::clearGarbage() { } PathTexture* PathCache::get(const SkPath* path, const SkPaint* paint) { - PathDescription entry(kShapePath, paint); + PathDescription entry(ShapeType::Path, paint); entry.shape.path.mGenerationID = path->getGenerationID(); PathTexture* texture = mCache.get(entry); @@ -366,9 +410,8 @@ PathTexture* PathCache::get(const SkPath* path, const SkPaint* paint) { return texture; } -void PathCache::remove(const SkPath* path, const SkPaint* paint) -{ - PathDescription entry(kShapePath, paint); +void PathCache::remove(const SkPath* path, const SkPaint* paint) { + PathDescription entry(ShapeType::Path, paint); entry.shape.path.mGenerationID = path->getGenerationID(); mCache.remove(entry); } @@ -378,7 +421,7 @@ void PathCache::precache(const SkPath* path, const SkPaint* paint) { return; } - PathDescription entry(kShapePath, paint); + PathDescription entry(ShapeType::Path, paint); entry.shape.path.mGenerationID = path->getGenerationID(); PathTexture* texture = mCache.get(entry); @@ -417,7 +460,7 @@ void PathCache::precache(const SkPath* path, const SkPaint* paint) { PathTexture* PathCache::getRoundRect(float width, float height, float rx, float ry, const SkPaint* paint) { - PathDescription entry(kShapeRoundRect, paint); + PathDescription entry(ShapeType::RoundRect, paint); entry.shape.roundRect.mWidth = width; entry.shape.roundRect.mHeight = height; entry.shape.roundRect.mRx = rx; @@ -442,7 +485,7 @@ PathTexture* PathCache::getRoundRect(float width, float height, /////////////////////////////////////////////////////////////////////////////// PathTexture* PathCache::getCircle(float radius, const SkPaint* paint) { - PathDescription entry(kShapeCircle, paint); + PathDescription entry(ShapeType::Circle, paint); entry.shape.circle.mRadius = radius; PathTexture* texture = get(entry); @@ -462,7 +505,7 @@ PathTexture* PathCache::getCircle(float radius, const SkPaint* paint) { /////////////////////////////////////////////////////////////////////////////// PathTexture* PathCache::getOval(float width, float height, const SkPaint* paint) { - PathDescription entry(kShapeOval, paint); + PathDescription entry(ShapeType::Oval, paint); entry.shape.oval.mWidth = width; entry.shape.oval.mHeight = height; @@ -485,7 +528,7 @@ PathTexture* PathCache::getOval(float width, float height, const SkPaint* paint) /////////////////////////////////////////////////////////////////////////////// PathTexture* PathCache::getRect(float width, float height, const SkPaint* paint) { - PathDescription entry(kShapeRect, paint); + PathDescription entry(ShapeType::Rect, paint); entry.shape.rect.mWidth = width; entry.shape.rect.mHeight = height; @@ -509,7 +552,7 @@ PathTexture* PathCache::getRect(float width, float height, const SkPaint* paint) PathTexture* PathCache::getArc(float width, float height, float startAngle, float sweepAngle, bool useCenter, const SkPaint* paint) { - PathDescription entry(kShapeArc, paint); + PathDescription entry(ShapeType::Arc, paint); entry.shape.arc.mWidth = width; entry.shape.arc.mHeight = height; entry.shape.arc.mStartAngle = startAngle; diff --git a/libs/hwui/PathCache.h b/libs/hwui/PathCache.h index d2633aa427c5..6368ddd49966 100644 --- a/libs/hwui/PathCache.h +++ b/libs/hwui/PathCache.h @@ -25,6 +25,7 @@ #include "utils/Pair.h" #include +#include #include #include #include @@ -108,18 +109,18 @@ private: sp > mTask; }; // struct PathTexture -enum ShapeType { - kShapeNone, - kShapeRect, - kShapeRoundRect, - kShapeCircle, - kShapeOval, - kShapeArc, - kShapePath +enum class ShapeType { + None, + Rect, + RoundRect, + Circle, + Oval, + Arc, + Path }; struct PathDescription { - DESCRIPTION_TYPE(PathDescription); + HASHABLE_TYPE(PathDescription); ShapeType type; SkPaint::Join join; SkPaint::Cap cap; @@ -159,8 +160,6 @@ struct PathDescription { PathDescription(); PathDescription(ShapeType shapeType, const SkPaint* paint); - - hash_t hash() const; }; /** diff --git a/libs/hwui/TessellationCache.cpp b/libs/hwui/TessellationCache.cpp index 14c8f3926e31..cfdc0848c8b0 100644 --- a/libs/hwui/TessellationCache.cpp +++ b/libs/hwui/TessellationCache.cpp @@ -35,13 +35,14 @@ namespace uirenderer { /////////////////////////////////////////////////////////////////////////////// TessellationCache::Description::Description() - : type(kNone) + : type(Type::None) , scaleX(1.0f) , scaleY(1.0f) , aa(false) , cap(SkPaint::kDefault_Cap) , style(SkPaint::kFill_Style) , strokeWidth(1.0f) { + // Shape bits should be set to zeroes, because they are used for hash calculation. memset(&shape, 0, sizeof(Shape)); } @@ -52,11 +53,30 @@ TessellationCache::Description::Description(Type type, const Matrix4& transform, , style(paint.getStyle()) , strokeWidth(paint.getStrokeWidth()) { PathTessellator::extractTessellationScales(transform, &scaleX, &scaleY); + // Shape bits should be set to zeroes, because they are used for hash calculation. memset(&shape, 0, sizeof(Shape)); } +bool TessellationCache::Description::operator==(const TessellationCache::Description& rhs) const { + if (type != rhs.type) return false; + if (scaleX != rhs.scaleX) return false; + if (scaleY != rhs.scaleY) return false; + if (aa != rhs.aa) return false; + if (cap != rhs.cap) return false; + if (style != rhs.style) return false; + if (strokeWidth != rhs.strokeWidth) return false; + if (type == Type::None) return true; + const Shape::RoundRect& lRect = shape.roundRect; + const Shape::RoundRect& rRect = rhs.shape.roundRect; + + if (lRect.width != rRect.width) return false; + if (lRect.height != rRect.height) return false; + if (lRect.rx != rRect.rx) return false; + return lRect.ry == rRect.ry; +} + hash_t TessellationCache::Description::hash() const { - uint32_t hash = JenkinsHashMix(0, type); + uint32_t hash = JenkinsHashMix(0, static_cast(type)); hash = JenkinsHashMix(hash, aa); hash = JenkinsHashMix(hash, cap); hash = JenkinsHashMix(hash, style); @@ -77,17 +97,23 @@ void TessellationCache::Description::setupMatrixAndPaint(Matrix4* matrix, SkPain TessellationCache::ShadowDescription::ShadowDescription() : nodeKey(nullptr) { - memset(&matrixData, 0, 16 * sizeof(float)); + memset(&matrixData, 0, sizeof(matrixData)); } -TessellationCache::ShadowDescription::ShadowDescription(const void* nodeKey, const Matrix4* drawTransform) +TessellationCache::ShadowDescription::ShadowDescription(const SkPath* nodeKey, const Matrix4* drawTransform) : nodeKey(nodeKey) { - memcpy(&matrixData, drawTransform->data, 16 * sizeof(float)); + memcpy(&matrixData, drawTransform->data, sizeof(matrixData)); +} + +bool TessellationCache::ShadowDescription::operator==( + const TessellationCache::ShadowDescription& rhs) const { + return nodeKey == rhs.nodeKey + && memcmp(&matrixData, &rhs.matrixData, sizeof(matrixData)) == 0; } hash_t TessellationCache::ShadowDescription::hash() const { uint32_t hash = JenkinsHashMixBytes(0, (uint8_t*) &nodeKey, sizeof(const void*)); - hash = JenkinsHashMixBytes(hash, (uint8_t*) &matrixData, 16 * sizeof(float)); + hash = JenkinsHashMixBytes(hash, (uint8_t*) &matrixData, sizeof(matrixData)); return JenkinsHashWhiten(hash); } @@ -428,7 +454,7 @@ static VertexBuffer* tessellateRoundRect(const TessellationCache::Description& d TessellationCache::Buffer* TessellationCache::getRoundRectBuffer( const Matrix4& transform, const SkPaint& paint, float width, float height, float rx, float ry) { - Description entry(Description::kRoundRect, transform, paint); + Description entry(Description::Type::RoundRect, transform, paint); entry.shape.roundRect.width = width; entry.shape.roundRect.height = height; entry.shape.roundRect.rx = rx; diff --git a/libs/hwui/TessellationCache.h b/libs/hwui/TessellationCache.h index 0bd6365db60f..6141b4ef63d7 100644 --- a/libs/hwui/TessellationCache.h +++ b/libs/hwui/TessellationCache.h @@ -52,10 +52,10 @@ public: typedef Pair vertexBuffer_pair_t; struct Description { - DESCRIPTION_TYPE(Description); - enum Type { - kNone, - kRoundRect, + HASHABLE_TYPE(Description); + enum class Type { + None, + RoundRect, }; Type type; @@ -76,18 +76,16 @@ public: Description(); Description(Type type, const Matrix4& transform, const SkPaint& paint); - hash_t hash() const; void setupMatrixAndPaint(Matrix4* matrix, SkPaint* paint) const; }; struct ShadowDescription { - DESCRIPTION_TYPE(ShadowDescription); - const void* nodeKey; + HASHABLE_TYPE(ShadowDescription); + const SkPath* nodeKey; float matrixData[16]; ShadowDescription(); - ShadowDescription(const void* nodeKey, const Matrix4* drawTransform); - hash_t hash() const; + ShadowDescription(const SkPath* nodeKey, const Matrix4* drawTransform); }; class ShadowTask : public Task { diff --git a/libs/hwui/utils/Macros.h b/libs/hwui/utils/Macros.h index ccf2287400dc..7212897bf5d3 100644 --- a/libs/hwui/utils/Macros.h +++ b/libs/hwui/utils/Macros.h @@ -23,12 +23,10 @@ Type(const Type&) = delete; \ void operator=(const Type&) = delete -#define DESCRIPTION_TYPE(Type) \ - int compare(const Type& rhs) const { return memcmp(this, &rhs, sizeof(Type));} \ - bool operator==(const Type& other) const { return compare(other) == 0; } \ - bool operator!=(const Type& other) const { return compare(other) != 0; } \ - friend inline int strictly_order_type(const Type& lhs, const Type& rhs) { return lhs.compare(rhs) < 0; } \ - friend inline int compare_type(const Type& lhs, const Type& rhs) { return lhs.compare(rhs); } \ +#define HASHABLE_TYPE(Type) \ + bool operator==(const Type& other) const; \ + hash_t hash() const; \ + bool operator!=(const Type& other) const { return !(*this == other); } \ friend inline hash_t hash_type(const Type& entry) { return entry.hash(); } #define REQUIRE_COMPATIBLE_LAYOUT(Type) \ -- cgit v1.2.3-59-g8ed1b