summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libs/hwui/Layer.cpp45
-rw-r--r--libs/hwui/Layer.h31
-rw-r--r--libs/hwui/LayerCache.cpp25
-rw-r--r--libs/hwui/LayerCache.h15
-rw-r--r--libs/hwui/LayerRenderer.cpp2
-rw-r--r--libs/hwui/OpenGLRenderer.cpp9
-rw-r--r--tests/HwAccelerationTest/res/layout/view_layers_5.xml25
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java65
8 files changed, 162 insertions, 55 deletions
diff --git a/libs/hwui/Layer.cpp b/libs/hwui/Layer.cpp
index 1d85b70..79dbfb0 100644
--- a/libs/hwui/Layer.cpp
+++ b/libs/hwui/Layer.cpp
@@ -54,6 +54,51 @@ Layer::~Layer() {
deleteTexture();
}
+uint32_t Layer::computeIdealWidth(uint32_t layerWidth) {
+ return uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE);
+}
+
+uint32_t Layer::computeIdealHeight(uint32_t layerHeight) {
+ return uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE);
+}
+
+bool Layer::resize(const uint32_t width, const uint32_t height) {
+ uint32_t desiredWidth = computeIdealWidth(width);
+ uint32_t desiredHeight = computeIdealWidth(height);
+
+ if (desiredWidth <= getWidth() && desiredHeight <= getHeight()) {
+ return true;
+ }
+
+ uint32_t oldWidth = getWidth();
+ uint32_t oldHeight = getHeight();
+
+ setSize(desiredWidth, desiredHeight);
+
+ if (fbo) {
+ Caches::getInstance().activeTexture(0);
+ bindTexture();
+ allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
+
+ if (glGetError() != GL_NO_ERROR) {
+ setSize(oldWidth, oldHeight);
+ return false;
+ }
+ }
+
+ if (stencil) {
+ bindStencilRenderBuffer();
+ allocateStencilRenderBuffer();
+
+ if (glGetError() != GL_NO_ERROR) {
+ setSize(oldWidth, oldHeight);
+ return false;
+ }
+ }
+
+ return true;
+}
+
void Layer::removeFbo(bool flush) {
if (stencil) {
// TODO: recycle & cache instead of simply deleting
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 9ef4894..a551b3f 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -48,6 +48,9 @@ struct Layer {
Layer(const uint32_t layerWidth, const uint32_t layerHeight);
~Layer();
+ static uint32_t computeIdealWidth(uint32_t layerWidth);
+ static uint32_t computeIdealHeight(uint32_t layerHeight);
+
/**
* Calling this method will remove (either by recycling or
* destroying) the associated FBO, if present, and any render
@@ -91,6 +94,17 @@ struct Layer {
return texture.height;
}
+ /**
+ * Resize the layer and its texture if needed.
+ *
+ * @param width The new width of the layer
+ * @param height The new height of the layer
+ *
+ * @return True if the layer was resized or nothing happened, false if
+ * a failure occurred during the resizing operation
+ */
+ bool resize(const uint32_t width, const uint32_t height);
+
void setSize(uint32_t width, uint32_t height) {
texture.width = width;
texture.height = height;
@@ -203,6 +217,12 @@ struct Layer {
}
}
+ inline void bindStencilRenderBuffer() {
+ if (stencil) {
+ glBindRenderbuffer(GL_RENDERBUFFER, stencil);
+ }
+ }
+
inline void generateTexture() {
if (!texture.id) {
glGenTextures(1, &texture.id);
@@ -229,7 +249,16 @@ struct Layer {
#if DEBUG_LAYERS
ALOGD(" Allocate layer: %dx%d", getWidth(), getHeight());
#endif
- glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL);
+ if (texture.id) {
+ glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0,
+ format, storage, NULL);
+ }
+ }
+
+ inline void allocateStencilRenderBuffer() {
+ if (stencil) {
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, getWidth(), getHeight());
+ }
}
inline mat4& getTexTransform() {
diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp
index cfc5b04..4278464 100644
--- a/libs/hwui/LayerCache.cpp
+++ b/libs/hwui/LayerCache.cpp
@@ -136,31 +136,6 @@ void LayerCache::dump() {
}
}
-bool LayerCache::resize(Layer* layer, const uint32_t width, const uint32_t height) {
- // TODO: We should be smarter and see if we have a texture of the appropriate
- // size already in the cache, and reuse it instead of creating a new one
-
- LayerEntry entry(width, height);
- if (entry.mWidth <= layer->getWidth() && entry.mHeight <= layer->getHeight()) {
- return true;
- }
-
- uint32_t oldWidth = layer->getWidth();
- uint32_t oldHeight = layer->getHeight();
-
- Caches::getInstance().activeTexture(0);
- layer->bindTexture();
- layer->setSize(entry.mWidth, entry.mHeight);
- layer->allocateTexture(GL_RGBA, GL_UNSIGNED_BYTE);
-
- if (glGetError() != GL_NO_ERROR) {
- layer->setSize(oldWidth, oldHeight);
- return false;
- }
-
- return true;
-}
-
bool LayerCache::put(Layer* layer) {
if (!layer->isCacheable()) return false;
diff --git a/libs/hwui/LayerCache.h b/libs/hwui/LayerCache.h
index fc2cd91..7720b42 100644
--- a/libs/hwui/LayerCache.h
+++ b/libs/hwui/LayerCache.h
@@ -72,17 +72,6 @@ public:
* Clears the cache. This causes all layers to be deleted.
*/
void clear();
- /**
- * Resize the specified layer if needed.
- *
- * @param layer The layer to resize
- * @param width The new width of the layer
- * @param height The new height of the layer
- *
- * @return True if the layer was resized or nothing happened, false if
- * a failure occurred during the resizing operation
- */
- bool resize(Layer* layer, const uint32_t width, const uint32_t height);
/**
* Sets the maximum size of the cache in bytes.
@@ -108,8 +97,8 @@ public:
}
LayerEntry(const uint32_t layerWidth, const uint32_t layerHeight): mLayer(NULL) {
- mWidth = uint32_t(ceilf(layerWidth / float(LAYER_SIZE)) * LAYER_SIZE);
- mHeight = uint32_t(ceilf(layerHeight / float(LAYER_SIZE)) * LAYER_SIZE);
+ mWidth = Layer::computeIdealWidth(layerWidth);
+ mHeight = Layer::computeIdealHeight(layerHeight);
}
LayerEntry(Layer* layer):
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index ba59bb3..61bedbb 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -264,7 +264,7 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) {
if (layer) {
LAYER_RENDERER_LOGD("Resizing layer fbo = %d to %dx%d", layer->getFbo(), width, height);
- if (Caches::getInstance().layerCache.resize(layer, width, height)) {
+ if (layer->resize(width, height)) {
layer->layer.set(0.0f, 0.0f, width, height);
layer->texCoords.set(0.0f, height / float(layer->getHeight()),
width / float(layer->getWidth()), 0.0f);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index be34b40..f55bc9d 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -1248,11 +1248,12 @@ void OpenGLRenderer::attachStencilBufferToLayer(Layer* layer) {
// TODO: See Layer::removeFbo(). The stencil renderbuffer should be cached
GLuint buffer;
glGenRenderbuffers(1, &buffer);
- glBindRenderbuffer(GL_RENDERBUFFER, buffer);
- glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8,
- layer->getWidth(), layer->getHeight());
- glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer);
+
layer->setStencilRenderBuffer(buffer);
+ layer->bindStencilRenderBuffer();
+ layer->allocateStencilRenderBuffer();
+
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, buffer);
}
}
diff --git a/tests/HwAccelerationTest/res/layout/view_layers_5.xml b/tests/HwAccelerationTest/res/layout/view_layers_5.xml
index 36cf8c9..5baf583 100644
--- a/tests/HwAccelerationTest/res/layout/view_layers_5.xml
+++ b/tests/HwAccelerationTest/res/layout/view_layers_5.xml
@@ -48,13 +48,32 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Grow layer" />
+
+ <Button
+ android:onClick="enableClip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="Circle clip" />
+
+ <Button
+ android:onClick="disableClip"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="No clip" />
</LinearLayout>
- <ListView
- android:id="@+id/list1"
+ <view class="com.android.test.hwui.ViewLayersActivity5$ClipFrameLayout"
+ android:id="@+id/container"
android:layout_width="0dip"
android:layout_height="match_parent"
- android:layout_weight="1" />
+ android:layout_weight="1">
+
+ <ListView
+ android:id="@+id/list1"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+
+ </view>
</LinearLayout>
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
index 2664977..cbbb7ef 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/ViewLayersActivity5.java
@@ -19,14 +19,18 @@ package com.android.test.hwui;
import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
+import android.graphics.Canvas;
import android.graphics.Paint;
+import android.graphics.Path;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.os.Bundle;
+import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
+import android.widget.FrameLayout;
import android.widget.ListView;
import android.widget.TextView;
@@ -37,30 +41,75 @@ public class ViewLayersActivity5 extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
+
+ init();
+
setContentView(R.layout.view_layers_5);
+ setupList(R.id.list1);
+ }
+
+ public static class ClipFrameLayout extends FrameLayout {
+ private final Path mClipPath = new Path();
+ private boolean mClipEnabled;
+
+ public ClipFrameLayout(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ }
+
+ public ClipFrameLayout(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ }
+
+ public boolean isClipEnabled() {
+ return mClipEnabled;
+ }
+ public void setClipEnabled(boolean clipEnabled) {
+ mClipEnabled = clipEnabled;
+ invalidate();
+ }
+
+ @Override
+ protected void dispatchDraw(Canvas canvas) {
+ if (mClipEnabled) {
+ mClipPath.reset();
+ mClipPath.addCircle(getWidth() / 2.0f, getHeight() / 2.0f,
+ Math.min(getWidth(), getHeight()) / 3.0f, Path.Direction.CW);
+
+ canvas.clipPath(mClipPath);
+ }
+ super.dispatchDraw(canvas);
+ }
+ }
+
+ private void init() {
mPaint.setColorFilter(new PorterDuffColorFilter(0xff00ff00, PorterDuff.Mode.MULTIPLY));
+ }
- setupList(R.id.list1);
+ public void enableClip(View v) {
+ ((ClipFrameLayout) findViewById(R.id.container)).setClipEnabled(true);
+ }
+
+ public void disableClip(View v) {
+ ((ClipFrameLayout) findViewById(R.id.container)).setClipEnabled(false);
}
public void enableLayer(View v) {
- findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
+ findViewById(R.id.container).setLayerType(View.LAYER_TYPE_HARDWARE, mPaint);
}
public void disableLayer(View v) {
- findViewById(R.id.list1).setLayerType(View.LAYER_TYPE_NONE, null);
+ findViewById(R.id.container).setLayerType(View.LAYER_TYPE_NONE, null);
}
public void growLayer(View v) {
- findViewById(R.id.list1).getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
- findViewById(R.id.list1).requestLayout();
+ findViewById(R.id.container).getLayoutParams().height = ViewGroup.LayoutParams.MATCH_PARENT;
+ findViewById(R.id.container).requestLayout();
}
public void shrinkLayer(View v) {
- findViewById(R.id.list1).getLayoutParams().height = 300;
- findViewById(R.id.list1).requestLayout();
+ findViewById(R.id.container).getLayoutParams().height = 300;
+ findViewById(R.id.container).requestLayout();
}
private void setupList(int listId) {