diff options
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 13 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 10 | ||||
-rw-r--r-- | libs/hwui/Line.h | 126 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 65 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 15 | ||||
-rw-r--r-- | libs/hwui/Patch.cpp | 13 | ||||
-rw-r--r-- | libs/hwui/Patch.h | 10 | ||||
-rw-r--r-- | libs/hwui/Rect.h | 2 | ||||
-rw-r--r-- | libs/hwui/SkiaShader.cpp | 23 | ||||
-rw-r--r-- | libs/hwui/SkiaShader.h | 6 | ||||
-rw-r--r-- | tests/HwAccelerationTest/AndroidManifest.xml | 2 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java | 4 |
12 files changed, 265 insertions, 24 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index e0c4b14..f917001 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -537,17 +537,24 @@ class GLES20Canvas extends Canvas { mLine[1] = startY; mLine[2] = stopX; mLine[3] = stopY; - drawLines(mLine, 0, 1, paint); + drawLines(mLine, 0, 4, paint); } @Override public void drawLines(float[] pts, int offset, int count, Paint paint) { - // TODO: Implement + if ((offset | count) < 0 || offset + count > pts.length) { + throw new IllegalArgumentException("The lines array must contain 4 elements per line."); + } + boolean hasModifier = setupModifiers(paint); + nDrawLines(mRenderer, pts, offset, count, paint.mNativePaint); + if (hasModifier) nResetModifiers(mRenderer); } + private native void nDrawLines(int renderer, float[] points, int offset, int count, int paint); + @Override public void drawLines(float[] pts, Paint paint) { - drawLines(pts, 0, pts.length / 4, paint); + drawLines(pts, 0, pts.length, paint); } @Override diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index a61a9d1..3a85bc1 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -265,6 +265,15 @@ static void android_view_GLES20Canvas_drawPath(JNIEnv* env, jobject canvas, renderer->drawPath(path, paint); } +static void android_view_GLES20Canvas_drawLines(JNIEnv* env, jobject canvas, + OpenGLRenderer* renderer, jfloatArray points, jint offset, jint count, SkPaint* paint) { + jfloat* storage = env->GetFloatArrayElements(points, NULL); + + renderer->drawLines(storage + offset, count, paint); + + env->ReleaseFloatArrayElements(points, storage, 0); +} + // ---------------------------------------------------------------------------- // Shaders and color filters // ---------------------------------------------------------------------------- @@ -421,6 +430,7 @@ static JNINativeMethod gMethods[] = { { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect }, { "nDrawRects", "(III)V", (void*) android_view_GLES20Canvas_drawRects }, { "nDrawPath", "(III)V", (void*) android_view_GLES20Canvas_drawPath }, + { "nDrawLines", "(I[FIII)V", (void*) android_view_GLES20Canvas_drawLines }, { "nResetModifiers", "(I)V", (void*) android_view_GLES20Canvas_resetModifiers }, { "nSetupShader", "(II)V", (void*) android_view_GLES20Canvas_setupShader }, diff --git a/libs/hwui/Line.h b/libs/hwui/Line.h new file mode 100644 index 0000000..48e18eb --- /dev/null +++ b/libs/hwui/Line.h @@ -0,0 +1,126 @@ +/* + * 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. + */ + +#ifndef ANDROID_UI_LINE_H +#define ANDROID_UI_LINE_H + +#include <GLES2/gl2.h> + +#include <cmath> + +#include <sys/types.h> + +#include "Patch.h" + +namespace android { +namespace uirenderer { + +/////////////////////////////////////////////////////////////////////////////// +// Globals +/////////////////////////////////////////////////////////////////////////////// + +// Alpha8 texture used to perform texture anti-aliasing +static const uint8_t gLineTexture[] = { + 0, 0, 0, 0, 0, + 0, 255, 255, 255, 0, + 0, 255, 255, 255, 0, + 0, 255, 255, 255, 0, + 0, 0, 0, 0, 0 +}; +static const GLsizei gLineTextureWidth = 5; +static const GLsizei gLineTextureHeight = 5; +static const float gLineAABias = 1.0f; + +/////////////////////////////////////////////////////////////////////////////// +// Line +/////////////////////////////////////////////////////////////////////////////// + +class Line { +public: + Line(): mXDivsCount(2), mYDivsCount(2) { + mPatch = new Patch(mXDivsCount, mYDivsCount); + mXDivs = new int32_t[mXDivsCount]; + mYDivs = new int32_t[mYDivsCount]; + + mXDivs[0] = mYDivs[0] = 2; + mXDivs[1] = mYDivs[1] = 3; + + glGenTextures(1, &mTexture); + glBindTexture(GL_TEXTURE_2D, mTexture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, gLineTextureWidth, gLineTextureHeight, 0, + GL_ALPHA, GL_UNSIGNED_BYTE, gLineTexture); + } + + ~Line() { + delete mPatch; + delete mXDivs; + delete mYDivs; + + glDeleteTextures(1, &mTexture); + } + + void update(float x1, float y1, float x2, float y2, float lineWidth, float& tx, float& ty) { + const float length = sqrtf((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); + const float half = lineWidth * 0.5f; + + mPatch->updateVertices(gLineTextureWidth, gLineTextureHeight, + -gLineAABias, -half - gLineAABias, length + gLineAABias, half + gLineAABias, + mXDivs, mYDivs, mXDivsCount, mYDivsCount); + + tx = -gLineAABias; + ty = -half - gLineAABias; + } + + inline GLvoid* getVertices() const { + return &mPatch->vertices[0].position[0]; + } + + inline GLvoid* getTexCoords() const { + return &mPatch->vertices[0].texture[0]; + } + + inline GLsizei getElementsCount() const { + return mPatch->verticesCount; + } + + inline GLuint getTexture() const { + return mTexture; + } + +private: + uint32_t mXDivsCount; + uint32_t mYDivsCount; + + int32_t* mXDivs; + int32_t* mYDivs; + + Patch* mPatch; + + GLuint mTexture; +}; // class Line + +}; // namespace uirenderer +}; // namespace android + +#endif // ANDROID_UI_LINE_H diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index d6c0053..ecc02fa 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -39,6 +39,9 @@ namespace uirenderer { // Generates simple and textured vertices #define FV(x, y, u, v) { { x, y }, { u, v } } +#define RAD_TO_DEG (180.0f / 3.14159265f) +#define MIN_ANGLE 0.001f + /////////////////////////////////////////////////////////////////////////////// // Globals /////////////////////////////////////////////////////////////////////////////// @@ -588,7 +591,7 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, getAlphaAndMode(paint, &alpha, &mode); Patch* mesh = mCaches.patchCache.get(patch); - mesh->updateVertices(bitmap, left, top, right, bottom, + mesh->updateVertices(bitmap->width(), bitmap->height(),left, top, right, bottom, &patch->xDivs[0], &patch->yDivs[0], patch->numXDivs, patch->numYDivs); // Specify right and bottom as +1.0f from left/top to prevent scaling since the @@ -598,6 +601,50 @@ void OpenGLRenderer::drawPatch(SkBitmap* bitmap, Res_png_9patch* patch, &mesh->vertices[0].texture[0], GL_TRIANGLES, mesh->verticesCount); } +void OpenGLRenderer::drawLines(float* points, int count, const SkPaint* paint) { + int alpha; + SkXfermode::Mode mode; + getAlphaAndMode(paint, &alpha, &mode); + + uint32_t color = paint->getColor(); + const GLfloat a = alpha / 255.0f; + const GLfloat r = a * ((color >> 16) & 0xFF) / 255.0f; + const GLfloat g = a * ((color >> 8) & 0xFF) / 255.0f; + const GLfloat b = a * ((color ) & 0xFF) / 255.0f; + + GLuint textureUnit = 0; + setupTextureAlpha8(mLine.getTexture(), 0, 0, textureUnit, 0.0f, 0.0f, r, g, b, a, + mode, false, true, mLine.getVertices(), mLine.getTexCoords()); + + for (int i = 0; i < count; i += 4) { + float tx = 0.0f; + float ty = 0.0f; + + mLine.update(points[i], points[i + 1], points[i + 2], points[i + 3], + paint->getStrokeWidth(), tx, ty); + + const float dx = points[i + 2] - points[i]; + const float dy = points[i + 3] - points[i + 1]; + const float mag = sqrtf(dx * dx + dy * dy); + const float angle = acos(dx / mag); + + mModelView.loadTranslate(points[i], points[i + 1], 0.0f); + if (angle > MIN_ANGLE || angle < -MIN_ANGLE) { + mModelView.rotate(angle * RAD_TO_DEG, 0.0f, 0.0f, 1.0f); + } + mModelView.translate(tx, ty, 0.0f); + mCaches.currentProgram->set(mOrthoMatrix, mModelView, *mSnapshot->transform); + + if (mShader) { + mShader->updateTransforms(mCaches.currentProgram, mModelView, *mSnapshot); + } + + glDrawArrays(GL_TRIANGLES, 0, mLine.getElementsCount()); + } + + glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords")); +} + void OpenGLRenderer::drawColor(int color, SkXfermode::Mode mode) { const Rect& clip = *mSnapshot->clipRect; drawColorRect(clip.left, clip.top, clip.right, clip.bottom, color, mode, true); @@ -793,12 +840,22 @@ void OpenGLRenderer::setupTextureAlpha8(const Texture* texture, GLuint& textureU 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); + x, y, r, g, b, a, mode, transforms, applyFilters, + &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]); } 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) { + setupTextureAlpha8(texture, width, height, textureUnit, + x, y, r, g, b, a, mode, transforms, applyFilters, + &mMeshVertices[0].position[0], &mMeshVertices[0].texture[0]); +} + +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, + GLvoid* vertices, GLvoid* texCoords) { // Describe the required shaders ProgramDescription description; description.hasTexture = true; @@ -827,9 +884,9 @@ void OpenGLRenderer::setupTextureAlpha8(GLuint texture, uint32_t width, uint32_t // Setup attributes glVertexAttribPointer(mCaches.currentProgram->position, 2, GL_FLOAT, GL_FALSE, - gMeshStride, &mMeshVertices[0].position[0]); + gMeshStride, vertices); glVertexAttribPointer(texCoordsSlot, 2, GL_FLOAT, GL_FALSE, - gMeshStride, &mMeshVertices[0].texture[0]); + gMeshStride, texCoords); // Setup uniforms if (transforms) { diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index 387fb12..cd7963f 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -40,6 +40,7 @@ #include "SkiaShader.h" #include "SkiaColorFilter.h" #include "Caches.h" +#include "Line.h" namespace android { namespace uirenderer { @@ -99,6 +100,7 @@ public: void drawColor(int color, SkXfermode::Mode mode); void drawRect(float left, float top, float right, float bottom, const SkPaint* paint); void drawPath(SkPath* path, SkPaint* paint); + void drawLines(float* points, int count, const SkPaint* paint); void resetShader(); void setupShader(SkiaShader* shader); @@ -297,6 +299,15 @@ private: SkXfermode::Mode mode, bool transforms, bool applyFilters); /** + * Same as above setupTextureAlpha8() but specifies the mesh's vertices + * and texCoords pointers. + */ + 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, + GLvoid* vertices, GLvoid* texCoords); + + /** * Draws text underline and strike-through if needed. * * @param text The text to decor @@ -403,6 +414,10 @@ private: // List of rectangles to clear due to calls to saveLayer() Vector<Rect*> mLayers; + // Single object used to draw lines + Line mLine; + + // Misc GLint mMaxTextureSize; }; // class OpenGLRenderer diff --git a/libs/hwui/Patch.cpp b/libs/hwui/Patch.cpp index a660730..0a6eca3 100644 --- a/libs/hwui/Patch.cpp +++ b/libs/hwui/Patch.cpp @@ -16,11 +16,8 @@ #define LOG_TAG "OpenGLRenderer" -#include <cstring> #include <cmath> -#include <utils/Log.h> - #include "Patch.h" namespace android { @@ -34,7 +31,6 @@ Patch::Patch(const uint32_t xCount, const uint32_t yCount) { // 2 triangles per patch, 3 vertices per triangle verticesCount = (xCount + 1) * (yCount + 1) * 2 * 3; vertices = new TextureVertex[verticesCount]; - memset(vertices, 0, sizeof(TextureVertex) * verticesCount); } Patch::~Patch() { @@ -45,9 +41,9 @@ Patch::~Patch() { // Vertices management /////////////////////////////////////////////////////////////////////////////// -void Patch::updateVertices(const SkBitmap* bitmap, float left, float top, float right, - float bottom, const int32_t* xDivs, const int32_t* yDivs, const uint32_t width, - const uint32_t height) { +void Patch::updateVertices(const float bitmapWidth, const float bitmapHeight, + float left, float top, float right, float bottom, + const int32_t* xDivs, const int32_t* yDivs, const uint32_t width, const uint32_t height) { const uint32_t xStretchCount = (width + 1) >> 1; const uint32_t yStretchCount = (height + 1) >> 1; @@ -56,9 +52,6 @@ void Patch::updateVertices(const SkBitmap* bitmap, float left, float top, float const float meshWidth = right - left; - const float bitmapWidth = float(bitmap->width()); - const float bitmapHeight = float(bitmap->height()); - if (xStretchCount > 0) { uint32_t stretchSize = 0; for (uint32_t i = 1; i < width; i += 2) { diff --git a/libs/hwui/Patch.h b/libs/hwui/Patch.h index f712455..1d08c64 100644 --- a/libs/hwui/Patch.h +++ b/libs/hwui/Patch.h @@ -19,8 +19,6 @@ #include <sys/types.h> -#include <SkBitmap.h> - #include "Vertex.h" namespace android { @@ -59,8 +57,9 @@ struct Patch { Patch(const uint32_t xCount, const uint32_t yCount); ~Patch(); - void updateVertices(const SkBitmap* bitmap, float left, float top, float right, float bottom, - const int32_t* xDivs, const int32_t* yDivs, + void updateVertices(const float bitmapWidth, const float bitmapHeight, + float left, float top, float right, float bottom, + const int32_t* xDivs, const int32_t* yDivs, const uint32_t width, const uint32_t height); TextureVertex* vertices; @@ -70,7 +69,8 @@ private: static inline void generateRow(TextureVertex*& vertex, float y1, float y2, float v1, float v2, const int32_t xDivs[], uint32_t xCount, float stretchX, float width, float bitmapWidth); - static inline void generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2, + static inline void generateQuad(TextureVertex*& vertex, + float x1, float y1, float x2, float y2, float u1, float v1, float u2, float v2); }; // struct Patch diff --git a/libs/hwui/Rect.h b/libs/hwui/Rect.h index 5166ee9..f03a602 100644 --- a/libs/hwui/Rect.h +++ b/libs/hwui/Rect.h @@ -164,4 +164,4 @@ struct Rect { }; // namespace uirenderer }; // namespace android -#endif // ANDROID_RECT_H +#endif // ANDROID_UI_RECT_H diff --git a/libs/hwui/SkiaShader.cpp b/libs/hwui/SkiaShader.cpp index a5e0f78..946cc4b 100644 --- a/libs/hwui/SkiaShader.cpp +++ b/libs/hwui/SkiaShader.cpp @@ -128,6 +128,22 @@ void SkiaBitmapShader::setupProgram(Program* program, const mat4& modelView, glUniform2f(program->getUniform("textureDimension"), 1.0f / width, 1.0f / height); } +void SkiaBitmapShader::updateTransforms(Program* program, const mat4& modelView, + const Snapshot& snapshot) { + mat4 textureTransform; + if (mMatrix) { + SkMatrix inverse; + mMatrix->invert(&inverse); + textureTransform.load(inverse); + textureTransform.multiply(modelView); + } else { + textureTransform.load(modelView); + } + + glUniformMatrix4fv(program->getUniform("textureTransform"), 1, + GL_FALSE, &textureTransform.data[0]); +} + /////////////////////////////////////////////////////////////////////////////// // Linear gradient shader /////////////////////////////////////////////////////////////////////////////// @@ -185,6 +201,13 @@ void SkiaLinearGradientShader::setupProgram(Program* program, const mat4& modelV glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); } +void SkiaLinearGradientShader::updateTransforms(Program* program, const mat4& modelView, + const Snapshot& snapshot) { + mat4 screenSpace(*snapshot.transform); + screenSpace.multiply(modelView); + glUniformMatrix4fv(program->getUniform("screenSpace"), 1, GL_FALSE, &screenSpace.data[0]); +} + /////////////////////////////////////////////////////////////////////////////// // Compose shader /////////////////////////////////////////////////////////////////////////////// diff --git a/libs/hwui/SkiaShader.h b/libs/hwui/SkiaShader.h index d95e3b0..cc94ae6 100644 --- a/libs/hwui/SkiaShader.h +++ b/libs/hwui/SkiaShader.h @@ -73,6 +73,10 @@ struct SkiaShader { mGradientCache = gradientCache; } + virtual void updateTransforms(Program* program, const mat4& modelView, + const Snapshot& snapshot) { + } + void setMatrix(SkMatrix* matrix) { mMatrix = matrix; } @@ -106,6 +110,7 @@ struct SkiaBitmapShader: public SkiaShader { void describe(ProgramDescription& description, const Extensions& extensions); void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, GLuint* textureUnit); + void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot); private: /** @@ -130,6 +135,7 @@ struct SkiaLinearGradientShader: public SkiaShader { void describe(ProgramDescription& description, const Extensions& extensions); void setupProgram(Program* program, const mat4& modelView, const Snapshot& snapshot, GLuint* textureUnit); + void updateTransforms(Program* program, const mat4& modelView, const Snapshot& snapshot); private: float* mBounds; diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index 5597415..8a08c48 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -214,7 +214,7 @@ <activity android:name="LinesActivity" android:label="_Lines" - android:hardwareAccelerated="false"> + android:hardwareAccelerated="true"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java index 208dd88..4430533 100644 --- a/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/LinesActivity.java @@ -97,6 +97,10 @@ public class LinesActivity extends Activity { mLargePaint.setShader(null); canvas.drawLines(mPoints, mAlphaPaint); + + mSmallPaint.setAntiAlias(false); + canvas.drawLine(0.0f, 0.0f, 400.0f, 0.0f, mSmallPaint); + mSmallPaint.setAntiAlias(true); canvas.translate(120.0f, 0.0f); mAlphaPaint.setShader(mShader); |