Merge "Layer changes" into lmp-mr1-dev

This commit is contained in:
John Reck
2014-10-31 22:55:46 +00:00
committed by Android (Google) Code Review
26 changed files with 163 additions and 188 deletions

View File

@ -43,6 +43,7 @@
#include <RenderNode.h>
#include <CanvasProperty.h>
#include <Paint.h>
#include <renderthread/RenderProxy.h>
#include "MinikinUtils.h"
@ -861,7 +862,7 @@ static void
android_app_ActivityThread_dumpGraphics(JNIEnv* env, jobject clazz, jobject javaFileDescriptor) {
#ifdef USE_OPENGL_RENDERER
int fd = jniGetFDFromFileDescriptor(env, javaFileDescriptor);
android::uirenderer::RenderNode::outputLogBuffer(fd);
android::uirenderer::renderthread::RenderProxy::outputLogBuffer(fd);
#endif // USE_OPENGL_RENDERER
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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) {

View File

@ -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);
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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,
@ -279,6 +279,12 @@ public:
void flush();
void render(const OpenGLRenderer& rootRenderer);
/**
* Posts a decStrong call to the appropriate thread.
* Thread-safe.
*/
void postDecStrong();
/**
* Bounds of the layer.
*/

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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

View File

@ -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();

View File

@ -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);

View File

@ -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 */

View File

@ -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 */

View File

@ -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);

View File

@ -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);

View File

@ -236,6 +236,8 @@ void CanvasContext::draw() {
if (status & DrawGlInfo::kStatusDrew) {
swapBuffers();
} else {
mEglManager.cancelFrame();
}
profiler().finishFrame();

View File

@ -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;

View File

@ -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 */

View File

@ -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 */

View File

@ -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;
};

View File

@ -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) {