diff options
author | Romain Guy <romainguy@google.com> | 2011-04-28 18:47:01 -0700 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2011-04-28 18:47:01 -0700 |
commit | ad44445c772efe66fdf063aa8f78d7ae3233570e (patch) | |
tree | 8097234b893dbc0dfe050a0a98e7acecce74b28b /libs | |
parent | efe2a0e6ac8183c98dfe969928509e3b32903b40 (diff) | |
parent | aa6c24c21c727a196451332448d4e3b11a80be69 (diff) | |
download | frameworks_base-ad44445c772efe66fdf063aa8f78d7ae3233570e.zip frameworks_base-ad44445c772efe66fdf063aa8f78d7ae3233570e.tar.gz frameworks_base-ad44445c772efe66fdf063aa8f78d7ae3233570e.tar.bz2 |
Merge "New widget: TextureView Bug #4343984"
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/Layer.h | 18 | ||||
-rw-r--r-- | libs/hwui/LayerCache.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.cpp | 47 | ||||
-rw-r--r-- | libs/hwui/LayerRenderer.h | 3 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 57 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 13 | ||||
-rw-r--r-- | libs/hwui/ProgramCache.cpp | 34 | ||||
-rw-r--r-- | libs/hwui/ProgramCache.h | 5 |
8 files changed, 166 insertions, 13 deletions
diff --git a/libs/hwui/Layer.h b/libs/hwui/Layer.h index 6c4a2a9..16566b8 100644 --- a/libs/hwui/Layer.h +++ b/libs/hwui/Layer.h @@ -45,6 +45,8 @@ struct Layer { mesh = NULL; meshIndices = NULL; meshElementCount = 0; + isCacheable = true; + isTextureLayer = false; } ~Layer() { @@ -137,6 +139,22 @@ struct Layer { TextureVertex* mesh; uint16_t* meshIndices; GLsizei meshElementCount; + + /** + * If set to true (by default), the layer can be reused. + */ + bool isCacheable; + + /** + * When set to true, this layer must be treated as a texture + * layer. + */ + bool isTextureLayer; + + /** + * Optional texture coordinates transform. + */ + mat4 texTransform; }; // struct Layer }; // namespace uirenderer diff --git a/libs/hwui/LayerCache.cpp b/libs/hwui/LayerCache.cpp index a9710ad..b2d795f 100644 --- a/libs/hwui/LayerCache.cpp +++ b/libs/hwui/LayerCache.cpp @@ -154,6 +154,8 @@ bool LayerCache::resize(Layer* layer, const uint32_t width, const uint32_t heigh } bool LayerCache::put(Layer* layer) { + if (!layer->isCacheable) return false; + const uint32_t size = layer->width * layer->height * 4; // Don't even try to cache a layer that's bigger than the cache if (size < mMaxSize) { diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp index ca1e7ae..e167336 100644 --- a/libs/hwui/LayerRenderer.cpp +++ b/libs/hwui/LayerRenderer.cpp @@ -20,6 +20,7 @@ #include "LayerCache.h" #include "LayerRenderer.h" +#include "Matrix.h" #include "Properties.h" #include "Rect.h" @@ -165,6 +166,40 @@ void LayerRenderer::generateMesh() { // Layers management /////////////////////////////////////////////////////////////////////////////// +Layer* LayerRenderer::createTextureLayer() { + LAYER_RENDERER_LOGD("Creating new texture layer"); + + Layer* layer = new Layer(0, 0); + layer->isCacheable = false; + layer->isTextureLayer = true; + layer->blend = true; + layer->empty = true; + layer->fbo = 0; + layer->colorFilter = NULL; + layer->fbo = 0; + layer->layer.set(0.0f, 0.0f, 0.0f, 0.0f); + layer->texCoords.set(0.0f, 1.0f, 0.0f, 1.0f); + layer->alpha = 255; + layer->mode = SkXfermode::kSrcOver_Mode; + layer->colorFilter = NULL; + layer->region.clear(); + + glActiveTexture(GL_TEXTURE0); + + glGenTextures(1, &layer->texture); + glBindTexture(GL_TEXTURE_EXTERNAL_OES, layer->texture); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_EXTERNAL_OES, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + return layer; +} + Layer* LayerRenderer::createLayer(uint32_t width, uint32_t height, bool isOpaque) { LAYER_RENDERER_LOGD("Creating new layer %dx%d", width, height); @@ -244,6 +279,18 @@ bool LayerRenderer::resizeLayer(Layer* layer, uint32_t width, uint32_t height) { return true; } +void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, + float* transform) { + if (layer) { + layer->width = width; + layer->height = height; + layer->layer.set(0.0f, 0.0f, width, height); + layer->region.set(width, height); + layer->regionRect.set(0.0f, 0.0f, width, height); + layer->texTransform.load(transform); + } +} + void LayerRenderer::destroyLayer(Layer* layer) { if (layer) { LAYER_RENDERER_LOGD("Destroying layer, fbo = %d", layer->fbo); diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h index d2f565e..b3cd5db 100644 --- a/libs/hwui/LayerRenderer.h +++ b/libs/hwui/LayerRenderer.h @@ -53,8 +53,11 @@ public: Region* getRegion(); GLint getTargetFbo(); + static Layer* createTextureLayer(); static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false); static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height); + static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height, + float* transform); static void destroyLayer(Layer* layer); static void destroyLayerDeferred(Layer* layer); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index ea42838..34d8fd3 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -633,15 +633,43 @@ void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { } } +void OpenGLRenderer::drawTextureLayer(Layer* layer, const Rect& rect) { + float alpha = layer->alpha / 255.0f; + + setupDraw(); + setupDrawWithExternalTexture(); + setupDrawColor(alpha, alpha, alpha, alpha); + setupDrawColorFilter(); + setupDrawBlending(layer->blend, layer->mode); + setupDrawProgram(); + setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom); + setupDrawPureColorUniforms(); + setupDrawColorFilterUniforms(); + setupDrawExternalTexture(layer->texture); + setupDrawTextureTransform(layer->texTransform); + setupDrawMesh(&mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]); + + glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); + + finishDrawTexture(); +} + void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap) { - const Rect& texCoords = layer->texCoords; - resetDrawTextureTexCoords(texCoords.left, texCoords.top, texCoords.right, texCoords.bottom); + if (!layer->isTextureLayer) { + const Rect& texCoords = layer->texCoords; + resetDrawTextureTexCoords(texCoords.left, texCoords.top, + texCoords.right, texCoords.bottom); - drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture, - layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0], - &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, swap, swap); + drawTextureMesh(rect.left, rect.top, rect.right, rect.bottom, layer->texture, + layer->alpha / 255.0f, layer->mode, layer->blend, &mMeshVertices[0].position[0], + &mMeshVertices[0].texture[0], GL_TRIANGLE_STRIP, gMeshCount, swap, swap); - resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); + resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); + } else { + resetDrawTextureTexCoords(0.0f, 1.0f, 1.0f, 0.0f); + drawTextureLayer(layer, rect); + resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f); + } } void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) { @@ -882,6 +910,10 @@ void OpenGLRenderer::setupDrawWithTexture(bool isAlpha8) { mDescription.hasAlpha8Texture = isAlpha8; } +void OpenGLRenderer::setupDrawWithExternalTexture() { + mDescription.hasExternalTexture = true; +} + void OpenGLRenderer::setupDrawAALine() { mDescription.hasWidth = true; } @@ -1055,6 +1087,19 @@ void OpenGLRenderer::setupDrawTexture(GLuint texture) { glEnableVertexAttribArray(mTexCoordsSlot); } +void OpenGLRenderer::setupDrawExternalTexture(GLuint texture) { + bindExternalTexture(texture); + glUniform1i(mCaches.currentProgram->getUniform("sampler"), mTextureUnit++); + + mTexCoordsSlot = mCaches.currentProgram->getAttrib("texCoords"); + glEnableVertexAttribArray(mTexCoordsSlot); +} + +void OpenGLRenderer::setupDrawTextureTransform(mat4& transform) { + glUniformMatrix4fv(mCaches.currentProgram->getUniform("mainTextureTransform"), 1, + GL_FALSE, &transform.data[0]); +} + void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLuint vbo) { if (!vertices) { mCaches.bindMeshBuffer(vbo == 0 ? mCaches.meshBuffer : vbo); diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 918e1fb..0ffd70b 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -248,6 +248,8 @@ private: */ void composeLayerRect(Layer* layer, const Rect& rect, bool swap = false); + void drawTextureLayer(Layer* layer, const Rect& rect); + /** * Mark the layer as dirty at the specified coordinates. The coordinates * are transformed with the supplied matrix. @@ -387,6 +389,14 @@ private: } /** + * Binds the specified EGLImage texture. The texture unit must have been selected + * prior to calling this method. + */ + inline void bindExternalTexture(GLuint texture) { + glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture); + } + + /** * Sets the wrap modes for the specified texture. The wrap modes are modified * only when needed. */ @@ -425,6 +435,7 @@ private: * Various methods to setup OpenGL rendering. */ void setupDrawWithTexture(bool isAlpha8 = false); + void setupDrawWithExternalTexture(); void setupDrawAALine(); void setupDrawPoint(float pointSize); void setupDrawColor(int color); @@ -453,6 +464,8 @@ private: void setupDrawColorFilterUniforms(); void setupDrawSimpleMesh(); void setupDrawTexture(GLuint texture); + void setupDrawExternalTexture(GLuint texture); + void setupDrawTextureTransform(mat4& transform); void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0); void setupDrawVertices(GLvoid* vertices); void setupDrawAALine(GLvoid* vertices, GLvoid* distanceCoords, float strokeWidth); diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp index 80b1917..62ac2ba 100644 --- a/libs/hwui/ProgramCache.cpp +++ b/libs/hwui/ProgramCache.cpp @@ -41,6 +41,8 @@ const char* gVS_Header_Attributes_TexCoords = "attribute vec2 texCoords;\n"; const char* gVS_Header_Attributes_Distance = "attribute float vtxDistance;\n"; +const char* gVS_Header_Uniforms_TextureTransform = + "uniform mat4 mainTextureTransform;\n"; const char* gVS_Header_Uniforms = "uniform mat4 transform;\n"; const char* gVS_Header_Uniforms_IsPoint = @@ -76,6 +78,8 @@ const char* gVS_Main = "\nvoid main(void) {\n"; const char* gVS_Main_OutTexCoords = " outTexCoords = texCoords;\n"; +const char* gVS_Main_OutTransformedTexCoords = + " outTexCoords = (mainTextureTransform * vec4(texCoords, 0.0, 1.0)).xy;\n"; const char* gVS_Main_OutGradient[3] = { // Linear " linear = vec2((screenSpace * position).x, 0.5);\n", @@ -103,6 +107,8 @@ const char* gVS_Footer = const char* gFS_Header_Extension_FramebufferFetch = "#extension GL_NV_shader_framebuffer_fetch : enable\n\n"; +const char* gFS_Header_Extension_ExternalTexture = + "#extension GL_OES_EGL_image_external : require\n\n"; const char* gFS_Header = "precision mediump float;\n\n"; const char* gFS_Uniforms_Color = @@ -116,6 +122,8 @@ const char* gFS_Header_Uniforms_PointHasBitmap = "uniform float pointSize;\n"; const char* gFS_Uniforms_TextureSampler = "uniform sampler2D sampler;\n"; +const char* gFS_Uniforms_ExternalTextureSampler = + "uniform samplerExternalOES sampler;\n"; const char* gFS_Uniforms_GradientSampler[3] = { // Linear "uniform sampler2D gradientSampler;\n", @@ -369,7 +377,7 @@ Program* ProgramCache::generateProgram(const ProgramDescription& description, pr String8 ProgramCache::generateVertexShader(const ProgramDescription& description) { // Add attributes String8 shader(gVS_Header_Attributes); - if (description.hasTexture) { + if (description.hasTexture || description.hasExternalTexture) { shader.append(gVS_Header_Attributes_TexCoords); } if (description.hasWidth) { @@ -377,6 +385,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description } // Uniforms shader.append(gVS_Header_Uniforms); + if (description.hasExternalTexture) { + shader.append(gVS_Header_Uniforms_TextureTransform); + } if (description.hasGradient) { shader.append(gVS_Header_Uniforms_HasGradient[description.gradientType]); } @@ -387,7 +398,7 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description shader.append(gVS_Header_Uniforms_IsPoint); } // Varyings - if (description.hasTexture) { + if (description.hasTexture || description.hasExternalTexture) { shader.append(gVS_Header_Varyings_HasTexture); } if (description.hasWidth) { @@ -407,6 +418,9 @@ String8 ProgramCache::generateVertexShader(const ProgramDescription& description if (description.hasTexture) { shader.append(gVS_Main_OutTexCoords); } + if (description.hasExternalTexture) { + shader.append(gVS_Main_OutTransformedTexCoords); + } if (description.hasWidth) { shader.append(gVS_Main_Width); } @@ -440,11 +454,14 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (blendFramebuffer) { shader.append(gFS_Header_Extension_FramebufferFetch); } + if (description.hasExternalTexture) { + shader.append(gFS_Header_Extension_ExternalTexture); + } shader.append(gFS_Header); // Varyings - if (description.hasTexture) { + if (description.hasTexture || description.hasExternalTexture) { shader.append(gVS_Header_Varyings_HasTexture); } if (description.hasWidth) { @@ -461,7 +478,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti // Uniforms int modulateOp = MODULATE_OP_NO_MODULATE; - const bool singleColor = !description.hasTexture && + const bool singleColor = !description.hasTexture && !description.hasExternalTexture && !description.hasGradient && !description.hasBitmap; if (description.modulate || singleColor) { @@ -471,6 +488,9 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti if (description.hasTexture) { shader.append(gFS_Uniforms_TextureSampler); } + if (description.hasExternalTexture) { + shader.append(gFS_Uniforms_ExternalTextureSampler); + } if (description.hasWidth) { shader.append(gFS_Uniforms_Width); } @@ -487,11 +507,11 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti bool fast = false; const bool noShader = !description.hasGradient && !description.hasBitmap; - const bool singleTexture = description.hasTexture && + const bool singleTexture = (description.hasTexture || description.hasExternalTexture) && !description.hasAlpha8Texture && noShader; const bool singleA8Texture = description.hasTexture && description.hasAlpha8Texture && noShader; - const bool singleGradient = !description.hasTexture && + const bool singleGradient = !description.hasTexture && !description.hasExternalTexture && description.hasGradient && !description.hasBitmap && description.gradientType == ProgramDescription::kGradientLinear; @@ -554,7 +574,7 @@ String8 ProgramCache::generateFragmentShader(const ProgramDescription& descripti // Begin the shader shader.append(gFS_Main); { // Stores the result in fragColor directly - if (description.hasTexture) { + if (description.hasTexture || description.hasExternalTexture) { if (description.hasAlpha8Texture) { if (!description.hasGradient && !description.hasBitmap) { shader.append(gFS_Main_FetchA8Texture[modulateOp]); diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h index 18d98cb..70909fd 100644 --- a/libs/hwui/ProgramCache.h +++ b/libs/hwui/ProgramCache.h @@ -77,6 +77,8 @@ namespace uirenderer { #define PROGRAM_HAS_WIDTH_SHIFT 37 +#define PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT 38 + /////////////////////////////////////////////////////////////////////////////// // Types /////////////////////////////////////////////////////////////////////////////// @@ -113,6 +115,7 @@ struct ProgramDescription { // Texturing bool hasTexture; bool hasAlpha8Texture; + bool hasExternalTexture; // Modulate, this should only be set when setColor() return true bool modulate; @@ -151,6 +154,7 @@ struct ProgramDescription { void reset() { hasTexture = false; hasAlpha8Texture = false; + hasExternalTexture = false; hasWidth = false; @@ -240,6 +244,7 @@ struct ProgramDescription { if (modulate) key |= programid(0x1) << PROGRAM_MODULATE_SHIFT; if (isPoint) key |= programid(0x1) << PROGRAM_IS_POINT_SHIFT; if (hasWidth) key |= programid(0x1) << PROGRAM_HAS_WIDTH_SHIFT; + if (hasExternalTexture) key |= programid(0x1) << PROGRAM_HAS_EXTERNAL_TEXTURE_SHIFT; return key; } |