Use NEAREST filtering for layers whenever possible.
Change-Id: Id5bee1bd4a322cf93e8000b08e18f1e1b058648e
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h
index 0310bc3..3c2d80d 100644
--- a/libs/hwui/Layer.h
+++ b/libs/hwui/Layer.h
@@ -27,6 +27,7 @@
#include "Rect.h"
#include "SkiaColorFilter.h"
+#include "Texture.h"
#include "Vertex.h"
namespace android {
@@ -40,14 +41,18 @@
* A layer has dimensions and is backed by an OpenGL texture or FBO.
*/
struct Layer {
- Layer(const uint32_t layerWidth, const uint32_t layerHeight):
- width(layerWidth), height(layerHeight) {
+ Layer(const uint32_t layerWidth, const uint32_t layerHeight) {
mesh = NULL;
meshIndices = NULL;
meshElementCount = 0;
- isCacheable = true;
- isTextureLayer = false;
+ cacheable = true;
+ textureLayer = false;
renderTarget = GL_TEXTURE_2D;
+ texture.width = layerWidth;
+ texture.height = layerHeight;
+ colorFilter = NULL;
+ firstFilter = true;
+ firstWrap = true;
}
~Layer() {
@@ -64,12 +69,152 @@
regionRect.set(bounds.leftTop().x, bounds.leftTop().y,
bounds.rightBottom().x, bounds.rightBottom().y);
- const float texX = 1.0f / float(width);
- const float texY = 1.0f / float(height);
+ const float texX = 1.0f / float(texture.width);
+ const float texY = 1.0f / float(texture.height);
const float height = layer.getHeight();
texCoords.set(
regionRect.left * texX, (height - regionRect.top) * texY,
regionRect.right * texX, (height - regionRect.bottom) * texY);
+
+ regionRect.translate(layer.left, layer.top);
+ }
+
+ inline uint32_t getWidth() {
+ return texture.width;
+ }
+
+ inline uint32_t getHeight() {
+ return texture.height;
+ }
+
+ void setSize(uint32_t width, uint32_t height) {
+ texture.width = width;
+ texture.height = height;
+ }
+
+ inline void setBlend(bool blend) {
+ texture.blend = blend;
+ }
+
+ inline bool isBlend() {
+ return texture.blend;
+ }
+
+ inline void setAlpha(int alpha) {
+ this->alpha = alpha;
+ }
+
+ inline void setAlpha(int alpha, SkXfermode::Mode mode) {
+ this->alpha = alpha;
+ this->mode = mode;
+ }
+
+ inline int getAlpha() {
+ return alpha;
+ }
+
+ inline SkXfermode::Mode getMode() {
+ return mode;
+ }
+
+ inline void setEmpty(bool empty) {
+ this->empty = empty;
+ }
+
+ inline bool isEmpty() {
+ return empty;
+ }
+
+ inline void setFbo(GLuint fbo) {
+ this->fbo = fbo;
+ }
+
+ inline GLuint getFbo() {
+ return fbo;
+ }
+
+ inline GLuint* getTexturePointer() {
+ return &texture.id;
+ }
+
+ inline GLuint getTexture() {
+ return texture.id;
+ }
+
+ inline GLenum getRenderTarget() {
+ return renderTarget;
+ }
+
+ inline void setRenderTarget(GLenum renderTarget) {
+ this->renderTarget = renderTarget;
+ }
+
+ void setWrap(GLenum wrapS, GLenum wrapT, bool bindTexture = false, bool force = false) {
+ if (firstWrap || force || wrapS != texture.wrapS || wrapT != texture.wrapT) {
+ firstWrap = true;
+ texture.setWrap(wrapS, wrapT);
+ if (bindTexture) {
+ glBindTexture(renderTarget, texture.id);
+ }
+ glTexParameteri(renderTarget, GL_TEXTURE_WRAP_S, wrapS);
+ glTexParameteri(renderTarget, GL_TEXTURE_WRAP_T, wrapT);
+ }
+ }
+
+ void setFilter(GLenum min, GLenum mag, bool bindTexture = false, bool force = false) {
+ if (firstFilter || force || min != texture.minFilter || mag != texture.magFilter) {
+ firstFilter = false;
+ texture.setFilter(min, mag);
+ if (bindTexture) {
+ glBindTexture(renderTarget, texture.id);
+ }
+ glTexParameteri(renderTarget, GL_TEXTURE_MIN_FILTER, min);
+ glTexParameteri(renderTarget, GL_TEXTURE_MAG_FILTER, mag);
+ }
+ }
+
+ inline bool isCacheable() {
+ return cacheable;
+ }
+
+ inline void setCacheable(bool cacheable) {
+ this->cacheable = cacheable;
+ }
+
+ inline bool isTextureLayer() {
+ return textureLayer;
+ }
+
+ inline void setTextureLayer(bool textureLayer) {
+ this->textureLayer = textureLayer;
+ }
+
+ inline SkiaColorFilter* getColorFilter() {
+ return colorFilter;
+ }
+
+ inline void setColorFilter(SkiaColorFilter* filter) {
+ colorFilter = filter;
+ }
+
+ inline void bindTexture() {
+ glBindTexture(renderTarget, texture.id);
+ }
+
+ inline void generateTexture() {
+ glGenTextures(1, &texture.id);
+ }
+
+ inline void deleteTexture() {
+ if (texture.id) glDeleteTextures(1, &texture.id);
+ }
+
+ inline void allocateTexture(GLenum format, GLenum storage) {
+ glTexImage2D(renderTarget, 0, format, getWidth(), getHeight(), 0, format, storage, NULL);
+ }
+
+ inline mat4& getTexTransform() {
+ return texTransform;
}
/**
@@ -82,43 +227,6 @@
Rect texCoords;
/**
- * Name of the FBO used to render the layer. If the name is 0
- * this layer is not backed by an FBO, but a simple texture.
- */
- GLuint fbo;
-
- /**
- * Opacity of the layer.
- */
- int alpha;
- /**
- * Blending mode of the layer.
- */
- SkXfermode::Mode mode;
- /**
- * Indicates whether this layer should be blended.
- */
- bool blend;
-
- /**
- * Indicates whether this layer has been used already.
- */
- bool empty;
-
- /**
- * Name of the texture used to render the layer.
- */
- GLuint texture;
- /**
- * Width of the layer texture.
- */
- uint32_t width;
- /**
- * Height of the layer texture.
- */
- uint32_t height;
-
- /**
* Dirty region indicating what parts of the layer
* have been drawn.
*/
@@ -130,37 +238,66 @@
Rect regionRect;
/**
- * Color filter used to draw this layer. Optional.
- */
- SkiaColorFilter* colorFilter;
-
- /**
* If the layer can be rendered as a mesh, this is non-null.
*/
TextureVertex* mesh;
uint16_t* meshIndices;
GLsizei meshElementCount;
+private:
+ /**
+ * Name of the FBO used to render the layer. If the name is 0
+ * this layer is not backed by an FBO, but a simple texture.
+ */
+ GLuint fbo;
+
+ /**
+ * Indicates whether this layer has been used already.
+ */
+ bool empty;
+
+ /**
+ * The texture backing this layer.
+ */
+ Texture texture;
+
/**
* If set to true (by default), the layer can be reused.
*/
- bool isCacheable;
+ bool cacheable;
/**
* When set to true, this layer must be treated as a texture
* layer.
*/
- bool isTextureLayer;
+ bool textureLayer;
+
+ /**
+ * Indicates the render target.
+ */
+ GLenum renderTarget;
+
+ /**
+ * Color filter used to draw this layer. Optional.
+ */
+ SkiaColorFilter* colorFilter;
+
+ /**
+ * Opacity of the layer.
+ */
+ int alpha;
+ /**
+ * Blending mode of the layer.
+ */
+ SkXfermode::Mode mode;
/**
* Optional texture coordinates transform.
*/
mat4 texTransform;
- /**
- * Indicates the render target.
- */
- GLenum renderTarget;
+ bool firstFilter;
+ bool firstWrap;
}; // struct Layer
}; // namespace uirenderer