Merge "Layer changes" into lmp-mr1-dev
This commit is contained in:
@ -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
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -236,6 +236,8 @@ void CanvasContext::draw() {
|
||||
|
||||
if (status & DrawGlInfo::kStatusDrew) {
|
||||
swapBuffers();
|
||||
} else {
|
||||
mEglManager.cancelFrame();
|
||||
}
|
||||
|
||||
profiler().finishFrame();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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) {
|
||||
|
Reference in New Issue
Block a user