diff options
Diffstat (limited to 'libs')
31 files changed, 212 insertions, 245 deletions
diff --git a/libs/androidfw/Android.mk b/libs/androidfw/Android.mk index dbee7ed8699a..20d547007cff 100644 --- a/libs/androidfw/Android.mk +++ b/libs/androidfw/Android.mk @@ -14,7 +14,7 @@ LOCAL_PATH:= $(call my-dir) -# libandroidfw is partially built for the host (used by obbtool and others) +# libandroidfw is partially built for the host (used by obbtool, aapt, and others) # These files are common to host and target builds. commonSources := \ @@ -35,26 +35,17 @@ deviceSources := \ BackupHelpers.cpp \ CursorWindow.cpp -hostSources := \ - $(commonSources) +hostSources := $(commonSources) # For the host # ===================================================== - include $(CLEAR_VARS) -LOCAL_SRC_FILES:= $(hostSources) - LOCAL_MODULE:= libandroidfw - LOCAL_MODULE_TAGS := optional - LOCAL_CFLAGS += -DSTATIC_ANDROIDFW_FOR_TOOLS - -LOCAL_C_INCLUDES := \ - external/zlib - -LOCAL_STATIC_LIBRARIES := liblog libziparchive-host libutils +LOCAL_SRC_FILES:= $(hostSources) +LOCAL_C_INCLUDES := external/zlib include $(BUILD_HOST_STATIC_LIBRARY) @@ -64,8 +55,13 @@ include $(BUILD_HOST_STATIC_LIBRARY) include $(CLEAR_VARS) +LOCAL_MODULE:= libandroidfw +LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES:= $(deviceSources) - +LOCAL_C_INCLUDES := \ + external/zlib \ + system/core/include +LOCAL_STATIC_LIBRARIES := libziparchive LOCAL_SHARED_LIBRARIES := \ libbinder \ liblog \ @@ -73,16 +69,6 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ libz -LOCAL_STATIC_LIBRARIES := libziparchive - -LOCAL_C_INCLUDES := \ - external/zlib \ - system/core/include - -LOCAL_MODULE:= libandroidfw - -LOCAL_MODULE_TAGS := optional - include $(BUILD_SHARED_LIBRARY) diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index 3bbca1a0165e..3cf1021dfc7c 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -87,11 +87,11 @@ inline static T max(T a, T b) { // range checked; guaranteed to NUL-terminate within the stated number of available slots // NOTE: if this truncates the dst string due to running out of space, no attempt is // made to avoid splitting surrogate pairs. -static void strcpy16_dtoh(uint16_t* dst, const uint16_t* src, size_t avail) +static void strcpy16_dtoh(char16_t* dst, const uint16_t* src, size_t avail) { - uint16_t* last = dst + avail - 1; + char16_t* last = dst + avail - 1; while (*src && (dst < last)) { - char16_t s = dtohs(*src); + char16_t s = dtohs(static_cast<char16_t>(*src)); *dst++ = s; src++; } @@ -501,7 +501,7 @@ status_t ResStringPool::setTo(const void* data, size_t size, bool copyData) if (mHeader->flags&ResStringPool_header::UTF8_FLAG) { charSize = sizeof(uint8_t); } else { - charSize = sizeof(char16_t); + charSize = sizeof(uint16_t); } // There should be at least space for the smallest string @@ -547,8 +547,8 @@ status_t ResStringPool::setTo(const void* data, size_t size, bool copyData) e[i] = dtohl(mEntries[i]); } if (!(mHeader->flags&ResStringPool_header::UTF8_FLAG)) { - const char16_t* strings = (const char16_t*)mStrings; - char16_t* s = const_cast<char16_t*>(strings); + const uint16_t* strings = (const uint16_t*)mStrings; + uint16_t* s = const_cast<uint16_t*>(strings); for (i=0; i<mStringPoolSize; i++) { s[i] = dtohs(strings[i]); } @@ -558,7 +558,7 @@ status_t ResStringPool::setTo(const void* data, size_t size, bool copyData) if ((mHeader->flags&ResStringPool_header::UTF8_FLAG && ((uint8_t*)mStrings)[mStringPoolSize-1] != 0) || (!mHeader->flags&ResStringPool_header::UTF8_FLAG && - ((char16_t*)mStrings)[mStringPoolSize-1] != 0)) { + ((uint16_t*)mStrings)[mStringPoolSize-1] != 0)) { ALOGW("Bad string block: last string is not 0-terminated\n"); return (mError=BAD_TYPE); } @@ -656,7 +656,7 @@ void ResStringPool::uninit() * add it together with the next character. */ static inline size_t -decodeLength(const char16_t** str) +decodeLength(const uint16_t** str) { size_t len = **str; if ((len & 0x8000) != 0) { @@ -689,19 +689,19 @@ decodeLength(const uint8_t** str) return len; } -const uint16_t* ResStringPool::stringAt(size_t idx, size_t* u16len) const +const char16_t* ResStringPool::stringAt(size_t idx, size_t* u16len) const { if (mError == NO_ERROR && idx < mHeader->stringCount) { const bool isUTF8 = (mHeader->flags&ResStringPool_header::UTF8_FLAG) != 0; - const uint32_t off = mEntries[idx]/(isUTF8?sizeof(char):sizeof(char16_t)); + const uint32_t off = mEntries[idx]/(isUTF8?sizeof(uint8_t):sizeof(uint16_t)); if (off < (mStringPoolSize-1)) { if (!isUTF8) { - const char16_t* strings = (char16_t*)mStrings; - const char16_t* str = strings+off; + const uint16_t* strings = (uint16_t*)mStrings; + const uint16_t* str = strings+off; *u16len = decodeLength(&str); if ((uint32_t)(str+*u16len-strings) < mStringPoolSize) { - return str; + return reinterpret_cast<const char16_t*>(str); } else { ALOGW("Bad string block: string #%d extends to %d, past end at %d\n", (int)idx, (int)(str+*u16len-strings), (int)mStringPoolSize); @@ -1013,7 +1013,7 @@ int32_t ResXMLParser::getCommentID() const return mCurNode != NULL ? dtohl(mCurNode->comment.index) : -1; } -const uint16_t* ResXMLParser::getComment(size_t* outLen) const +const char16_t* ResXMLParser::getComment(size_t* outLen) const { int32_t id = getCommentID(); return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL; @@ -1032,7 +1032,7 @@ int32_t ResXMLParser::getTextID() const return -1; } -const uint16_t* ResXMLParser::getText(size_t* outLen) const +const char16_t* ResXMLParser::getText(size_t* outLen) const { int32_t id = getTextID(); return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL; @@ -1055,7 +1055,7 @@ int32_t ResXMLParser::getNamespacePrefixID() const return -1; } -const uint16_t* ResXMLParser::getNamespacePrefix(size_t* outLen) const +const char16_t* ResXMLParser::getNamespacePrefix(size_t* outLen) const { int32_t id = getNamespacePrefixID(); //printf("prefix=%d event=%p\n", id, mEventCode); @@ -1070,7 +1070,7 @@ int32_t ResXMLParser::getNamespaceUriID() const return -1; } -const uint16_t* ResXMLParser::getNamespaceUri(size_t* outLen) const +const char16_t* ResXMLParser::getNamespaceUri(size_t* outLen) const { int32_t id = getNamespaceUriID(); //printf("uri=%d event=%p\n", id, mEventCode); @@ -1088,7 +1088,7 @@ int32_t ResXMLParser::getElementNamespaceID() const return -1; } -const uint16_t* ResXMLParser::getElementNamespace(size_t* outLen) const +const char16_t* ResXMLParser::getElementNamespace(size_t* outLen) const { int32_t id = getElementNamespaceID(); return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL; @@ -1105,7 +1105,7 @@ int32_t ResXMLParser::getElementNameID() const return -1; } -const uint16_t* ResXMLParser::getElementName(size_t* outLen) const +const char16_t* ResXMLParser::getElementName(size_t* outLen) const { int32_t id = getElementNameID(); return id >= 0 ? mTree.mStrings.stringAt(id, outLen) : NULL; @@ -1134,7 +1134,7 @@ int32_t ResXMLParser::getAttributeNamespaceID(size_t idx) const return -2; } -const uint16_t* ResXMLParser::getAttributeNamespace(size_t idx, size_t* outLen) const +const char16_t* ResXMLParser::getAttributeNamespace(size_t idx, size_t* outLen) const { int32_t id = getAttributeNamespaceID(idx); //printf("attribute namespace=%d idx=%d event=%p\n", id, idx, mEventCode); @@ -1165,7 +1165,7 @@ int32_t ResXMLParser::getAttributeNameID(size_t idx) const return -1; } -const uint16_t* ResXMLParser::getAttributeName(size_t idx, size_t* outLen) const +const char16_t* ResXMLParser::getAttributeName(size_t idx, size_t* outLen) const { int32_t id = getAttributeNameID(idx); //printf("attribute name=%d idx=%d event=%p\n", id, idx, mEventCode); @@ -1205,7 +1205,7 @@ int32_t ResXMLParser::getAttributeValueStringID(size_t idx) const return -1; } -const uint16_t* ResXMLParser::getAttributeStringValue(size_t idx, size_t* outLen) const +const char16_t* ResXMLParser::getAttributeStringValue(size_t idx, size_t* outLen) const { int32_t id = getAttributeValueStringID(idx); //XML_NOISY(printf("getAttributeValue 0x%x=0x%x\n", idx, id)); @@ -3645,8 +3645,12 @@ ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag Entry entry; status_t err = getEntry(grp, t, e, &desiredConfig, &entry); if (err != NO_ERROR) { + // Only log the failure when we're not running on the host as + // part of a tool. The caller will do its own logging. +#ifndef STATIC_ANDROIDFW_FOR_TOOLS ALOGW("Failure getting entry for 0x%08x (t=%d e=%d) (error %d)\n", resID, t, e, err); +#endif return err; } @@ -4239,7 +4243,7 @@ nope: return 0; } -bool ResTable::expandResourceRef(const uint16_t* refStr, size_t refLen, +bool ResTable::expandResourceRef(const char16_t* refStr, size_t refLen, String16* outPackage, String16* outType, String16* outName, @@ -5665,8 +5669,8 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg, if (idx == 0) { idx = mPackageGroups.size() + 1; - char16_t tmpName[sizeof(pkg->name)/sizeof(char16_t)]; - strcpy16_dtoh(tmpName, pkg->name, sizeof(pkg->name)/sizeof(char16_t)); + char16_t tmpName[sizeof(pkg->name)/sizeof(pkg->name[0])]; + strcpy16_dtoh(tmpName, pkg->name, sizeof(pkg->name)/sizeof(pkg->name[0])); group = new PackageGroup(this, String16(tmpName), id); if (group == NULL) { delete package; @@ -6036,7 +6040,10 @@ status_t ResTable::createIdmap(const ResTable& overlay, *outSize += 2 * sizeof(uint16_t); // overlay packages are assumed to contain only one package group - const String16 overlayPackage(overlay.mPackageGroups[0]->packages[0]->package->name); + const ResTable_package* overlayPackageStruct = overlay.mPackageGroups[0]->packages[0]->package; + char16_t tmpName[sizeof(overlayPackageStruct->name)/sizeof(overlayPackageStruct->name[0])]; + strcpy16_dtoh(tmpName, overlayPackageStruct->name, sizeof(overlayPackageStruct->name)/sizeof(overlayPackageStruct->name[0])); + const String16 overlayPackage(tmpName); for (size_t typeIndex = 0; typeIndex < pg->types.size(); ++typeIndex) { const TypeList& typeList = pg->types[typeIndex]; @@ -6345,8 +6352,10 @@ void ResTable::print(bool inclValues) const // Use a package's real ID, since the ID may have been assigned // if this package is a shared library. packageId = pkg->package->id; + char16_t tmpName[sizeof(pkg->package->name)/sizeof(pkg->package->name[0])]; + strcpy16_dtoh(tmpName, pkg->package->name, sizeof(pkg->package->name)/sizeof(pkg->package->name[0])); printf(" Package %d id=0x%02x name=%s\n", (int)pkgIndex, - pkg->package->id, String8(String16(pkg->package->name)).string()); + pkg->package->id, String8(tmpName).string()); } for (size_t typeIndex=0; typeIndex < pg->types.size(); typeIndex++) { diff --git a/libs/androidfw/misc.cpp b/libs/androidfw/misc.cpp index 29686efe3753..ea54cc56e7b0 100644 --- a/libs/androidfw/misc.cpp +++ b/libs/androidfw/misc.cpp @@ -22,9 +22,9 @@ #include <androidfw/misc.h> #include <sys/stat.h> -#include <string.h> +#include <cstring> #include <errno.h> -#include <stdio.h> +#include <cstdio> using namespace android; diff --git a/libs/androidfw/tests/Android.mk b/libs/androidfw/tests/Android.mk index b2e465c55e47..2d7906f28ba3 100644 --- a/libs/androidfw/tests/Android.mk +++ b/libs/androidfw/tests/Android.mk @@ -37,7 +37,6 @@ testFiles := \ include $(CLEAR_VARS) LOCAL_MODULE := libandroidfw_tests - LOCAL_SRC_FILES := $(testFiles) LOCAL_STATIC_LIBRARIES := \ libandroidfw \ @@ -55,11 +54,9 @@ ifneq ($(SDK_ONLY),true) include $(CLEAR_VARS) LOCAL_MODULE := libandroidfw_tests - LOCAL_SRC_FILES := $(testFiles) \ BackupData_test.cpp \ ObbFile_test.cpp - LOCAL_SHARED_LIBRARIES := \ libandroidfw \ libcutils \ diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index f0bf7b22ff01..952f7394fb5c 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -265,14 +265,27 @@ void Caches::dumpMemoryUsage() { } void Caches::dumpMemoryUsage(String8 &log) { + uint32_t total = 0; log.appendFormat("Current memory usage / total memory usage (bytes):\n"); log.appendFormat(" TextureCache %8d / %8d\n", textureCache.getSize(), textureCache.getMaxSize()); log.appendFormat(" LayerCache %8d / %8d (numLayers = %zu)\n", layerCache.getSize(), layerCache.getMaxSize(), layerCache.getCount()); - log.appendFormat(" Garbage layers %8zu\n", mLayerGarbage.size()); - log.appendFormat(" Active layers %8zu\n", - mRenderState ? mRenderState->mActiveLayers.size() : 0); + if (mRenderState) { + int memused = 0; + for (std::set<const Layer*>::iterator it = mRenderState->mActiveLayers.begin(); + it != mRenderState->mActiveLayers.end(); it++) { + const Layer* layer = *it; + log.appendFormat(" Layer size %dx%d; isTextureLayer()=%d; texid=%u fbo=%u; refs=%d\n", + layer->getWidth(), layer->getHeight(), + layer->isTextureLayer(), layer->getTexture(), + layer->getFbo(), layer->getStrongCount()); + memused += layer->getWidth() * layer->getHeight() * 4; + } + log.appendFormat(" Layers total %8d (numLayers = %zu)\n", + memused, mRenderState->mActiveLayers.size()); + total += memused; + } log.appendFormat(" RenderBufferCache %8d / %8d\n", renderBufferCache.getSize(), renderBufferCache.getMaxSize()); log.appendFormat(" GradientCache %8d / %8d\n", @@ -297,9 +310,7 @@ void Caches::dumpMemoryUsage(String8 &log) { log.appendFormat(" FboCache %8d / %8d\n", fboCache.getSize(), fboCache.getMaxSize()); - uint32_t total = 0; total += textureCache.getSize(); - total += layerCache.getSize(); total += renderBufferCache.getSize(); total += gradientCache.getSize(); total += pathCache.getSize(); @@ -323,27 +334,6 @@ void Caches::clearGarbage() { textureCache.clearGarbage(); pathCache.clearGarbage(); patchCache.clearGarbage(); - - Vector<Layer*> layers; - - { // scope for the lock - Mutex::Autolock _l(mGarbageLock); - layers = mLayerGarbage; - mLayerGarbage.clear(); - } - - size_t count = layers.size(); - for (size_t i = 0; i < count; i++) { - Layer* layer = layers.itemAt(i); - delete layer; - } - layers.clear(); -} - -void Caches::deleteLayerDeferred(Layer* layer) { - Mutex::Autolock _l(mGarbageLock); - layer->state = Layer::kState_InGarbageList; - mLayerGarbage.push(layer); } void Caches::flush(FlushMode mode) { diff --git a/libs/hwui/DeferredLayerUpdater.cpp b/libs/hwui/DeferredLayerUpdater.cpp index a6d7e78b87bf..d02455c8fc1d 100644 --- a/libs/hwui/DeferredLayerUpdater.cpp +++ b/libs/hwui/DeferredLayerUpdater.cpp @@ -24,25 +24,6 @@ namespace android { namespace uirenderer { -class DeleteLayerTask : public renderthread::RenderTask { -public: - DeleteLayerTask(renderthread::EglManager& eglManager, Layer* layer) - : mEglManager(eglManager) - , mLayer(layer) - {} - - virtual void run() { - mEglManager.requireGlContext(); - LayerRenderer::destroyLayer(mLayer); - mLayer = 0; - delete this; - } - -private: - renderthread::EglManager& mEglManager; - Layer* mLayer; -}; - DeferredLayerUpdater::DeferredLayerUpdater(renderthread::RenderThread& thread, Layer* layer) : mSurfaceTexture(0) , mTransform(0) @@ -62,7 +43,7 @@ DeferredLayerUpdater::DeferredLayerUpdater(renderthread::RenderThread& thread, L DeferredLayerUpdater::~DeferredLayerUpdater() { SkSafeUnref(mColorFilter); setTransform(0); - mRenderThread.queue(new DeleteLayerTask(mRenderThread.eglManager(), mLayer)); + mLayer->postDecStrong(); mLayer = 0; } diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp index d8932ce4631e..4a927cfc6399 100644 --- a/libs/hwui/DisplayList.cpp +++ b/libs/hwui/DisplayList.cpp @@ -61,10 +61,6 @@ void DisplayListData::cleanupResources() { caches.resourceCache.decrementRefcountLocked(sourcePaths.itemAt(i)); } - for (size_t i = 0; i < layers.size(); i++) { - caches.resourceCache.decrementRefcountLocked(layers.itemAt(i)); - } - caches.resourceCache.unlock(); for (size_t i = 0; i < paints.size(); i++) { @@ -86,7 +82,6 @@ void DisplayListData::cleanupResources() { paints.clear(); regions.clear(); paths.clear(); - layers.clear(); } size_t DisplayListData::addChild(DrawRenderNodeOp* op) { diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index dea109cd57b7..cb8a8d1cbc88 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -147,7 +147,6 @@ public: Vector<const SkPath*> paths; SortedVector<const SkPath*> sourcePaths; Vector<const SkRegion*> regions; - Vector<Layer*> layers; Vector<Functor*> functors; const Vector<Chunk>& getChunks() const { @@ -157,11 +156,7 @@ public: size_t addChild(DrawRenderNodeOp* childOp); const Vector<DrawRenderNodeOp*>& children() { return mChildren; } - void refProperty(CanvasPropertyPrimitive* prop) { - mReferenceHolders.push(prop); - } - - void refProperty(CanvasPropertyPaint* prop) { + void ref(VirtualLightRefBase* prop) { mReferenceHolders.push(prop); } diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 1f7092147686..c17dd098d4e6 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -189,7 +189,7 @@ status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty } status_t DisplayListRenderer::drawLayer(Layer* layer, float x, float y) { - layer = refLayer(layer); + mDisplayListData->ref(layer); addDrawOp(new (alloc()) DrawLayerOp(layer, x, y)); return DrawGlInfo::kStatusDone; } @@ -280,13 +280,13 @@ status_t DisplayListRenderer::drawRoundRect( CanvasPropertyPrimitive* right, CanvasPropertyPrimitive* bottom, CanvasPropertyPrimitive* rx, CanvasPropertyPrimitive* ry, CanvasPropertyPaint* paint) { - mDisplayListData->refProperty(left); - mDisplayListData->refProperty(top); - mDisplayListData->refProperty(right); - mDisplayListData->refProperty(bottom); - mDisplayListData->refProperty(rx); - mDisplayListData->refProperty(ry); - mDisplayListData->refProperty(paint); + mDisplayListData->ref(left); + mDisplayListData->ref(top); + mDisplayListData->ref(right); + mDisplayListData->ref(bottom); + mDisplayListData->ref(rx); + mDisplayListData->ref(ry); + mDisplayListData->ref(paint); addDrawOp(new (alloc()) DrawRoundRectPropsOp(&left->value, &top->value, &right->value, &bottom->value, &rx->value, &ry->value, &paint->value)); return DrawGlInfo::kStatusDone; @@ -300,10 +300,10 @@ status_t DisplayListRenderer::drawCircle(float x, float y, float radius, const S status_t DisplayListRenderer::drawCircle(CanvasPropertyPrimitive* x, CanvasPropertyPrimitive* y, CanvasPropertyPrimitive* radius, CanvasPropertyPaint* paint) { - mDisplayListData->refProperty(x); - mDisplayListData->refProperty(y); - mDisplayListData->refProperty(radius); - mDisplayListData->refProperty(paint); + mDisplayListData->ref(x); + mDisplayListData->ref(y); + mDisplayListData->ref(radius); + mDisplayListData->ref(paint); addDrawOp(new (alloc()) DrawCirclePropsOp(&x->value, &y->value, &radius->value, &paint->value)); return DrawGlInfo::kStatusDone; diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index 3a3fc3af9f0f..901e8f02fa7a 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -267,12 +267,6 @@ private: return regionCopy; } - inline Layer* refLayer(Layer* layer) { - mDisplayListData->layers.add(layer); - mCaches.resourceCache.incrementRefcount(layer); - return layer; - } - inline const SkBitmap* refBitmap(const SkBitmap* bitmap) { // Note that this assumes the bitmap is immutable. There are cases this won't handle // correctly, such as creating the bitmap from scratch, drawing with it, changing its diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp index b5089aa79ff3..b95636bbf7db 100644 --- a/libs/hwui/Layer.cpp +++ b/libs/hwui/Layer.cpp @@ -35,6 +35,9 @@ Layer::Layer(Type layerType, RenderState& renderState, const uint32_t layerWidth , renderState(renderState) , texture(caches) , type(layerType) { + // TODO: This is a violation of Android's typical ref counting, but it + // preserves the old inc/dec ref locations. This should be changed... + incStrong(0); mesh = NULL; meshElementCount = 0; cacheable = true; @@ -53,20 +56,14 @@ Layer::Layer(Type layerType, RenderState& renderState, const uint32_t layerWidth forceFilter = false; deferredList = NULL; convexMask = NULL; - caches.resourceCache.incrementRefcount(this); rendererLightPosDirty = true; wasBuildLayered = false; - if (!isTextureLayer()) { - // track only non-texture layer lifecycles in renderstate, - // because texture layers are destroyed via finalizer - renderState.registerLayer(this); - } + renderState.registerLayer(this); } Layer::~Layer() { - if (!isTextureLayer()) { - renderState.unregisterLayer(this); - } + renderState.requireGLContext(); + renderState.unregisterLayer(this); SkSafeUnref(colorFilter); removeFbo(); deleteTexture(); @@ -292,5 +289,9 @@ void Layer::render(const OpenGLRenderer& rootRenderer) { renderNode = NULL; } +void Layer::postDecStrong() { + renderState.postDecStrong(this); +} + }; // namespace uirenderer }; // namespace android diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index a8e1c2671064..64d1d1226ffb 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -52,7 +52,7 @@ class DeferStateStruct; /** * A layer has dimensions and is backed by an OpenGL texture or FBO. */ -class Layer { +class Layer : public VirtualLightRefBase { public: enum Type { kType_Texture, @@ -280,6 +280,12 @@ public: void render(const OpenGLRenderer& rootRenderer); /** + * Posts a decStrong call to the appropriate thread. + * Thread-safe. + */ + void postDecStrong(); + + /** * Bounds of the layer. */ Rect layer; diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index 833f64bc96e7..3033dc689c22 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -84,7 +84,7 @@ void LayerCache::deleteLayer(Layer* layer) { layer->getFbo()); mSize -= layer->getWidth() * layer->getHeight() * 4; layer->state = Layer::kState_DeletedFromCache; - Caches::getInstance().resourceCache.decrementRefcount(layer); + layer->decStrong(0); } } diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index 103c84324627..394c64795aee 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -212,7 +212,7 @@ Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width // Creating a new layer always increment its refcount by 1, this allows // us to destroy the layer object if one was created for us - Caches::getInstance().resourceCache.decrementRefcount(layer); + layer->decStrong(0); return NULL; } @@ -240,7 +240,7 @@ Layer* LayerRenderer::createRenderLayer(RenderState& renderState, uint32_t width if (glGetError() != GL_NO_ERROR) { ALOGE("Could not allocate texture for layer (fbo=%d %dx%d)", fbo, width, height); renderState.bindFramebuffer(previousFbo); - caches.resourceCache.decrementRefcount(layer); + layer->decStrong(0); return NULL; } } @@ -316,7 +316,7 @@ void LayerRenderer::destroyLayer(Layer* layer) { if (!Caches::getInstance().layerCache.put(layer)) { LAYER_RENDERER_LOGD(" Destroyed!"); - Caches::getInstance().resourceCache.decrementRefcount(layer); + layer->decStrong(0); } else { LAYER_RENDERER_LOGD(" Cached!"); #if DEBUG_LAYER_RENDERER @@ -328,14 +328,6 @@ void LayerRenderer::destroyLayer(Layer* layer) { } } -void LayerRenderer::destroyLayerDeferred(Layer* layer) { - if (layer) { - LAYER_RENDERER_LOGD("Deferring layer destruction, fbo = %d", layer->getFbo()); - - Caches::getInstance().deleteLayerDeferred(layer); - } -} - void LayerRenderer::flushLayer(RenderState& renderState, Layer* layer) { #ifdef GL_EXT_discard_framebuffer if (!layer) return; diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index bf7828c3c175..4d8620b8a4ea 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -60,7 +60,6 @@ public: static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, bool isOpaque, bool forceFilter, GLenum renderTarget, float* textureTransform); static void destroyLayer(Layer* layer); - ANDROID_API static void destroyLayerDeferred(Layer* layer); static bool copyLayer(RenderState& renderState, Layer* layer, SkBitmap* bitmap); static void flushLayer(RenderState& renderState, Layer* layer); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 19fc9a3caf0d..d570b0d5bc9c 100755 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -509,11 +509,8 @@ 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); + Layer* layer = mLayerUpdates.itemAt(i).get(); updateLayer(layer, false); - if (CC_UNLIKELY(mCaches.drawDeferDisabled)) { - mCaches.resourceCache.decrementRefcount(layer); - } } if (CC_UNLIKELY(mCaches.drawDeferDisabled)) { @@ -532,7 +529,7 @@ void OpenGLRenderer::flushLayers() { // Note: it is very important to update the layers in order for (int i = 0; i < count; i++) { - Layer* layer = mLayerUpdates.itemAt(i); + Layer* layer = mLayerUpdates.itemAt(i).get(); sprintf(layerName, "Layer #%d", i); startMark(layerName); @@ -542,8 +539,6 @@ void OpenGLRenderer::flushLayers() { ATRACE_END(); endMark(); - - mCaches.resourceCache.decrementRefcount(layer); } mLayerUpdates.clear(); @@ -565,7 +560,6 @@ void OpenGLRenderer::pushLayerUpdate(Layer* layer) { } } mLayerUpdates.push_back(layer); - mCaches.resourceCache.incrementRefcount(layer); } } @@ -574,25 +568,12 @@ void OpenGLRenderer::cancelLayerUpdate(Layer* layer) { for (int i = mLayerUpdates.size() - 1; i >= 0; i--) { if (mLayerUpdates.itemAt(i) == layer) { mLayerUpdates.removeAt(i); - mCaches.resourceCache.decrementRefcount(layer); break; } } } } -void OpenGLRenderer::clearLayerUpdates() { - size_t count = mLayerUpdates.size(); - if (count > 0) { - mCaches.resourceCache.lock(); - for (size_t i = 0; i < count; i++) { - mCaches.resourceCache.decrementRefcountLocked(mLayerUpdates.itemAt(i)); - } - mCaches.resourceCache.unlock(); - mLayerUpdates.clear(); - } -} - void OpenGLRenderer::flushLayerUpdates() { ATRACE_CALL(); syncState(); @@ -956,7 +937,7 @@ void OpenGLRenderer::composeLayer(const Snapshot& removed, const Snapshot& resto layer->setConvexMask(NULL); if (!mCaches.layerCache.put(layer)) { LAYER_LOGD("Deleting layer"); - Caches::getInstance().resourceCache.decrementRefcount(layer); + layer->decStrong(0); } } diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index c2c0b0efc72e..e1c3d10fc9c9 100755 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -140,7 +140,6 @@ public: void pushLayerUpdate(Layer* layer); void cancelLayerUpdate(Layer* layer); - void clearLayerUpdates(); void flushLayerUpdates(); void markLayersAsBuildLayers(); @@ -982,7 +981,7 @@ private: // List of rectangles to clear after saveLayer() is invoked Vector<Rect*> mLayers; // List of layers to update at the beginning of a frame - Vector<Layer*> mLayerUpdates; + Vector< sp<Layer> > mLayerUpdates; // The following fields are used to setup drawing // Used to describe the shaders to generate diff --git a/libs/hwui/PathTessellator.cpp b/libs/hwui/PathTessellator.cpp index 281ca02c39f1..27ef06fae866 100644 --- a/libs/hwui/PathTessellator.cpp +++ b/libs/hwui/PathTessellator.cpp @@ -812,7 +812,7 @@ void PathTessellator::tessellatePoints(const float* points, int count, const SkP // determine point shape SkPath path; float radius = paintInfo.halfStrokeWidth; - if (radius == 0.0f) radius = 0.25f; + if (radius == 0.0f) radius = 0.5f; if (paintInfo.cap == SkPaint::kRound_Cap) { path.addCircle(0, 0, radius); diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp index cc72ae098b0f..0dad0dcae641 100644 --- a/libs/hwui/Program.cpp +++ b/libs/hwui/Program.cpp @@ -141,11 +141,12 @@ GLuint Program::buildShader(const char* source, GLenum type) { GLint status; glGetShaderiv(shader, GL_COMPILE_STATUS, &status); if (status != GL_TRUE) { + ALOGE("Error while compiling this shader:\n===\n%s\n===", source); // Some drivers return wrong values for GL_INFO_LOG_LENGTH // use a fixed size instead GLchar log[512]; glGetShaderInfoLog(shader, sizeof(log), 0, &log[0]); - LOG_ALWAYS_FATAL("Error while compiling shader: %s", log); + LOG_ALWAYS_FATAL("Shader info log: %s", log); return 0; } diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp index 40cd13ef4f02..c9ed9a7d780b 100644 --- a/libs/hwui/RenderNode.cpp +++ b/libs/hwui/RenderNode.cpp @@ -87,7 +87,11 @@ RenderNode::RenderNode() RenderNode::~RenderNode() { deleteDisplayListData(); delete mStagingDisplayListData; - LayerRenderer::destroyLayerDeferred(mLayer); + if (mLayer) { + ALOGW("Memory Warning: Layer %p missed its detachment, held on to for far too long!", mLayer); + mLayer->postDecStrong(); + mLayer = 0; + } } void RenderNode::setStagingDisplayList(DisplayListData* data) { @@ -201,6 +205,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) { info.damageAccumulator->peekAtDirty(&dirty); if (!mLayer) { + Caches::getInstance().dumpMemoryUsage(); if (info.errorHandler) { std::string msg = "Unable to create layer for "; msg += getName(); diff --git a/libs/hwui/RenderNode.h b/libs/hwui/RenderNode.h index f32928301fc4..2ce7cb7f3034 100644 --- a/libs/hwui/RenderNode.h +++ b/libs/hwui/RenderNode.h @@ -101,7 +101,7 @@ public: kReplayFlag_ClipChildren = 0x1 }; - ANDROID_API static void outputLogBuffer(int fd); + static void outputLogBuffer(int fd); void debugDumpLayers(const char* prefix); ANDROID_API void setStagingDisplayList(DisplayListData* newData); diff --git a/libs/hwui/RenderState.cpp b/libs/hwui/RenderState.cpp index 86bd7dd00ccd..a8cf26f0d5da 100644 --- a/libs/hwui/RenderState.cpp +++ b/libs/hwui/RenderState.cpp @@ -16,15 +16,18 @@ #include "RenderState.h" #include "renderthread/CanvasContext.h" +#include "renderthread/EglManager.h" namespace android { namespace uirenderer { -RenderState::RenderState() - : mCaches(NULL) +RenderState::RenderState(renderthread::RenderThread& thread) + : mRenderThread(thread) + , mCaches(NULL) , mViewportWidth(0) , mViewportHeight(0) , mFramebuffer(0) { + mThreadId = pthread_self(); } RenderState::~RenderState() { @@ -39,7 +42,6 @@ void RenderState::onGLContextCreated() { void RenderState::onGLContextDestroyed() { /* - AutoMutex _lock(mLayerLock); size_t size = mActiveLayers.size(); if (CC_UNLIKELY(size != 0)) { ALOGE("Crashing, have %d contexts and %d layers at context destruction. isempty %d", @@ -146,5 +148,34 @@ void RenderState::debugOverdraw(bool enable, bool clear) { } } +void RenderState::requireGLContext() { + assertOnGLThread(); + mRenderThread.eglManager().requireGlContext(); +} + +void RenderState::assertOnGLThread() { + pthread_t curr = pthread_self(); + LOG_ALWAYS_FATAL_IF(!pthread_equal(mThreadId, curr), "Wrong thread!"); +} + + +class DecStrongTask : public renderthread::RenderTask { +public: + DecStrongTask(VirtualLightRefBase* object) : mObject(object) {} + + virtual void run() { + mObject->decStrong(0); + mObject = 0; + delete this; + } + +private: + VirtualLightRefBase* mObject; +}; + +void RenderState::postDecStrong(VirtualLightRefBase* object) { + mRenderThread.queue(new DecStrongTask(object)); +} + } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/RenderState.h b/libs/hwui/RenderState.h index cbe7cfc3db4e..afeef950d5cd 100644 --- a/libs/hwui/RenderState.h +++ b/libs/hwui/RenderState.h @@ -53,16 +53,10 @@ public: void debugOverdraw(bool enable, bool clear); void registerLayer(const Layer* layer) { - /* - AutoMutex _lock(mLayerLock); mActiveLayers.insert(layer); - */ } void unregisterLayer(const Layer* layer) { - /* - AutoMutex _lock(mLayerLock); mActiveLayers.erase(layer); - */ } void registerCanvasContext(renderthread::CanvasContext* context) { @@ -73,16 +67,24 @@ public: mRegisteredContexts.erase(context); } + void requireGLContext(); + + // TODO: This system is a little clunky feeling, this could use some + // more thinking... + void postDecStrong(VirtualLightRefBase* object); + private: friend class renderthread::RenderThread; friend class Caches; void interruptForFunctorInvoke(); void resumeFromFunctorInvoke(); + void assertOnGLThread(); - RenderState(); + RenderState(renderthread::RenderThread& thread); ~RenderState(); + renderthread::RenderThread& mRenderThread; Caches* mCaches; std::set<const Layer*> mActiveLayers; std::set<renderthread::CanvasContext*> mRegisteredContexts; @@ -90,7 +92,8 @@ private: GLsizei mViewportWidth; GLsizei mViewportHeight; GLuint mFramebuffer; - Mutex mLayerLock; + + pthread_t mThreadId; }; } /* namespace uirenderer */ diff --git a/libs/hwui/ResourceCache.cpp b/libs/hwui/ResourceCache.cpp index 8b553d1383d4..329d92f0be13 100644 --- a/libs/hwui/ResourceCache.cpp +++ b/libs/hwui/ResourceCache.cpp @@ -75,10 +75,6 @@ void ResourceCache::incrementRefcount(const Res_png_9patch* patchResource) { incrementRefcount((void*) patchResource, kNinePatch); } -void ResourceCache::incrementRefcount(Layer* layerResource) { - incrementRefcount((void*) layerResource, kLayer); -} - void ResourceCache::incrementRefcountLocked(void* resource, ResourceType resourceType) { ssize_t index = mCache->indexOfKey(resource); ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL; @@ -103,10 +99,6 @@ void ResourceCache::incrementRefcountLocked(const Res_png_9patch* patchResource) incrementRefcountLocked((void*) patchResource, kNinePatch); } -void ResourceCache::incrementRefcountLocked(Layer* layerResource) { - incrementRefcountLocked((void*) layerResource, kLayer); -} - void ResourceCache::decrementRefcount(void* resource) { Mutex::Autolock _l(mLock); decrementRefcountLocked(resource); @@ -126,10 +118,6 @@ void ResourceCache::decrementRefcount(const Res_png_9patch* patchResource) { decrementRefcount((void*) patchResource); } -void ResourceCache::decrementRefcount(Layer* layerResource) { - decrementRefcount((void*) layerResource); -} - void ResourceCache::decrementRefcountLocked(void* resource) { ssize_t index = mCache->indexOfKey(resource); ResourceReference* ref = index >= 0 ? mCache->valueAt(index) : NULL; @@ -157,10 +145,6 @@ void ResourceCache::decrementRefcountLocked(const Res_png_9patch* patchResource) decrementRefcountLocked((void*) patchResource); } -void ResourceCache::decrementRefcountLocked(Layer* layerResource) { - decrementRefcountLocked((void*) layerResource); -} - void ResourceCache::destructor(SkPath* resource) { Mutex::Autolock _l(mLock); destructorLocked(resource); @@ -274,7 +258,7 @@ void ResourceCache::deleteResourceReferenceLocked(const void* resource, Resource if (ref->recycled && ref->resourceType == kBitmap) { ((SkBitmap*) resource)->setPixels(NULL, NULL); } - if (ref->destroyed || ref->resourceType == kLayer) { + if (ref->destroyed) { switch (ref->resourceType) { case kBitmap: { SkBitmap* bitmap = (SkBitmap*) resource; @@ -305,11 +289,6 @@ void ResourceCache::deleteResourceReferenceLocked(const void* resource, Resource } } break; - case kLayer: { - Layer* layer = (Layer*) resource; - Caches::getInstance().deleteLayerDeferred(layer); - } - break; } } mCache->removeItem(resource); diff --git a/libs/hwui/ResourceCache.h b/libs/hwui/ResourceCache.h index 3864d4bf2a7d..8539d123b09a 100644 --- a/libs/hwui/ResourceCache.h +++ b/libs/hwui/ResourceCache.h @@ -36,8 +36,7 @@ namespace uirenderer { enum ResourceType { kBitmap, kNinePatch, - kPath, - kLayer + kPath }; class ResourceReference { @@ -69,22 +68,18 @@ public: void incrementRefcount(const SkPath* resource); void incrementRefcount(const SkBitmap* resource); void incrementRefcount(const Res_png_9patch* resource); - void incrementRefcount(Layer* resource); void incrementRefcountLocked(const SkPath* resource); void incrementRefcountLocked(const SkBitmap* resource); void incrementRefcountLocked(const Res_png_9patch* resource); - void incrementRefcountLocked(Layer* resource); void decrementRefcount(const SkBitmap* resource); void decrementRefcount(const SkPath* resource); void decrementRefcount(const Res_png_9patch* resource); - void decrementRefcount(Layer* resource); void decrementRefcountLocked(const SkBitmap* resource); void decrementRefcountLocked(const SkPath* resource); void decrementRefcountLocked(const Res_png_9patch* resource); - void decrementRefcountLocked(Layer* resource); void destructor(SkPath* resource); void destructor(const SkBitmap* resource); diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 9d2ae8b6d8ad..b499dd086312 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -236,6 +236,8 @@ void CanvasContext::draw() { if (status & DrawGlInfo::kStatusDrew) { swapBuffers(); + } else { + mEglManager.cancelFrame(); } profiler().finishFrame(); diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp index e37aafcd63fa..9bd6f41a9614 100644 --- a/libs/hwui/renderthread/EglManager.cpp +++ b/libs/hwui/renderthread/EglManager.cpp @@ -73,7 +73,8 @@ EglManager::EglManager(RenderThread& thread) , mAllowPreserveBuffer(load_dirty_regions_property()) , mCurrentSurface(EGL_NO_SURFACE) , mAtlasMap(NULL) - , mAtlasMapSize(0) { + , mAtlasMapSize(0) + , mInFrame(false) { mCanSetPreserveBuffer = mAllowPreserveBuffer; ALOGD("Use EGL_SWAP_BEHAVIOR_PRESERVED: %s", mAllowPreserveBuffer ? "true" : "false"); } @@ -105,10 +106,12 @@ bool EglManager::hasEglContext() { void EglManager::requireGlContext() { LOG_ALWAYS_FATAL_IF(mEglDisplay == EGL_NO_DISPLAY, "No EGL context"); - // We can't be certain about the state of the current surface (whether - // or not it is destroyed, for example), so err on the side of using - // the pbuffer surface which we fully control - usePBufferSurface(); + if (!mInFrame) { + // We can't be certain about the state of the current surface (whether + // or not it is destroyed, for example), so err on the side of using + // the pbuffer surface which we fully control + usePBufferSurface(); + } } void EglManager::loadConfig() { @@ -251,9 +254,11 @@ void EglManager::beginFrame(EGLSurface surface, EGLint* width, EGLint* height) { eglQuerySurface(mEglDisplay, surface, EGL_HEIGHT, height); } eglBeginFrame(mEglDisplay, surface); + mInFrame = true; } bool EglManager::swapBuffers(EGLSurface surface) { + mInFrame = false; eglSwapBuffers(mEglDisplay, surface); EGLint err = eglGetError(); if (CC_LIKELY(err == EGL_SUCCESS)) { @@ -272,6 +277,10 @@ bool EglManager::swapBuffers(EGLSurface surface) { return false; } +void EglManager::cancelFrame() { + mInFrame = false; +} + bool EglManager::setPreserveBuffer(EGLSurface surface, bool preserve) { if (CC_UNLIKELY(!mAllowPreserveBuffer)) return false; diff --git a/libs/hwui/renderthread/EglManager.h b/libs/hwui/renderthread/EglManager.h index ae03ea1fc3b8..e12db3acbe2f 100644 --- a/libs/hwui/renderthread/EglManager.h +++ b/libs/hwui/renderthread/EglManager.h @@ -48,6 +48,7 @@ public: bool makeCurrent(EGLSurface surface); void beginFrame(EGLSurface surface, EGLint* width, EGLint* height); bool swapBuffers(EGLSurface surface); + void cancelFrame(); // Returns true iff the surface is now preserving buffers. bool setPreserveBuffer(EGLSurface surface, bool preserve); @@ -80,6 +81,12 @@ private: sp<GraphicBuffer> mAtlasBuffer; int64_t* mAtlasMap; size_t mAtlasMapSize; + + // Whether or not we are in the middle of drawing a frame. This is used + // to avoid switching surfaces mid-frame if requireGlContext() is called + // TODO: Need to be better about surface/context management so that this isn't + // necessary + bool mInFrame; }; } /* namespace renderthread */ diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp index 8f99b4ed90c6..5d55ea62af1f 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -235,12 +235,7 @@ void RenderProxy::invokeFunctor(Functor* functor, bool waitForCompletion) { // waitForCompletion = true is expected to be fairly rare and only // happen in destruction. Thus it should be fine to temporarily // create a Mutex - Mutex mutex; - Condition condition; - SignalingRenderTask syncTask(task, &mutex, &condition); - AutoMutex _lock(mutex); - thread.queue(&syncTask); - condition.wait(mutex); + staticPostAndWait(task); } else { thread.queue(task); } @@ -258,17 +253,6 @@ void RenderProxy::runWithGlContext(RenderTask* gltask) { postAndWait(task); } -CREATE_BRIDGE1(destroyLayer, Layer* layer) { - LayerRenderer::destroyLayer(args->layer); - return NULL; -} - -void RenderProxy::enqueueDestroyLayer(Layer* layer) { - SETUP_TASK(destroyLayer); - args->layer = layer; - RenderThread::getInstance().queue(task); -} - CREATE_BRIDGE2(createTextureLayer, RenderThread* thread, CanvasContext* context) { Layer* layer = args->context->createTextureLayer(); if (!layer) return 0; @@ -400,6 +384,17 @@ void RenderProxy::dumpProfileInfo(int fd) { postAndWait(task); } +CREATE_BRIDGE1(outputLogBuffer, int fd) { + RenderNode::outputLogBuffer(args->fd); + return NULL; +} + +void RenderProxy::outputLogBuffer(int fd) { + SETUP_TASK(outputLogBuffer); + args->fd = fd; + staticPostAndWait(task); +} + CREATE_BRIDGE4(setTextureAtlas, RenderThread* thread, GraphicBuffer* buffer, int64_t* map, size_t size) { CanvasContext::setTextureAtlas(*args->thread, args->buffer, args->map, args->size); args->buffer->decStrong(0); @@ -430,6 +425,19 @@ void* RenderProxy::postAndWait(MethodInvokeRenderTask* task) { return retval; } +void* RenderProxy::staticPostAndWait(MethodInvokeRenderTask* task) { + RenderThread& thread = RenderThread::getInstance(); + void* retval; + task->setReturnPtr(&retval); + Mutex mutex; + Condition condition; + SignalingRenderTask syncTask(task, &mutex, &condition); + AutoMutex _lock(mutex); + thread.queue(&syncTask); + condition.wait(mutex); + return retval; +} + } /* namespace renderthread */ } /* namespace uirenderer */ } /* namespace android */ diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h index dddf0c746249..4989b1492838 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -81,7 +81,6 @@ public: ANDROID_API void runWithGlContext(RenderTask* task); - static void enqueueDestroyLayer(Layer* layer); ANDROID_API DeferredLayerUpdater* createTextureLayer(); ANDROID_API void buildLayer(RenderNode* node); ANDROID_API bool copyLayerInto(DeferredLayerUpdater* layer, SkBitmap* bitmap); @@ -97,6 +96,7 @@ public: ANDROID_API void notifyFramePending(); ANDROID_API void dumpProfileInfo(int fd); + ANDROID_API static void outputLogBuffer(int fd); ANDROID_API void setTextureAtlas(const sp<GraphicBuffer>& buffer, int64_t* map, size_t size); @@ -114,6 +114,8 @@ private: void post(RenderTask* task); void* postAndWait(MethodInvokeRenderTask* task); + static void* staticPostAndWait(MethodInvokeRenderTask* task); + // Friend class to help with bridging friend class RenderProxyBridge; }; diff --git a/libs/hwui/renderthread/RenderThread.cpp b/libs/hwui/renderthread/RenderThread.cpp index 403e1644bc7b..f887103e28ae 100644 --- a/libs/hwui/renderthread/RenderThread.cpp +++ b/libs/hwui/renderthread/RenderThread.cpp @@ -168,7 +168,7 @@ void RenderThread::initializeDisplayEventReceiver() { void RenderThread::initThreadLocals() { initializeDisplayEventReceiver(); mEglManager = new EglManager(*this); - mRenderState = new RenderState(); + mRenderState = new RenderState(*this); } int RenderThread::displayEventReceiverCallback(int fd, int events, void* data) { |