Merge "Discard framebuffer rendering queues when discarding layers Bug #5581817" into ics-mr1

This commit is contained in:
Mathias Agopian
2011-11-14 00:52:09 -08:00
committed by Android (Google) Code Review
11 changed files with 80 additions and 5 deletions

View File

@ -154,6 +154,7 @@ class GLES20Canvas extends HardwareCanvas {
static native void nSetTextureLayerTransform(int layerId, int matrix);
static native void nDestroyLayer(int layerId);
static native void nDestroyLayerDeferred(int layerId);
static native void nFlushLayer(int layerId);
static native boolean nCopyLayer(int layerId, int bitmap);
///////////////////////////////////////////////////////////////////////////

View File

@ -60,6 +60,13 @@ abstract class GLES20Layer extends HardwareLayer {
}
mLayer = 0;
}
@Override
void flush() {
if (mLayer != 0) {
GLES20Canvas.nFlushLayer(mLayer);
}
}
static class Finalizer {
private int mLayerId;

View File

@ -115,6 +115,11 @@ abstract class HardwareLayer {
*/
abstract void destroy();
/**
* Flush the render queue associated with this layer.
*/
abstract void flush();
/**
* This must be invoked before drawing onto this layer.
* @param currentCanvas

View File

@ -10146,6 +10146,12 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
break;
}
}
void flushLayer() {
if (mLayerType == LAYER_TYPE_HARDWARE && mHardwareLayer != null) {
mHardwareLayer.flush();
}
}
/**
* <p>Returns a hardware layer that can be used to draw this view again
@ -10158,6 +10164,9 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
!mAttachInfo.mHardwareRenderer.isEnabled()) {
return null;
}
if (!mAttachInfo.mHardwareRenderer.validate()) return null;
final int width = mRight - mLeft;
final int height = mBottom - mTop;
@ -10232,8 +10241,14 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
*/
boolean destroyLayer() {
if (mHardwareLayer != null) {
mHardwareLayer.destroy();
mHardwareLayer = null;
AttachInfo info = mAttachInfo;
if (info != null && info.mHardwareRenderer != null &&
info.mHardwareRenderer.isEnabled()) {
if (!info.mHardwareRenderer.validate()) {
mHardwareLayer.destroy();
mHardwareLayer = null;
}
}
return true;
}
return false;

View File

@ -2957,6 +2957,16 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
if (enabled != mDrawLayers) {
mDrawLayers = enabled;
invalidate(true);
AttachInfo info = mAttachInfo;
if (info != null && info.mHardwareRenderer != null &&
info.mHardwareRenderer.isEnabled()) {
if (!info.mHardwareRenderer.validate()) {
enabled = false;
}
} else {
enabled = false;
}
// We need to invalidate any child with a layer. For instance,
// if a child is backed by a hardware layer and we disable layers
@ -2968,6 +2978,7 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
for (int i = 0; i < mChildrenCount; i++) {
View child = mChildren[i];
if (child.mLayerType != LAYER_TYPE_NONE) {
if (!enabled) child.flushLayer();
child.invalidate(true);
}
}

View File

@ -718,6 +718,10 @@ static void android_view_GLES20Canvas_destroyLayerDeferred(JNIEnv* env,
LayerRenderer::destroyLayerDeferred(layer);
}
static void android_view_GLES20Canvas_flushLayer(JNIEnv* env, jobject clazz, Layer* layer) {
LayerRenderer::flushLayer(layer);
}
static void android_view_GLES20Canvas_drawLayer(JNIEnv* env, jobject clazz,
OpenGLRenderer* renderer, Layer* layer, jfloat x, jfloat y, SkPaint* paint) {
renderer->drawLayer(layer, x, y, paint);
@ -860,6 +864,7 @@ static JNINativeMethod gMethods[] = {
{ "nSetTextureLayerTransform", "(II)V", (void*) android_view_GLES20Canvas_setTextureLayerTransform },
{ "nDestroyLayer", "(I)V", (void*) android_view_GLES20Canvas_destroyLayer },
{ "nDestroyLayerDeferred", "(I)V", (void*) android_view_GLES20Canvas_destroyLayerDeferred },
{ "nFlushLayer", "(I)V", (void*) android_view_GLES20Canvas_flushLayer },
{ "nDrawLayer", "(IIFFI)V", (void*) android_view_GLES20Canvas_drawLayer },
{ "nCopyLayer", "(II)Z", (void*) android_view_GLES20Canvas_copyLayer },

View File

@ -38,7 +38,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
external/skia/src/ports \
external/skia/include/utils
LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER
LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DGL_GLEXT_PROTOTYPES
LOCAL_CFLAGS += -fvisibility=hidden
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
LOCAL_SHARED_LIBRARIES := libcutils libutils libGLESv2 libskia libui

View File

@ -66,6 +66,7 @@ public:
mHasNPot = hasExtension("GL_OES_texture_npot");
mHasFramebufferFetch = hasExtension("GL_NV_shader_framebuffer_fetch");
mHasDiscardFramebuffer = hasExtension("GL_EXT_discard_framebuffer");
const char* vendor = (const char*) glGetString(GL_VENDOR);
EXT_LOGD("Vendor: %s", vendor);
@ -80,6 +81,7 @@ public:
inline bool hasNPot() const { return mHasNPot; }
inline bool hasFramebufferFetch() const { return mHasFramebufferFetch; }
inline bool needsHighpTexCoords() const { return mNeedsHighpTexCoords; }
inline bool hasDiscardFramebuffer() const { return mHasDiscardFramebuffer; }
bool hasExtension(const char* extension) const {
const String8 s(extension);
@ -98,6 +100,7 @@ private:
bool mHasNPot;
bool mNeedsHighpTexCoords;
bool mHasFramebufferFetch;
bool mHasDiscardFramebuffer;
}; // class Extensions
}; // namespace uirenderer

View File

@ -305,8 +305,10 @@ void LayerRenderer::destroyLayer(Layer* layer) {
LAYER_RENDERER_LOGD("Recycling layer, %dx%d fbo = %d",
layer->getWidth(), layer->getHeight(), layer->getFbo());
if (layer->getFbo()) {
Caches::getInstance().fboCache.put(layer->getFbo());
GLuint fbo = layer->getFbo();
if (fbo) {
flushLayer(layer);
Caches::getInstance().fboCache.put(fbo);
}
if (!Caches::getInstance().layerCache.put(layer)) {
@ -331,6 +333,26 @@ void LayerRenderer::destroyLayerDeferred(Layer* layer) {
}
}
void LayerRenderer::flushLayer(Layer* layer) {
#ifdef GL_EXT_discard_framebuffer
GLuint fbo = layer->getFbo();
if (layer && fbo) {
// If possible, discard any enqued operations on deferred
// rendering architectures
if (Caches::getInstance().extensions.hasDiscardFramebuffer()) {
GLuint previousFbo;
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*) &previousFbo);
GLenum attachments = GL_COLOR_ATTACHMENT0;
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
glDiscardFramebufferEXT(GL_FRAMEBUFFER, 1, &attachments);
glBindFramebuffer(GL_FRAMEBUFFER, previousFbo);
}
}
#endif
}
bool LayerRenderer::copyLayer(Layer* layer, SkBitmap* bitmap) {
Caches& caches = Caches::getInstance();
if (layer && layer->isTextureLayer() && bitmap->width() <= caches.maxTextureSize &&

View File

@ -61,6 +61,7 @@ public:
bool isOpaque, GLenum renderTarget, float* transform);
ANDROID_API static void destroyLayer(Layer* layer);
ANDROID_API static void destroyLayerDeferred(Layer* layer);
ANDROID_API static void flushLayer(Layer* layer);
ANDROID_API static bool copyLayer(Layer* layer, SkBitmap* bitmap);
private:

View File

@ -611,6 +611,11 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) {
}
if (fboLayer) {
// Note: No need to use glDiscardFramebufferEXT() since we never
// create/compose layers that are not on screen with this
// code path
// See LayerRenderer::destroyLayer(Layer*)
// Detach the texture from the FBO
glBindFramebuffer(GL_FRAMEBUFFER, current->fbo);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);