Cleanup, better code reuse.
Change-Id: Ib86a7309ae579cce3b7cf464782c34e70a74c616
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index da5b9dd..700355a 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -562,82 +562,6 @@
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)) {
@@ -668,7 +592,12 @@
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();
@@ -677,94 +606,19 @@
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) {
@@ -787,7 +641,12 @@
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"));
}
///////////////////////////////////////////////////////////////////////////////
@@ -837,6 +696,135 @@
// 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
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 948ff13..49143a5 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -226,17 +226,17 @@
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
@@ -247,11 +247,50 @@
* @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
diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml
index 181b4c8..775dc249 100644
--- a/tests/HwAccelerationTest/AndroidManifest.xml
+++ b/tests/HwAccelerationTest/AndroidManifest.xml
@@ -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>
diff --git a/tests/HwAccelerationTest/src/com/google/android/test/hwui/StackActivity.java b/tests/HwAccelerationTest/src/com/google/android/test/hwui/StackActivity.java
new file mode 100644
index 0000000..46c790c
--- /dev/null
+++ b/tests/HwAccelerationTest/src/com/google/android/test/hwui/StackActivity.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.google.android.test.hwui;
+
+import android.app.Activity;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.view.Gravity;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AbsListView;
+import android.widget.ArrayAdapter;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.StackView;
+
+@SuppressWarnings({"UnusedDeclaration"})
+public class StackActivity extends Activity {
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ StackView stack = new StackView(this);
+ stack.setAdapter(new ArrayAdapter<Drawable>(this, android.R.layout.simple_list_item_1,
+ android.R.id.text1, new Drawable[] {
+ getResources().getDrawable(R.drawable.sunset1),
+ getResources().getDrawable(R.drawable.sunset2),
+ getResources().getDrawable(R.drawable.sunset1),
+ getResources().getDrawable(R.drawable.sunset2),
+ getResources().getDrawable(R.drawable.sunset1),
+ getResources().getDrawable(R.drawable.sunset2)
+ }) {
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ ImageView image;
+ if (convertView == null) {
+ image = new ImageView(StackActivity.this);
+ } else {
+ image = (ImageView) convertView;
+ }
+ image.setImageDrawable(getItem(position % getCount()));
+ return image;
+ }
+ });
+ stack.setDisplayedChild(0);
+
+ FrameLayout layout = new FrameLayout(this);
+ layout.addView(stack, new FrameLayout.LayoutParams(500, 500, Gravity.CENTER));
+ setContentView(layout);
+ }
+}