Loading libs/hwui/OpenGLRenderer.cpp +188 −200 Original line number Diff line number Diff line Loading @@ -183,12 +183,12 @@ OpenGLRenderer::~OpenGLRenderer() { void OpenGLRenderer::setViewport(int width, int height) { glViewport(0, 0, width, height); mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1); mWidth = width; mHeight = height; mFirstSnapshot->height = height; mFirstSnapshot->viewport.set(0, 0, width, height); } void OpenGLRenderer::prepare() { Loading Loading @@ -254,6 +254,8 @@ bool OpenGLRenderer::restoreSnapshot() { sp<Snapshot> previous = mSnapshot->previous; if (restoreOrtho) { Rect& r = previous->viewport; glViewport(r.left, r.top, r.right, r.bottom); mOrthoMatrix.load(current->orthoMatrix); } Loading @@ -267,39 +269,6 @@ bool OpenGLRenderer::restoreSnapshot() { return restoreClip; } void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { if (!current->layer) { LOGE("Attempting to compose a layer that does not exist"); return; } // Unbind current FBO and restore previous one // Most of the time, previous->fbo will be 0 to bind the default buffer glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); // Restore the clip from the previous snapshot const Rect& clip = previous->clipRect; glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight()); Layer* layer = current->layer; const Rect& rect = layer->layer; drawTextureRect(rect.left, rect.top, rect.right, rect.bottom, layer->texture, layer->alpha, layer->mode, layer->blend); LayerSize size(rect.getWidth(), rect.getHeight()); // Failing to add the layer to the cache should happen only if the // layer is too large if (!mLayerCache.put(size, layer)) { LAYER_LOGD("Deleting layer"); glDeleteFramebuffers(1, &layer->fbo); glDeleteTextures(1, &layer->texture); delete layer; } } /////////////////////////////////////////////////////////////////////////////// // Layers /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -366,21 +335,58 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, // Creates a new snapshot to draw into the FBO saveSnapshot(); // TODO: This doesn't preserve other transformations (check Skia first) mSnapshot->transform.loadTranslate(-left, -top, 0.0f); mSnapshot->setClip(0.0f, 0.0f, right - left, bottom - top); mSnapshot->viewport.set(0.0f, 0.0f, right - left, bottom - top); mSnapshot->height = bottom - top; setScissorFromClip(); mSnapshot->flags = Snapshot::kFlagDirtyOrtho | Snapshot::kFlagClipSet; mSnapshot->orthoMatrix.load(mOrthoMatrix); // Change the ortho projection mOrthoMatrix.loadOrtho(0.0f, right - left, bottom - top, 0.0f, 0.0f, 1.0f); glViewport(0, 0, right - left, bottom - top); // Don't flip the FBO, it will get flipped when drawing back to the framebuffer mOrthoMatrix.loadOrtho(0.0f, right - left, 0.0f, bottom - top, -1.0f, 1.0f); return true; } void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { if (!current->layer) { LOGE("Attempting to compose a layer that does not exist"); return; } // Unbind current FBO and restore previous one // Most of the time, previous->fbo will be 0 to bind the default buffer glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); // Restore the clip from the previous snapshot const Rect& clip = previous->clipRect; glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight()); Layer* layer = current->layer; const Rect& rect = layer->layer; drawTextureRect(rect.left, rect.top, rect.right, rect.bottom, layer->texture, layer->alpha, layer->mode, layer->blend); LayerSize size(rect.getWidth(), rect.getHeight()); // Failing to add the layer to the cache should happen only if the // layer is too large if (!mLayerCache.put(size, layer)) { LAYER_LOGD("Deleting layer"); glDeleteFramebuffers(1, &layer->fbo); glDeleteTextures(1, &layer->texture); delete layer; } } /////////////////////////////////////////////////////////////////////////////// // Transforms /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -424,14 +430,9 @@ const Rect& OpenGLRenderer::getClipBounds() { } bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) { SkRect sr; sr.set(left, top, right, bottom); SkMatrix m; mSnapshot->transform.copyTo(m); m.mapRect(&sr); Rect r(left, top, right, bottom); mSnapshot->transform.mapRect(r); Rect r(sr.fLeft, sr.fTop, sr.fRight, sr.fBottom); return !mSnapshot->clipRect.intersects(r); } Loading Loading @@ -562,82 +563,6 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, drawColorRect(left, top, right, bottom, color, mode); } void OpenGLRenderer::renderShadow(const ShadowTexture* texture, float x, float y, SkXfermode::Mode mode) { const float sx = x - texture->left + mShadowDx; const float sy = y - texture->top + mShadowDy; const GLfloat a = ((mShadowColor >> 24) & 0xFF) / 255.0f; const GLfloat r = a * ((mShadowColor >> 16) & 0xFF) / 255.0f; const GLfloat g = a * ((mShadowColor >> 8) & 0xFF) / 255.0f; const GLfloat b = a * ((mShadowColor ) & 0xFF) / 255.0f; GLuint textureUnit = 0; renderTextureAlpha8(texture, textureUnit, sx, sy, r, g, b, a, mode, false); } void OpenGLRenderer::renderTextureAlpha8(const Texture* texture, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool applyFilters) { // Describe the required shaders ProgramDescription description; description.hasTexture = true; description.hasAlpha8Texture = true; if (applyFilters) { if (mShader) { mShader->describe(description, mExtensions); } if (mColorFilter) { mColorFilter->describe(description, mExtensions); } } // Build and use the appropriate shader useProgram(mProgramCache.get(description)); // Setup the blending mode chooseBlending(true, mode); bindTexture(texture->id, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit); glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit); int texCoordsSlot = mCurrentProgram->getAttrib("texCoords"); glEnableVertexAttribArray(texCoordsSlot); // Setup attributes glVertexAttribPointer(mCurrentProgram->position, 2, GL_FLOAT, GL_FALSE, gMeshStride, &mMeshVertices[0].position[0]); glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, &mMeshVertices[0].texture[0]); // Setup uniforms mModelView.loadTranslate(x, y, 0.0f); mModelView.scale(texture->width, texture->height, 1.0f); mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); glUniform4f(mCurrentProgram->color, r, g, b, a); textureUnit++; if (applyFilters) { // Setup attributes and uniforms required by the shaders if (mShader) { mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit); } if (mColorFilter) { mColorFilter->setupProgram(mCurrentProgram); } } // Draw the mesh glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); glDisableVertexAttribArray(texCoordsSlot); } #define kStdStrikeThru_Offset (-6.0f / 21.0f) #define kStdUnderline_Offset (1.0f / 9.0f) #define kStdUnderline_Thickness (1.0f / 18.0f) void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint) { if (text == NULL || count == 0 || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) { Loading Loading @@ -668,7 +593,12 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, const ShadowTexture* shadow = mDropShadowCache.get(paint, text, bytesCount, count, mShadowRadius); const AutoTexture autoCleanup(shadow); renderShadow(shadow, x, y, mode); setupShadow(shadow, x, y, mode); // Draw the mesh glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); glDisableVertexAttribArray(mCurrentProgram->getAttrib("texCoords")); } uint32_t color = paint->getColor(); Loading @@ -677,94 +607,19 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; const GLfloat b = a * ((color ) & 0xFF) / 255.0f; mModelView.loadIdentity(); GLuint textureUnit = 0; // Needs to be set prior to calling FontRenderer::getTexture() glActiveTexture(gTextureUnits[textureUnit]); ProgramDescription description; description.hasTexture = true; description.hasAlpha8Texture = true; if (mShader) { mShader->describe(description, mExtensions); } if (mColorFilter) { mColorFilter->describe(description, mExtensions); } useProgram(mProgramCache.get(description)); mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); // Text is always blended, no need to check the shader chooseBlending(true, mode); bindTexture(mFontRenderer.getTexture(), GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit); glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit); int texCoordsSlot = mCurrentProgram->getAttrib("texCoords"); glEnableVertexAttribArray(texCoordsSlot); // Always premultiplied glUniform4f(mCurrentProgram->color, r, g, b, a); textureUnit++; // Setup attributes and uniforms required by the shaders if (mShader) { mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit); } if (mColorFilter) { mColorFilter->setupProgram(mCurrentProgram); } setupTextureAlpha8(mFontRenderer.getTexture(), 0, 0, textureUnit, x, y, r, g, b, a, mode, false, true); const Rect& clip = mSnapshot->getLocalClip(); mFontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDisableVertexAttribArray(texCoordsSlot); glDisableVertexAttribArray(mCurrentProgram->getAttrib("texCoords")); // Handle underline and strike-through uint32_t flags = paint->getFlags(); if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) { float underlineWidth = length; // If length is > 0.0f, we already measured the text for the text alignment if (length <= 0.0f) { underlineWidth = paint->measureText(text, bytesCount); } float offsetX = 0; switch (paint->getTextAlign()) { case SkPaint::kCenter_Align: offsetX = underlineWidth * 0.5f; break; case SkPaint::kRight_Align: offsetX = underlineWidth; break; default: break; } if (underlineWidth > 0.0f) { float textSize = paint->getTextSize(); float height = textSize * kStdUnderline_Thickness; float left = x - offsetX; float top = 0.0f; float right = left + underlineWidth; float bottom = 0.0f; if (flags & SkPaint::kUnderlineText_Flag) { top = y + textSize * kStdUnderline_Offset; bottom = top + height; drawRect(left, top, right, bottom, paint); } if (flags & SkPaint::kStrikeThruText_Flag) { top = y + textSize * kStdStrikeThru_Offset; bottom = top + height; drawRect(left, top, right, bottom, paint); } } } drawTextDecorations(text, bytesCount, length, x, y, paint); } void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) { Loading @@ -787,7 +642,12 @@ void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) { const float x = texture->left - texture->offset; const float y = texture->top - texture->offset; renderTextureAlpha8(texture, textureUnit, x, y, r, g, b, a, mode, true); setupTextureAlpha8(texture, textureUnit, x, y, r, g, b, a, mode, true, true); // Draw the mesh glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); glDisableVertexAttribArray(mCurrentProgram->getAttrib("texCoords")); } /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -837,6 +697,134 @@ void OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) { // Drawing implementation /////////////////////////////////////////////////////////////////////////////// void OpenGLRenderer::setupShadow(const ShadowTexture* texture, float x, float y, SkXfermode::Mode mode) { const float sx = x - texture->left + mShadowDx; const float sy = y - texture->top + mShadowDy; const GLfloat a = ((mShadowColor >> 24) & 0xFF) / 255.0f; const GLfloat r = a * ((mShadowColor >> 16) & 0xFF) / 255.0f; const GLfloat g = a * ((mShadowColor >> 8) & 0xFF) / 255.0f; const GLfloat b = a * ((mShadowColor ) & 0xFF) / 255.0f; GLuint textureUnit = 0; setupTextureAlpha8(texture, textureUnit, sx, sy, r, g, b, a, mode, true, false); } void OpenGLRenderer::setupTextureAlpha8(const Texture* texture, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool transforms, bool applyFilters) { setupTextureAlpha8(texture->id, texture->width, texture->height, textureUnit, x, y, r, g, b, a, mode, transforms, applyFilters); } void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool transforms, bool applyFilters) { // Describe the required shaders ProgramDescription description; description.hasTexture = true; description.hasAlpha8Texture = true; if (applyFilters) { if (mShader) { mShader->describe(description, mExtensions); } if (mColorFilter) { mColorFilter->describe(description, mExtensions); } } // Build and use the appropriate shader useProgram(mProgramCache.get(description)); // Setup the blending mode chooseBlending(true, mode); bindTexture(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit); glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit); int texCoordsSlot = mCurrentProgram->getAttrib("texCoords"); glEnableVertexAttribArray(texCoordsSlot); // Setup attributes glVertexAttribPointer(mCurrentProgram->position, 2, GL_FLOAT, GL_FALSE, gMeshStride, &mMeshVertices[0].position[0]); glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, &mMeshVertices[0].texture[0]); // Setup uniforms if (transforms) { mModelView.loadTranslate(x, y, 0.0f); mModelView.scale(width, height, 1.0f); } else { mModelView.loadIdentity(); } mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); glUniform4f(mCurrentProgram->color, r, g, b, a); textureUnit++; if (applyFilters) { // Setup attributes and uniforms required by the shaders if (mShader) { mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit); } if (mColorFilter) { mColorFilter->setupProgram(mCurrentProgram); } } } #define kStdStrikeThru_Offset (-6.0f / 21.0f) #define kStdUnderline_Offset (1.0f / 9.0f) #define kStdUnderline_Thickness (1.0f / 18.0f) void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float length, float x, float y, SkPaint* paint) { // Handle underline and strike-through uint32_t flags = paint->getFlags(); if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) { float underlineWidth = length; // If length is > 0.0f, we already measured the text for the text alignment if (length <= 0.0f) { underlineWidth = paint->measureText(text, bytesCount); } float offsetX = 0; switch (paint->getTextAlign()) { case SkPaint::kCenter_Align: offsetX = underlineWidth * 0.5f; break; case SkPaint::kRight_Align: offsetX = underlineWidth; break; default: break; } if (underlineWidth > 0.0f) { float textSize = paint->getTextSize(); float height = textSize * kStdUnderline_Thickness; float left = x - offsetX; float top = 0.0f; float right = left + underlineWidth; float bottom = 0.0f; if (flags & SkPaint::kUnderlineText_Flag) { top = y + textSize * kStdUnderline_Offset; bottom = top + height; drawRect(left, top, right, bottom, paint); } if (flags & SkPaint::kStrikeThruText_Flag) { top = y + textSize * kStdStrikeThru_Offset; bottom = top + height; drawRect(left, top, right, bottom, paint); } } } } void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, int color, SkXfermode::Mode mode, bool ignoreTransform) { // If a shader is set, preserve only the alpha Loading libs/hwui/OpenGLRenderer.h +44 −5 Original line number Diff line number Diff line Loading @@ -226,17 +226,17 @@ private: GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount = 0); /** * Renders the specified shadow. * Prepares the renderer to draw the specified shadow. * * @param texture The shadow texture * @param x The x coordinate of the shadow * @param y The y coordinate of the shadow * @param mode The blending mode */ void renderShadow(const ShadowTexture* texture, float x, float y, SkXfermode::Mode mode); void setupShadow(const ShadowTexture* texture, float x, float y, SkXfermode::Mode mode); /** * Renders the specified Alpha8 texture as a rectangle. * Prepares the renderer to draw the specified Alpha8 texture as a rectangle. * * @param texture The texture to render with * @param textureUnit The texture unit to use, may be modified Loading @@ -247,11 +247,50 @@ private: * @param b The blue component of the color * @param a The alpha component of the color * @param mode The blending mode * @param transforms True if the matrix passed to the shader should be multiplied * by the model-view matrix * @param applyFilters Whether or not to take color filters and * shaders into account */ void renderTextureAlpha8(const Texture* texture, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool applyFilters); void setupTextureAlpha8(const Texture* texture, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool transforms, bool applyFilters); /** * Prepares the renderer to draw the specified Alpha8 texture as a rectangle. * * @param texture The texture to render with * @param width The width of the texture * @param height The height of the texture * @param textureUnit The texture unit to use, may be modified * @param x The x coordinate of the rectangle to draw * @param y The y coordinate of the rectangle to draw * @param r The red component of the color * @param g The green component of the color * @param b The blue component of the color * @param a The alpha component of the color * @param mode The blending mode * @param transforms True if the matrix passed to the shader should be multiplied * by the model-view matrix * @param applyFilters Whether or not to take color filters and * shaders into account */ void setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool transforms, bool applyFilters); /** * Draws text underline and strike-through if needed. * * @param text The text to decor * @param bytesCount The number of bytes in the text * @param length The length in pixels of the text, can be <= 0.0f to force a measurement * @param x The x coordinate where the text will be drawn * @param y The y coordinate where the text will be drawn * @param paint The paint to draw the text with */ void drawTextDecorations(const char* text, int bytesCount, float length, float x, float y, SkPaint* paint); /** * Resets the texture coordinates stored in mMeshVertices. Setting the values Loading libs/hwui/Snapshot.h +7 −1 Original line number Diff line number Diff line Loading @@ -57,7 +57,8 @@ public: flags(0), previous(s), layer(NULL), fbo(s->fbo) { fbo(s->fbo), viewport(s->viewport) { if ((s->flags & Snapshot::kFlagClipSet) && !(s->flags & Snapshot::kFlagDirtyLocalClip)) { localClip.set(s->localClip); Loading Loading @@ -179,6 +180,11 @@ public: Layer* layer; GLuint fbo; /** * Current viewport. */ Rect viewport; /** * Contains the previous ortho matrix. */ Loading libs/hwui/TextDropShadowCache.h +1 −1 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ struct ShadowText { ShadowText(const ShadowText& shadow): paint(shadow.paint), radius(shadow.radius), len(shadow.len), hash(shadow.hash) { text = new char[len]; text = new char[shadow.len]; memcpy(text, shadow.text, shadow.len); } Loading tests/HwAccelerationTest/AndroidManifest.xml +9 −0 Original line number Diff line number Diff line Loading @@ -189,5 +189,14 @@ </intent-filter> </activity> <activity android:name="StackActivity" android:label="_Stacks"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> Loading
libs/hwui/OpenGLRenderer.cpp +188 −200 Original line number Diff line number Diff line Loading @@ -183,12 +183,12 @@ OpenGLRenderer::~OpenGLRenderer() { void OpenGLRenderer::setViewport(int width, int height) { glViewport(0, 0, width, height); mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1); mWidth = width; mHeight = height; mFirstSnapshot->height = height; mFirstSnapshot->viewport.set(0, 0, width, height); } void OpenGLRenderer::prepare() { Loading Loading @@ -254,6 +254,8 @@ bool OpenGLRenderer::restoreSnapshot() { sp<Snapshot> previous = mSnapshot->previous; if (restoreOrtho) { Rect& r = previous->viewport; glViewport(r.left, r.top, r.right, r.bottom); mOrthoMatrix.load(current->orthoMatrix); } Loading @@ -267,39 +269,6 @@ bool OpenGLRenderer::restoreSnapshot() { return restoreClip; } void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { if (!current->layer) { LOGE("Attempting to compose a layer that does not exist"); return; } // Unbind current FBO and restore previous one // Most of the time, previous->fbo will be 0 to bind the default buffer glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); // Restore the clip from the previous snapshot const Rect& clip = previous->clipRect; glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight()); Layer* layer = current->layer; const Rect& rect = layer->layer; drawTextureRect(rect.left, rect.top, rect.right, rect.bottom, layer->texture, layer->alpha, layer->mode, layer->blend); LayerSize size(rect.getWidth(), rect.getHeight()); // Failing to add the layer to the cache should happen only if the // layer is too large if (!mLayerCache.put(size, layer)) { LAYER_LOGD("Deleting layer"); glDeleteFramebuffers(1, &layer->fbo); glDeleteTextures(1, &layer->texture); delete layer; } } /////////////////////////////////////////////////////////////////////////////// // Layers /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -366,21 +335,58 @@ bool OpenGLRenderer::createLayer(sp<Snapshot> snapshot, float left, float top, // Creates a new snapshot to draw into the FBO saveSnapshot(); // TODO: This doesn't preserve other transformations (check Skia first) mSnapshot->transform.loadTranslate(-left, -top, 0.0f); mSnapshot->setClip(0.0f, 0.0f, right - left, bottom - top); mSnapshot->viewport.set(0.0f, 0.0f, right - left, bottom - top); mSnapshot->height = bottom - top; setScissorFromClip(); mSnapshot->flags = Snapshot::kFlagDirtyOrtho | Snapshot::kFlagClipSet; mSnapshot->orthoMatrix.load(mOrthoMatrix); // Change the ortho projection mOrthoMatrix.loadOrtho(0.0f, right - left, bottom - top, 0.0f, 0.0f, 1.0f); glViewport(0, 0, right - left, bottom - top); // Don't flip the FBO, it will get flipped when drawing back to the framebuffer mOrthoMatrix.loadOrtho(0.0f, right - left, 0.0f, bottom - top, -1.0f, 1.0f); return true; } void OpenGLRenderer::composeLayer(sp<Snapshot> current, sp<Snapshot> previous) { if (!current->layer) { LOGE("Attempting to compose a layer that does not exist"); return; } // Unbind current FBO and restore previous one // Most of the time, previous->fbo will be 0 to bind the default buffer glBindFramebuffer(GL_FRAMEBUFFER, previous->fbo); // Restore the clip from the previous snapshot const Rect& clip = previous->clipRect; glScissor(clip.left, mHeight - clip.bottom, clip.getWidth(), clip.getHeight()); Layer* layer = current->layer; const Rect& rect = layer->layer; drawTextureRect(rect.left, rect.top, rect.right, rect.bottom, layer->texture, layer->alpha, layer->mode, layer->blend); LayerSize size(rect.getWidth(), rect.getHeight()); // Failing to add the layer to the cache should happen only if the // layer is too large if (!mLayerCache.put(size, layer)) { LAYER_LOGD("Deleting layer"); glDeleteFramebuffers(1, &layer->fbo); glDeleteTextures(1, &layer->texture); delete layer; } } /////////////////////////////////////////////////////////////////////////////// // Transforms /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -424,14 +430,9 @@ const Rect& OpenGLRenderer::getClipBounds() { } bool OpenGLRenderer::quickReject(float left, float top, float right, float bottom) { SkRect sr; sr.set(left, top, right, bottom); SkMatrix m; mSnapshot->transform.copyTo(m); m.mapRect(&sr); Rect r(left, top, right, bottom); mSnapshot->transform.mapRect(r); Rect r(sr.fLeft, sr.fTop, sr.fRight, sr.fBottom); return !mSnapshot->clipRect.intersects(r); } Loading Loading @@ -562,82 +563,6 @@ void OpenGLRenderer::drawRect(float left, float top, float right, float bottom, drawColorRect(left, top, right, bottom, color, mode); } void OpenGLRenderer::renderShadow(const ShadowTexture* texture, float x, float y, SkXfermode::Mode mode) { const float sx = x - texture->left + mShadowDx; const float sy = y - texture->top + mShadowDy; const GLfloat a = ((mShadowColor >> 24) & 0xFF) / 255.0f; const GLfloat r = a * ((mShadowColor >> 16) & 0xFF) / 255.0f; const GLfloat g = a * ((mShadowColor >> 8) & 0xFF) / 255.0f; const GLfloat b = a * ((mShadowColor ) & 0xFF) / 255.0f; GLuint textureUnit = 0; renderTextureAlpha8(texture, textureUnit, sx, sy, r, g, b, a, mode, false); } void OpenGLRenderer::renderTextureAlpha8(const Texture* texture, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool applyFilters) { // Describe the required shaders ProgramDescription description; description.hasTexture = true; description.hasAlpha8Texture = true; if (applyFilters) { if (mShader) { mShader->describe(description, mExtensions); } if (mColorFilter) { mColorFilter->describe(description, mExtensions); } } // Build and use the appropriate shader useProgram(mProgramCache.get(description)); // Setup the blending mode chooseBlending(true, mode); bindTexture(texture->id, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit); glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit); int texCoordsSlot = mCurrentProgram->getAttrib("texCoords"); glEnableVertexAttribArray(texCoordsSlot); // Setup attributes glVertexAttribPointer(mCurrentProgram->position, 2, GL_FLOAT, GL_FALSE, gMeshStride, &mMeshVertices[0].position[0]); glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, &mMeshVertices[0].texture[0]); // Setup uniforms mModelView.loadTranslate(x, y, 0.0f); mModelView.scale(texture->width, texture->height, 1.0f); mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); glUniform4f(mCurrentProgram->color, r, g, b, a); textureUnit++; if (applyFilters) { // Setup attributes and uniforms required by the shaders if (mShader) { mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit); } if (mColorFilter) { mColorFilter->setupProgram(mCurrentProgram); } } // Draw the mesh glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); glDisableVertexAttribArray(texCoordsSlot); } #define kStdStrikeThru_Offset (-6.0f / 21.0f) #define kStdUnderline_Offset (1.0f / 9.0f) #define kStdUnderline_Thickness (1.0f / 18.0f) void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint) { if (text == NULL || count == 0 || (paint->getAlpha() == 0 && paint->getXfermode() == NULL)) { Loading Loading @@ -668,7 +593,12 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, const ShadowTexture* shadow = mDropShadowCache.get(paint, text, bytesCount, count, mShadowRadius); const AutoTexture autoCleanup(shadow); renderShadow(shadow, x, y, mode); setupShadow(shadow, x, y, mode); // Draw the mesh glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); glDisableVertexAttribArray(mCurrentProgram->getAttrib("texCoords")); } uint32_t color = paint->getColor(); Loading @@ -677,94 +607,19 @@ void OpenGLRenderer::drawText(const char* text, int bytesCount, int count, const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; const GLfloat b = a * ((color ) & 0xFF) / 255.0f; mModelView.loadIdentity(); GLuint textureUnit = 0; // Needs to be set prior to calling FontRenderer::getTexture() glActiveTexture(gTextureUnits[textureUnit]); ProgramDescription description; description.hasTexture = true; description.hasAlpha8Texture = true; if (mShader) { mShader->describe(description, mExtensions); } if (mColorFilter) { mColorFilter->describe(description, mExtensions); } useProgram(mProgramCache.get(description)); mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); // Text is always blended, no need to check the shader chooseBlending(true, mode); bindTexture(mFontRenderer.getTexture(), GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit); glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit); int texCoordsSlot = mCurrentProgram->getAttrib("texCoords"); glEnableVertexAttribArray(texCoordsSlot); // Always premultiplied glUniform4f(mCurrentProgram->color, r, g, b, a); textureUnit++; // Setup attributes and uniforms required by the shaders if (mShader) { mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit); } if (mColorFilter) { mColorFilter->setupProgram(mCurrentProgram); } setupTextureAlpha8(mFontRenderer.getTexture(), 0, 0, textureUnit, x, y, r, g, b, a, mode, false, true); const Rect& clip = mSnapshot->getLocalClip(); mFontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glDisableVertexAttribArray(texCoordsSlot); glDisableVertexAttribArray(mCurrentProgram->getAttrib("texCoords")); // Handle underline and strike-through uint32_t flags = paint->getFlags(); if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) { float underlineWidth = length; // If length is > 0.0f, we already measured the text for the text alignment if (length <= 0.0f) { underlineWidth = paint->measureText(text, bytesCount); } float offsetX = 0; switch (paint->getTextAlign()) { case SkPaint::kCenter_Align: offsetX = underlineWidth * 0.5f; break; case SkPaint::kRight_Align: offsetX = underlineWidth; break; default: break; } if (underlineWidth > 0.0f) { float textSize = paint->getTextSize(); float height = textSize * kStdUnderline_Thickness; float left = x - offsetX; float top = 0.0f; float right = left + underlineWidth; float bottom = 0.0f; if (flags & SkPaint::kUnderlineText_Flag) { top = y + textSize * kStdUnderline_Offset; bottom = top + height; drawRect(left, top, right, bottom, paint); } if (flags & SkPaint::kStrikeThruText_Flag) { top = y + textSize * kStdStrikeThru_Offset; bottom = top + height; drawRect(left, top, right, bottom, paint); } } } drawTextDecorations(text, bytesCount, length, x, y, paint); } void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) { Loading @@ -787,7 +642,12 @@ void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) { const float x = texture->left - texture->offset; const float y = texture->top - texture->offset; renderTextureAlpha8(texture, textureUnit, x, y, r, g, b, a, mode, true); setupTextureAlpha8(texture, textureUnit, x, y, r, g, b, a, mode, true, true); // Draw the mesh glDrawArrays(GL_TRIANGLE_STRIP, 0, gMeshCount); glDisableVertexAttribArray(mCurrentProgram->getAttrib("texCoords")); } /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -837,6 +697,134 @@ void OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) { // Drawing implementation /////////////////////////////////////////////////////////////////////////////// void OpenGLRenderer::setupShadow(const ShadowTexture* texture, float x, float y, SkXfermode::Mode mode) { const float sx = x - texture->left + mShadowDx; const float sy = y - texture->top + mShadowDy; const GLfloat a = ((mShadowColor >> 24) & 0xFF) / 255.0f; const GLfloat r = a * ((mShadowColor >> 16) & 0xFF) / 255.0f; const GLfloat g = a * ((mShadowColor >> 8) & 0xFF) / 255.0f; const GLfloat b = a * ((mShadowColor ) & 0xFF) / 255.0f; GLuint textureUnit = 0; setupTextureAlpha8(texture, textureUnit, sx, sy, r, g, b, a, mode, true, false); } void OpenGLRenderer::setupTextureAlpha8(const Texture* texture, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool transforms, bool applyFilters) { setupTextureAlpha8(texture->id, texture->width, texture->height, textureUnit, x, y, r, g, b, a, mode, transforms, applyFilters); } void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool transforms, bool applyFilters) { // Describe the required shaders ProgramDescription description; description.hasTexture = true; description.hasAlpha8Texture = true; if (applyFilters) { if (mShader) { mShader->describe(description, mExtensions); } if (mColorFilter) { mColorFilter->describe(description, mExtensions); } } // Build and use the appropriate shader useProgram(mProgramCache.get(description)); // Setup the blending mode chooseBlending(true, mode); bindTexture(texture, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, textureUnit); glUniform1i(mCurrentProgram->getUniform("sampler"), textureUnit); int texCoordsSlot = mCurrentProgram->getAttrib("texCoords"); glEnableVertexAttribArray(texCoordsSlot); // Setup attributes glVertexAttribPointer(mCurrentProgram->position, 2, GL_FLOAT, GL_FALSE, gMeshStride, &mMeshVertices[0].position[0]); glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, gMeshStride, &mMeshVertices[0].texture[0]); // Setup uniforms if (transforms) { mModelView.loadTranslate(x, y, 0.0f); mModelView.scale(width, height, 1.0f); } else { mModelView.loadIdentity(); } mCurrentProgram->set(mOrthoMatrix, mModelView, mSnapshot->transform); glUniform4f(mCurrentProgram->color, r, g, b, a); textureUnit++; if (applyFilters) { // Setup attributes and uniforms required by the shaders if (mShader) { mShader->setupProgram(mCurrentProgram, mModelView, *mSnapshot, &textureUnit); } if (mColorFilter) { mColorFilter->setupProgram(mCurrentProgram); } } } #define kStdStrikeThru_Offset (-6.0f / 21.0f) #define kStdUnderline_Offset (1.0f / 9.0f) #define kStdUnderline_Thickness (1.0f / 18.0f) void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float length, float x, float y, SkPaint* paint) { // Handle underline and strike-through uint32_t flags = paint->getFlags(); if (flags & (SkPaint::kUnderlineText_Flag | SkPaint::kStrikeThruText_Flag)) { float underlineWidth = length; // If length is > 0.0f, we already measured the text for the text alignment if (length <= 0.0f) { underlineWidth = paint->measureText(text, bytesCount); } float offsetX = 0; switch (paint->getTextAlign()) { case SkPaint::kCenter_Align: offsetX = underlineWidth * 0.5f; break; case SkPaint::kRight_Align: offsetX = underlineWidth; break; default: break; } if (underlineWidth > 0.0f) { float textSize = paint->getTextSize(); float height = textSize * kStdUnderline_Thickness; float left = x - offsetX; float top = 0.0f; float right = left + underlineWidth; float bottom = 0.0f; if (flags & SkPaint::kUnderlineText_Flag) { top = y + textSize * kStdUnderline_Offset; bottom = top + height; drawRect(left, top, right, bottom, paint); } if (flags & SkPaint::kStrikeThruText_Flag) { top = y + textSize * kStdStrikeThru_Offset; bottom = top + height; drawRect(left, top, right, bottom, paint); } } } } void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom, int color, SkXfermode::Mode mode, bool ignoreTransform) { // If a shader is set, preserve only the alpha Loading
libs/hwui/OpenGLRenderer.h +44 −5 Original line number Diff line number Diff line Loading @@ -226,17 +226,17 @@ private: GLvoid* vertices, GLvoid* texCoords, GLvoid* indices, GLsizei elementsCount = 0); /** * Renders the specified shadow. * Prepares the renderer to draw the specified shadow. * * @param texture The shadow texture * @param x The x coordinate of the shadow * @param y The y coordinate of the shadow * @param mode The blending mode */ void renderShadow(const ShadowTexture* texture, float x, float y, SkXfermode::Mode mode); void setupShadow(const ShadowTexture* texture, float x, float y, SkXfermode::Mode mode); /** * Renders the specified Alpha8 texture as a rectangle. * Prepares the renderer to draw the specified Alpha8 texture as a rectangle. * * @param texture The texture to render with * @param textureUnit The texture unit to use, may be modified Loading @@ -247,11 +247,50 @@ private: * @param b The blue component of the color * @param a The alpha component of the color * @param mode The blending mode * @param transforms True if the matrix passed to the shader should be multiplied * by the model-view matrix * @param applyFilters Whether or not to take color filters and * shaders into account */ void renderTextureAlpha8(const Texture* texture, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool applyFilters); void setupTextureAlpha8(const Texture* texture, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool transforms, bool applyFilters); /** * Prepares the renderer to draw the specified Alpha8 texture as a rectangle. * * @param texture The texture to render with * @param width The width of the texture * @param height The height of the texture * @param textureUnit The texture unit to use, may be modified * @param x The x coordinate of the rectangle to draw * @param y The y coordinate of the rectangle to draw * @param r The red component of the color * @param g The green component of the color * @param b The blue component of the color * @param a The alpha component of the color * @param mode The blending mode * @param transforms True if the matrix passed to the shader should be multiplied * by the model-view matrix * @param applyFilters Whether or not to take color filters and * shaders into account */ void setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t height, GLuint& textureUnit, float x, float y, float r, float g, float b, float a, SkXfermode::Mode mode, bool transforms, bool applyFilters); /** * Draws text underline and strike-through if needed. * * @param text The text to decor * @param bytesCount The number of bytes in the text * @param length The length in pixels of the text, can be <= 0.0f to force a measurement * @param x The x coordinate where the text will be drawn * @param y The y coordinate where the text will be drawn * @param paint The paint to draw the text with */ void drawTextDecorations(const char* text, int bytesCount, float length, float x, float y, SkPaint* paint); /** * Resets the texture coordinates stored in mMeshVertices. Setting the values Loading
libs/hwui/Snapshot.h +7 −1 Original line number Diff line number Diff line Loading @@ -57,7 +57,8 @@ public: flags(0), previous(s), layer(NULL), fbo(s->fbo) { fbo(s->fbo), viewport(s->viewport) { if ((s->flags & Snapshot::kFlagClipSet) && !(s->flags & Snapshot::kFlagDirtyLocalClip)) { localClip.set(s->localClip); Loading Loading @@ -179,6 +180,11 @@ public: Layer* layer; GLuint fbo; /** * Current viewport. */ Rect viewport; /** * Contains the previous ortho matrix. */ Loading
libs/hwui/TextDropShadowCache.h +1 −1 Original line number Diff line number Diff line Loading @@ -47,7 +47,7 @@ struct ShadowText { ShadowText(const ShadowText& shadow): paint(shadow.paint), radius(shadow.radius), len(shadow.len), hash(shadow.hash) { text = new char[len]; text = new char[shadow.len]; memcpy(text, shadow.text, shadow.len); } Loading
tests/HwAccelerationTest/AndroidManifest.xml +9 −0 Original line number Diff line number Diff line Loading @@ -189,5 +189,14 @@ </intent-filter> </activity> <activity android:name="StackActivity" android:label="_Stacks"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>