summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorRomain Guy <romainguy@google.com>2012-09-21 00:39:43 -0700
committerRomain Guy <romainguy@google.com>2012-09-21 00:39:43 -0700
commit11cb642756093a4af901b1525375b1eb2b5c3e2b (patch)
treeb412ad763bb1cc240c65c7545a208e4e709c0b30 /libs
parent3e87eafc7d1aef95801f1758bb78da8b2f960a75 (diff)
downloadframeworks_base-11cb642756093a4af901b1525375b1eb2b5c3e2b.zip
frameworks_base-11cb642756093a4af901b1525375b1eb2b5c3e2b.tar.gz
frameworks_base-11cb642756093a4af901b1525375b1eb2b5c3e2b.tar.bz2
Update layers in a single batch at the beginning of a frame
Bug #7186819 Change-Id: Ice5926dfedfb3be3a3064e65008dafa2852407da
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/LayerRenderer.cpp4
-rw-r--r--libs/hwui/LayerRenderer.h10
-rw-r--r--libs/hwui/OpenGLRenderer.cpp136
-rw-r--r--libs/hwui/OpenGLRenderer.h15
4 files changed, 121 insertions, 44 deletions
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 5d59a4c..bb004c0 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -78,6 +78,10 @@ GLint LayerRenderer::getTargetFbo() {
return mLayer->getFbo();
}
+bool LayerRenderer::suppressErrorChecks() {
+ return true;
+}
+
///////////////////////////////////////////////////////////////////////////////
// Dirty region tracking
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 8d42f7f..392f863 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -51,10 +51,6 @@ public:
virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
virtual void finish();
- virtual bool hasLayer();
- virtual Region* getRegion();
- virtual GLint getTargetFbo();
-
ANDROID_API static Layer* createTextureLayer(bool isOpaque);
ANDROID_API static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false);
ANDROID_API static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
@@ -64,6 +60,12 @@ public:
ANDROID_API static void destroyLayerDeferred(Layer* layer);
ANDROID_API static bool copyLayer(Layer* layer, SkBitmap* bitmap);
+protected:
+ virtual bool hasLayer();
+ virtual Region* getRegion();
+ virtual GLint getTargetFbo();
+ virtual bool suppressErrorChecks();
+
private:
void generateMesh();
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index da0900a..c475f20 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -177,6 +177,8 @@ int OpenGLRenderer::prepareDirty(float left, float top, float right, float botto
mSnapshot->setClip(left, top, right, bottom);
mDirtyClip = opaque;
+ updateLayers();
+
// If we know that we are going to redraw the entire framebuffer,
// perform a discard to let the driver know we don't need to preserve
// the back buffer for this frame.
@@ -230,33 +232,36 @@ void OpenGLRenderer::endTiling() {
void OpenGLRenderer::finish() {
endTiling();
+ if (!suppressErrorChecks()) {
#if DEBUG_OPENGL
- GLenum status = GL_NO_ERROR;
- while ((status = glGetError()) != GL_NO_ERROR) {
- ALOGD("GL error from OpenGLRenderer: 0x%x", status);
- switch (status) {
- case GL_INVALID_ENUM:
- ALOGE(" GL_INVALID_ENUM");
- break;
- case GL_INVALID_VALUE:
- ALOGE(" GL_INVALID_VALUE");
- break;
- case GL_INVALID_OPERATION:
- ALOGE(" GL_INVALID_OPERATION");
- break;
- case GL_OUT_OF_MEMORY:
- ALOGE(" Out of memory!");
- break;
+ GLenum status = GL_NO_ERROR;
+ while ((status = glGetError()) != GL_NO_ERROR) {
+ ALOGD("GL error from OpenGLRenderer: 0x%x", status);
+ switch (status) {
+ case GL_INVALID_ENUM:
+ ALOGE(" GL_INVALID_ENUM");
+ break;
+ case GL_INVALID_VALUE:
+ ALOGE(" GL_INVALID_VALUE");
+ break;
+ case GL_INVALID_OPERATION:
+ ALOGE(" GL_INVALID_OPERATION");
+ break;
+ case GL_OUT_OF_MEMORY:
+ ALOGE(" Out of memory!");
+ break;
+ }
}
- }
#endif
+
#if DEBUG_MEMORY_USAGE
- mCaches.dumpMemoryUsage();
-#else
- if (mCaches.getDebugLevel() & kDebugMemory) {
mCaches.dumpMemoryUsage();
- }
+#else
+ if (mCaches.getDebugLevel() & kDebugMemory) {
+ mCaches.dumpMemoryUsage();
+ }
#endif
+ }
}
void OpenGLRenderer::interrupt() {
@@ -393,6 +398,75 @@ status_t OpenGLRenderer::callDrawGLFunction(Functor* functor, Rect& dirty) {
}
///////////////////////////////////////////////////////////////////////////////
+// Layers
+///////////////////////////////////////////////////////////////////////////////
+
+bool OpenGLRenderer::updateLayer(Layer* layer, bool inFrame) {
+ if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) {
+ OpenGLRenderer* renderer = layer->renderer;
+ Rect& dirty = layer->dirtyRect;
+
+ if (inFrame) endTiling();
+
+ renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
+ renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend());
+ renderer->drawDisplayList(layer->displayList, dirty, DisplayList::kReplayFlag_ClipChildren);
+ renderer->finish();
+
+ if (inFrame) {
+ resumeAfterLayer();
+ startTiling(mSnapshot);
+ }
+
+ dirty.setEmpty();
+ layer->deferredUpdateScheduled = false;
+ layer->renderer = NULL;
+ layer->displayList = NULL;
+
+ return true;
+ }
+
+ return false;
+}
+
+void OpenGLRenderer::updateLayers() {
+ int count = mLayerUpdates.size();
+ if (count > 0) {
+ startMark("Layer Updates");
+
+ // Note: it is very important to update the layers in reverse order
+ for (int i = count - 1; i >= 0; i--) {
+ Layer* layer = mLayerUpdates.itemAt(i);
+ updateLayer(layer, false);
+ mCaches.resourceCache.decrementRefcount(layer);
+ }
+ mLayerUpdates.clear();
+
+ glBindFramebuffer(GL_FRAMEBUFFER, getTargetFbo());
+ endMark();
+ }
+}
+
+void OpenGLRenderer::pushLayerUpdate(Layer* layer) {
+ if (layer) {
+ mLayerUpdates.push_back(layer);
+ mCaches.resourceCache.incrementRefcount(layer);
+ }
+}
+
+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();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
// State management
///////////////////////////////////////////////////////////////////////////////
@@ -2629,25 +2703,7 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* pain
}
bool debugLayerUpdate = false;
- if (layer->deferredUpdateScheduled && layer->renderer && layer->displayList) {
- OpenGLRenderer* renderer = layer->renderer;
- Rect& dirty = layer->dirtyRect;
-
- endTiling();
-
- renderer->setViewport(layer->layer.getWidth(), layer->layer.getHeight());
- renderer->prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, !layer->isBlend());
- renderer->drawDisplayList(layer->displayList, dirty, DisplayList::kReplayFlag_ClipChildren);
- renderer->finish();
-
- resumeAfterLayer();
- startTiling(mSnapshot);
-
- dirty.setEmpty();
- layer->deferredUpdateScheduled = false;
- layer->renderer = NULL;
- layer->displayList = NULL;
-
+ if (updateLayer(layer, true)) {
debugLayerUpdate = mCaches.debugLayersUpdates;
}
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 4bbdde1..3e34336 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -132,6 +132,9 @@ public:
ANDROID_API void attachFunctor(Functor* functor);
virtual status_t callDrawGLFunction(Functor* functor, Rect& dirty);
+ ANDROID_API void pushLayerUpdate(Layer* layer);
+ ANDROID_API void clearLayerUpdates();
+
ANDROID_API int getSaveCount() const;
virtual int save(int flags);
virtual void restore();
@@ -339,6 +342,13 @@ protected:
return resultMode;
}
+ /**
+ * Set to true to suppress error checks at the end of a frame.
+ */
+ virtual bool suppressErrorChecks() {
+ return false;
+ }
+
private:
/**
* Ensures the state of the renderer is the same as the state of
@@ -720,6 +730,9 @@ private:
void finishDrawTexture();
void accountForClear(SkXfermode::Mode mode);
+ bool updateLayer(Layer* layer, bool inFrame);
+ void updateLayers();
+
/**
* Renders the specified region as a series of rectangles. This method
* is used for debugging only.
@@ -780,6 +793,8 @@ private:
Vector<Rect*> mLayers;
// List of functors to invoke after a frame is drawn
SortedVector<Functor*> mFunctors;
+ // List of layers to update at the beginning of a frame
+ Vector<Layer*> mLayerUpdates;
// Indentity matrix
const mat4 mIdentity;