* commit '8b946c055ddd90cf79cd407c9f68a013d5d24c2a': Defer layer rendering to avoid stalls Bug #7326824
This commit is contained in:
@ -1200,7 +1200,12 @@ public abstract class HardwareRenderer {
|
|||||||
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
|
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "prepareFrame");
|
||||||
|
try {
|
||||||
status = onPreDraw(dirty);
|
status = onPreDraw(dirty);
|
||||||
|
} finally {
|
||||||
|
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
|
||||||
|
}
|
||||||
saveCount = canvas.save();
|
saveCount = canvas.save();
|
||||||
callbacks.onHardwarePreDraw(canvas);
|
callbacks.onHardwarePreDraw(canvas);
|
||||||
|
|
||||||
|
@ -1434,7 +1434,7 @@ void DisplayListRenderer::setViewport(int width, int height) {
|
|||||||
mHeight = height;
|
mHeight = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
int DisplayListRenderer::prepareDirty(float left, float top,
|
status_t DisplayListRenderer::prepareDirty(float left, float top,
|
||||||
float right, float bottom, bool opaque) {
|
float right, float bottom, bool opaque) {
|
||||||
mSnapshot = new Snapshot(mFirstSnapshot,
|
mSnapshot = new Snapshot(mFirstSnapshot,
|
||||||
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
|
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
|
||||||
|
@ -550,7 +550,7 @@ public:
|
|||||||
virtual bool isDeferred();
|
virtual bool isDeferred();
|
||||||
|
|
||||||
virtual void setViewport(int width, int height);
|
virtual void setViewport(int width, int height);
|
||||||
virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
|
virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
|
||||||
virtual void finish();
|
virtual void finish();
|
||||||
|
|
||||||
virtual status_t callDrawGLFunction(Functor *functor, Rect& dirty);
|
virtual status_t callDrawGLFunction(Functor *functor, Rect& dirty);
|
||||||
|
@ -31,6 +31,7 @@ Layer::Layer(const uint32_t layerWidth, const uint32_t layerHeight) {
|
|||||||
meshIndices = NULL;
|
meshIndices = NULL;
|
||||||
meshElementCount = 0;
|
meshElementCount = 0;
|
||||||
cacheable = true;
|
cacheable = true;
|
||||||
|
dirty = false;
|
||||||
textureLayer = false;
|
textureLayer = false;
|
||||||
renderTarget = GL_TEXTURE_2D;
|
renderTarget = GL_TEXTURE_2D;
|
||||||
texture.width = layerWidth;
|
texture.width = layerWidth;
|
||||||
|
@ -162,6 +162,14 @@ struct Layer {
|
|||||||
this->cacheable = cacheable;
|
this->cacheable = cacheable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool isDirty() {
|
||||||
|
return dirty;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void setDirty(bool dirty) {
|
||||||
|
this->dirty = dirty;
|
||||||
|
}
|
||||||
|
|
||||||
inline bool isTextureLayer() {
|
inline bool isTextureLayer() {
|
||||||
return textureLayer;
|
return textureLayer;
|
||||||
}
|
}
|
||||||
@ -286,6 +294,12 @@ private:
|
|||||||
*/
|
*/
|
||||||
bool textureLayer;
|
bool textureLayer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When set to true, this layer is dirty and should be cleared
|
||||||
|
* before any rendering occurs.
|
||||||
|
*/
|
||||||
|
bool dirty;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates the render target.
|
* Indicates the render target.
|
||||||
*/
|
*/
|
||||||
|
@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include <ui/Rect.h>
|
#include <ui/Rect.h>
|
||||||
|
|
||||||
|
#include <private/hwui/DrawGlInfo.h>
|
||||||
|
|
||||||
#include "LayerCache.h"
|
#include "LayerCache.h"
|
||||||
#include "LayerRenderer.h"
|
#include "LayerRenderer.h"
|
||||||
#include "Matrix.h"
|
#include "Matrix.h"
|
||||||
@ -41,7 +43,8 @@ void LayerRenderer::setViewport(int width, int height) {
|
|||||||
initViewport(width, height);
|
initViewport(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
int LayerRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
|
status_t LayerRenderer::prepareDirty(float left, float top, float right, float bottom,
|
||||||
|
bool opaque) {
|
||||||
LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
|
LAYER_RENDERER_LOGD("Rendering into layer, fbo = %d", mLayer->getFbo());
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, mLayer->getFbo());
|
glBindFramebuffer(GL_FRAMEBUFFER, mLayer->getFbo());
|
||||||
@ -63,6 +66,20 @@ int LayerRenderer::prepareDirty(float left, float top, float right, float bottom
|
|||||||
return OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque);
|
return OpenGLRenderer::prepareDirty(dirty.left, dirty.top, dirty.right, dirty.bottom, opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t LayerRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
|
||||||
|
if (mLayer->isDirty()) {
|
||||||
|
getCaches().disableScissor();
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
|
||||||
|
getCaches().resetScissor();
|
||||||
|
mLayer->setDirty(false);
|
||||||
|
|
||||||
|
return DrawGlInfo::kStatusDone;
|
||||||
|
}
|
||||||
|
|
||||||
|
return OpenGLRenderer::clear(left, top, right, bottom, opaque);
|
||||||
|
}
|
||||||
|
|
||||||
void LayerRenderer::finish() {
|
void LayerRenderer::finish() {
|
||||||
OpenGLRenderer::finish();
|
OpenGLRenderer::finish();
|
||||||
|
|
||||||
@ -201,6 +218,7 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque
|
|||||||
layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
|
layer->setAlpha(255, SkXfermode::kSrcOver_Mode);
|
||||||
layer->setBlend(!isOpaque);
|
layer->setBlend(!isOpaque);
|
||||||
layer->setColorFilter(NULL);
|
layer->setColorFilter(NULL);
|
||||||
|
layer->setDirty(true);
|
||||||
layer->region.clear();
|
layer->region.clear();
|
||||||
|
|
||||||
GLuint previousFbo;
|
GLuint previousFbo;
|
||||||
@ -229,9 +247,6 @@ Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque
|
|||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
|
||||||
layer->getTexture(), 0);
|
layer->getTexture(), 0);
|
||||||
|
|
||||||
caches.disableScissor();
|
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
|
||||||
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
|
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
|
||||||
|
|
||||||
return layer;
|
return layer;
|
||||||
|
@ -48,7 +48,8 @@ public:
|
|||||||
virtual ~LayerRenderer();
|
virtual ~LayerRenderer();
|
||||||
|
|
||||||
virtual void setViewport(int width, int height);
|
virtual void setViewport(int width, int height);
|
||||||
virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
|
virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
|
||||||
|
virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
|
||||||
virtual void finish();
|
virtual void finish();
|
||||||
|
|
||||||
ANDROID_API static Layer* createTextureLayer(bool isOpaque);
|
ANDROID_API static Layer* createTextureLayer(bool isOpaque);
|
||||||
|
@ -165,11 +165,12 @@ void OpenGLRenderer::initViewport(int width, int height) {
|
|||||||
mFirstSnapshot->viewport.set(0, 0, width, height);
|
mFirstSnapshot->viewport.set(0, 0, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
int OpenGLRenderer::prepare(bool opaque) {
|
status_t OpenGLRenderer::prepare(bool opaque) {
|
||||||
return prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque);
|
return prepareDirty(0.0f, 0.0f, mWidth, mHeight, opaque);
|
||||||
}
|
}
|
||||||
|
|
||||||
int OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom, bool opaque) {
|
status_t OpenGLRenderer::prepareDirty(float left, float top, float right, float bottom,
|
||||||
|
bool opaque) {
|
||||||
mCaches.clearGarbage();
|
mCaches.clearGarbage();
|
||||||
|
|
||||||
mSnapshot = new Snapshot(mFirstSnapshot,
|
mSnapshot = new Snapshot(mFirstSnapshot,
|
||||||
@ -203,15 +204,18 @@ int OpenGLRenderer::prepareDirty(float left, float top, float right, float botto
|
|||||||
|
|
||||||
debugOverdraw(true, true);
|
debugOverdraw(true, true);
|
||||||
|
|
||||||
|
return clear(left, top, right, bottom, opaque);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t OpenGLRenderer::clear(float left, float top, float right, float bottom, bool opaque) {
|
||||||
if (!opaque) {
|
if (!opaque) {
|
||||||
mCaches.enableScissor();
|
mCaches.enableScissor();
|
||||||
mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
|
mCaches.setScissor(left, mSnapshot->height - bottom, right - left, bottom - top);
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
return DrawGlInfo::kStatusDrew;
|
return DrawGlInfo::kStatusDrew;
|
||||||
} else {
|
|
||||||
mCaches.resetScissor();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCaches.resetScissor();
|
||||||
return DrawGlInfo::kStatusDone;
|
return DrawGlInfo::kStatusDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -743,6 +747,7 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto
|
|||||||
bounds.getWidth() / float(layer->getWidth()), 0.0f);
|
bounds.getWidth() / float(layer->getWidth()), 0.0f);
|
||||||
layer->setColorFilter(mColorFilter);
|
layer->setColorFilter(mColorFilter);
|
||||||
layer->setBlend(true);
|
layer->setBlend(true);
|
||||||
|
layer->setDirty(false);
|
||||||
|
|
||||||
// Save the layer in the snapshot
|
// Save the layer in the snapshot
|
||||||
mSnapshot->flags |= Snapshot::kFlagIsLayer;
|
mSnapshot->flags |= Snapshot::kFlagIsLayer;
|
||||||
|
@ -94,7 +94,7 @@ public:
|
|||||||
* and will not be cleared. If false, the target surface
|
* and will not be cleared. If false, the target surface
|
||||||
* will be cleared
|
* will be cleared
|
||||||
*/
|
*/
|
||||||
ANDROID_API int prepare(bool opaque);
|
ANDROID_API status_t prepare(bool opaque);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prepares the renderer to draw a frame. This method must be invoked
|
* Prepares the renderer to draw a frame. This method must be invoked
|
||||||
@ -110,7 +110,7 @@ public:
|
|||||||
* and will not be cleared. If false, the target surface
|
* and will not be cleared. If false, the target surface
|
||||||
* will be cleared in the specified dirty rectangle
|
* will be cleared in the specified dirty rectangle
|
||||||
*/
|
*/
|
||||||
virtual int prepareDirty(float left, float top, float right, float bottom, bool opaque);
|
virtual status_t prepareDirty(float left, float top, float right, float bottom, bool opaque);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates the end of a frame. This method must be invoked whenever
|
* Indicates the end of a frame. This method must be invoked whenever
|
||||||
@ -269,6 +269,11 @@ protected:
|
|||||||
*/
|
*/
|
||||||
void initViewport(int width, int height);
|
void initViewport(int width, int height);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears the underlying surface if needed.
|
||||||
|
*/
|
||||||
|
virtual status_t clear(float left, float top, float right, float bottom, bool opaque);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this method after updating a layer during a drawing pass.
|
* Call this method after updating a layer during a drawing pass.
|
||||||
*/
|
*/
|
||||||
@ -355,6 +360,10 @@ protected:
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Caches& getCaches() {
|
||||||
|
return mCaches;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* Ensures the state of the renderer is the same as the state of
|
* Ensures the state of the renderer is the same as the state of
|
||||||
|
Reference in New Issue
Block a user