diff options
author | Romain Guy <romainguy@google.com> | 2013-01-04 19:05:13 -0800 |
---|---|---|
committer | Romain Guy <romainguy@google.com> | 2013-01-04 19:21:54 -0800 |
commit | 672433d90fab7383cd28beac9d4485b566a90940 (patch) | |
tree | 8e5088ba91b9a33aeffccd3b2c6f03b0c8e2b144 | |
parent | 5913148104f0b233d861fab2873befc865bf57c0 (diff) | |
download | frameworks_base-672433d90fab7383cd28beac9d4485b566a90940.zip frameworks_base-672433d90fab7383cd28beac9d4485b566a90940.tar.gz frameworks_base-672433d90fab7383cd28beac9d4485b566a90940.tar.bz2 |
Add visual profiling feature
When profiling is enabled with debug.hwui.profile set to true,
setting debug.hwui.profile_visualizer to true will display the
profiling data directly on screen.
Change-Id: I3d5fe3f0347090815087b1cbfce66b8e76d9347b
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 11 | ||||
-rw-r--r-- | core/java/android/view/HardwareRenderer.java | 365 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 39 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 25 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.h | 2 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 73 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 5 |
7 files changed, 415 insertions, 105 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index b64a06e..7739ff7 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -1013,6 +1013,17 @@ class GLES20Canvas extends HardwareCanvas { private static native void nDrawPath(int renderer, int path, int paint); private static native void nDrawRects(int renderer, int region, int paint); + void drawRects(float[] rects, int count, Paint paint) { + int modifiers = setupModifiers(paint, MODIFIER_COLOR_FILTER | MODIFIER_SHADER); + try { + nDrawRects(mRenderer, rects, count, paint.mNativePaint); + } finally { + if (modifiers != MODIFIER_NONE) nResetModifiers(mRenderer, modifiers); + } + } + + private static native void nDrawRects(int renderer, float[] rects, int count, int paint); + @Override public void drawPicture(Picture picture) { if (picture.createdFromStream) { diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java index 157c321..e50b36d 100644 --- a/core/java/android/view/HardwareRenderer.java +++ b/core/java/android/view/HardwareRenderer.java @@ -88,12 +88,27 @@ public abstract class HardwareRenderer { * Possible values: * "true", to enable profiling * "false", to disable profiling - * + * * @hide */ public static final String PROFILE_PROPERTY = "debug.hwui.profile"; /** + * System property used to enable or disable hardware rendering profiling + * visualization. The default value of this property is assumed to be false. + * + * This property is only taken into account when {@link #PROFILE_PROPERTY} is + * turned on. + * + * Possible values: + * "true", to enable on screen profiling + * "false", to disable on screen profiling + * + * @hide + */ + public static final String PROFILE_VISUALIZER_PROPERTY = "debug.hwui.profile_visualizer"; + + /** * System property used to specify the number of frames to be used * when doing hardware rendering profiling. * The default value of this property is #PROFILE_MAX_FRAMES. @@ -342,7 +357,7 @@ public abstract class HardwareRenderer { * Notifies EGL that the frame is about to be rendered. * @param size */ - private static void beginFrame(int[] size) { + static void beginFrame(int[] size) { nBeginFrame(size); } @@ -648,10 +663,14 @@ public abstract class HardwareRenderer { boolean mUpdateDirtyRegions; boolean mProfileEnabled; + boolean mProfileVisualizerEnabled; float[] mProfileData; ReentrantLock mProfileLock; int mProfileCurrentFrame = -PROFILE_FRAME_DATA_COUNT; - + + float[][] mProfileRects; + Paint mProfilePaint; + boolean mDebugDirtyRegions; boolean mShowOverdraw; @@ -698,6 +717,18 @@ public abstract class HardwareRenderer { mProfileData = null; mProfileLock = null; } + + mProfileRects = null; + mProfilePaint = null; + } + + value = SystemProperties.getBoolean(PROFILE_VISUALIZER_PROPERTY, false); + if (value != mProfileVisualizerEnabled) { + changed = true; + mProfileVisualizerEnabled = value; + + mProfileRects = null; + mProfilePaint = null; } value = SystemProperties.getBoolean(DEBUG_DIRTY_REGIONS_PROPERTY, false); @@ -1175,23 +1206,7 @@ public abstract class HardwareRenderer { mProfileLock.lock(); } - // We had to change the current surface and/or context, redraw everything - if (surfaceState == SURFACE_STATE_UPDATED) { - dirty = null; - beginFrame(null); - } else { - int[] size = mSurfaceSize; - beginFrame(size); - - if (size[1] != mHeight || size[0] != mWidth) { - mWidth = size[0]; - mHeight = size[1]; - - canvas.setViewport(mWidth, mHeight); - - dirty = null; - } - } + dirty = beginFrame(canvas, dirty, surfaceState); int saveCount = 0; int status = DisplayList.STATUS_DONE; @@ -1201,63 +1216,19 @@ public abstract class HardwareRenderer { == View.PFLAG_INVALIDATED; view.mPrivateFlags &= ~View.PFLAG_INVALIDATED; - long getDisplayListStartTime = 0; - if (mProfileEnabled) { - mProfileCurrentFrame += PROFILE_FRAME_DATA_COUNT; - if (mProfileCurrentFrame >= mProfileData.length) { - mProfileCurrentFrame = 0; - } - - getDisplayListStartTime = System.nanoTime(); - } - + long buildDisplayListStartTime = startBuildDisplayListProfiling(); canvas.clearLayerUpdates(); - DisplayList displayList; - Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList"); - try { - displayList = view.getDisplayList(); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_VIEW); - } + DisplayList displayList = buildDisplayList(view); + status = prepareFrame(dirty); - Trace.traceBegin(Trace.TRACE_TAG_VIEW, "prepareFrame"); - try { - status = onPreDraw(dirty); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_VIEW); - } saveCount = canvas.save(); callbacks.onHardwarePreDraw(canvas); - if (mProfileEnabled) { - long now = System.nanoTime(); - float total = (now - getDisplayListStartTime) * 0.000001f; - //noinspection PointlessArithmeticExpression - mProfileData[mProfileCurrentFrame] = total; - } + endBuildDisplayListProfiling(buildDisplayListStartTime); if (displayList != null) { - long drawDisplayListStartTime = 0; - if (mProfileEnabled) { - drawDisplayListStartTime = System.nanoTime(); - } - - Trace.traceBegin(Trace.TRACE_TAG_VIEW, "drawDisplayList"); - try { - status |= canvas.drawDisplayList(displayList, mRedrawClip, - DisplayList.FLAG_CLIP_CHILDREN); - } finally { - Trace.traceEnd(Trace.TRACE_TAG_VIEW); - } - - if (mProfileEnabled) { - long now = System.nanoTime(); - float total = (now - drawDisplayListStartTime) * 0.000001f; - mProfileData[mProfileCurrentFrame + 1] = total; - } - - handleFunctorStatus(attachInfo, status); + status = drawDisplayList(attachInfo, canvas, displayList, status); } else { // Shouldn't reach here view.draw(canvas); @@ -1269,43 +1240,19 @@ public abstract class HardwareRenderer { mFrameCount++; - if (mDebugDirtyRegions) { - if (mDebugPaint == null) { - mDebugPaint = new Paint(); - mDebugPaint.setColor(0x7fff0000); - } - - if (dirty != null && (mFrameCount & 1) == 0) { - canvas.drawRect(dirty, mDebugPaint); - } - } + debugDirtyRegions(dirty, canvas); + drawProfileData(); } onPostDraw(); - attachInfo.mIgnoreDirtyState = false; - - if ((status & DisplayList.STATUS_DREW) == DisplayList.STATUS_DREW) { - long eglSwapBuffersStartTime = 0; - if (mProfileEnabled) { - eglSwapBuffersStartTime = System.nanoTime(); - } - - sEgl.eglSwapBuffers(sEglDisplay, mEglSurface); - - if (mProfileEnabled) { - long now = System.nanoTime(); - float total = (now - eglSwapBuffersStartTime) * 0.000001f; - mProfileData[mProfileCurrentFrame + 2] = total; - } - - checkEglErrors(); - } + swapBuffers(status); if (mProfileEnabled) { mProfileLock.unlock(); } + attachInfo.mIgnoreDirtyState = false; return dirty == null; } } @@ -1313,6 +1260,133 @@ public abstract class HardwareRenderer { return false; } + abstract void drawProfileData(); + + private Rect beginFrame(HardwareCanvas canvas, Rect dirty, int surfaceState) { + // We had to change the current surface and/or context, redraw everything + if (surfaceState == SURFACE_STATE_UPDATED) { + dirty = null; + beginFrame(null); + } else { + int[] size = mSurfaceSize; + beginFrame(size); + + if (size[1] != mHeight || size[0] != mWidth) { + mWidth = size[0]; + mHeight = size[1]; + + canvas.setViewport(mWidth, mHeight); + + dirty = null; + } + } + + if (mProfileEnabled && mProfileVisualizerEnabled) dirty = null; + + return dirty; + } + + private long startBuildDisplayListProfiling() { + if (mProfileEnabled) { + mProfileCurrentFrame += PROFILE_FRAME_DATA_COUNT; + if (mProfileCurrentFrame >= mProfileData.length) { + mProfileCurrentFrame = 0; + } + + return System.nanoTime(); + } + return 0; + } + + private void endBuildDisplayListProfiling(long getDisplayListStartTime) { + if (mProfileEnabled) { + long now = System.nanoTime(); + float total = (now - getDisplayListStartTime) * 0.000001f; + //noinspection PointlessArithmeticExpression + mProfileData[mProfileCurrentFrame] = total; + } + } + + private static DisplayList buildDisplayList(View view) { + DisplayList displayList; + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "getDisplayList"); + try { + displayList = view.getDisplayList(); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + } + return displayList; + } + + private int prepareFrame(Rect dirty) { + int status; + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "prepareFrame"); + try { + status = onPreDraw(dirty); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + } + return status; + } + + private int drawDisplayList(View.AttachInfo attachInfo, HardwareCanvas canvas, + DisplayList displayList, int status) { + + long drawDisplayListStartTime = 0; + if (mProfileEnabled) { + drawDisplayListStartTime = System.nanoTime(); + } + + Trace.traceBegin(Trace.TRACE_TAG_VIEW, "drawDisplayList"); + try { + status |= canvas.drawDisplayList(displayList, mRedrawClip, + DisplayList.FLAG_CLIP_CHILDREN); + } finally { + Trace.traceEnd(Trace.TRACE_TAG_VIEW); + } + + if (mProfileEnabled) { + long now = System.nanoTime(); + float total = (now - drawDisplayListStartTime) * 0.000001f; + mProfileData[mProfileCurrentFrame + 1] = total; + } + + handleFunctorStatus(attachInfo, status); + return status; + } + + private void swapBuffers(int status) { + if ((status & DisplayList.STATUS_DREW) == DisplayList.STATUS_DREW) { + long eglSwapBuffersStartTime = 0; + if (mProfileEnabled) { + eglSwapBuffersStartTime = System.nanoTime(); + } + + sEgl.eglSwapBuffers(sEglDisplay, mEglSurface); + + if (mProfileEnabled) { + long now = System.nanoTime(); + float total = (now - eglSwapBuffersStartTime) * 0.000001f; + mProfileData[mProfileCurrentFrame + 2] = total; + } + + checkEglErrors(); + } + } + + private void debugDirtyRegions(Rect dirty, HardwareCanvas canvas) { + if (mDebugDirtyRegions) { + if (mDebugPaint == null) { + mDebugPaint = new Paint(); + mDebugPaint.setColor(0x7fff0000); + } + + if (dirty != null && (mFrameCount & 1) == 0) { + canvas.drawRect(dirty, mDebugPaint); + } + } + } + private void handleFunctorStatus(View.AttachInfo attachInfo, int status) { // If the draw flag is set, functors will be invoked while executing // the tree of display lists @@ -1389,6 +1463,15 @@ public abstract class HardwareRenderer { * Hardware renderer using OpenGL ES 2.0. */ static class Gl20Renderer extends GlRenderer { + // TODO: Convert dimensions to dp instead of px + private static final int PROFILE_DRAW_MARGIN = 1; + private static final int PROFILE_DRAW_WIDTH = 3; + private static final int[] PROFILE_DRAW_COLORS = { 0xff3e66cc, 0xffdc3912, 0xffe69800 }; + private static final int PROFILE_DRAW_THRESHOLD_COLOR = 0xff5faa4d; + private static final int PROFILE_DRAW_THRESHOLD_STROKE_WIDTH = 2; + private static final int PROFILE_DRAW_CURRENT_FRAME_COLOR = 0xff5faa4d; + private static final int PROFILE_DRAW_PX_PER_MS = 10; + private GLES20Canvas mGlCanvas; private static EGLSurface sPbuffer; @@ -1494,6 +1577,94 @@ public abstract class HardwareRenderer { } @Override + void drawProfileData() { + if (mProfileEnabled && mProfileVisualizerEnabled) { + initProfileDrawData(); + + int x = 0; + int count = 0; + int current = 0; + + for (int i = 0; i < mProfileData.length; i += PROFILE_FRAME_DATA_COUNT) { + if (mProfileData[i] < 0.0f) break; + + int index = count * 4; + if (i == mProfileCurrentFrame) current = index; + + x += PROFILE_DRAW_MARGIN; + int x2 = x + PROFILE_DRAW_WIDTH; + + int y2 = mHeight; + int y1 = (int) (y2 - mProfileData[i] * PROFILE_DRAW_PX_PER_MS); + + float[] r = mProfileRects[0]; + r[index] = x; + r[index + 1] = y1; + r[index + 2] = x2; + r[index + 3] = y2; + + y2 = y1; + y1 = (int) (y2 - mProfileData[i + 1] * PROFILE_DRAW_PX_PER_MS); + + r = mProfileRects[1]; + r[index] = x; + r[index + 1] = y1; + r[index + 2] = x2; + r[index + 3] = y2; + + y2 = y1; + y1 = (int) (y2 - mProfileData[i + 2] * PROFILE_DRAW_PX_PER_MS); + + r = mProfileRects[2]; + r[index] = x; + r[index + 1] = y1; + r[index + 2] = x2; + r[index + 3] = y2; + + x += PROFILE_DRAW_WIDTH; + + count++; + } + + drawGraph(count); + drawCurrentFrame(current); + drawThreshold(x + PROFILE_DRAW_MARGIN); + } + } + + private void drawGraph(int count) { + for (int i = 0; i < mProfileRects.length; i++) { + mProfilePaint.setColor(PROFILE_DRAW_COLORS[i]); + mGlCanvas.drawRects(mProfileRects[i], count, mProfilePaint); + } + } + + private void drawCurrentFrame(int index) { + mProfilePaint.setColor(PROFILE_DRAW_CURRENT_FRAME_COLOR); + mGlCanvas.drawRect(mProfileRects[2][index], mProfileRects[2][index + 1], + mProfileRects[2][index + 2], mProfileRects[0][index + 3], mProfilePaint); + } + + private void drawThreshold(int x) { + mProfilePaint.setColor(PROFILE_DRAW_THRESHOLD_COLOR); + mProfilePaint.setStrokeWidth(PROFILE_DRAW_THRESHOLD_STROKE_WIDTH); + int y = mHeight - 16 * 10; + mGlCanvas.drawLine(0.0f, y, x, y, mProfilePaint); + mProfilePaint.setStrokeWidth(1.0f); + } + + private void initProfileDrawData() { + if (mProfileRects == null) { + mProfileRects = new float[PROFILE_FRAME_DATA_COUNT][]; + for (int i = 0; i < mProfileRects.length; i++) { + int count = mProfileData.length / PROFILE_FRAME_DATA_COUNT; + mProfileRects[i] = new float[count * 4]; + } + mProfilePaint = new Paint(); + } + } + + @Override void destroy(boolean full) { try { super.destroy(full); diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index d8d55b2..7d886da 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -449,16 +449,40 @@ static void android_view_GLES20Canvas_drawArc(JNIEnv* env, jobject clazz, renderer->drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint); } -static void android_view_GLES20Canvas_drawRects(JNIEnv* env, jobject clazz, +static void android_view_GLES20Canvas_drawRegionAsRects(JNIEnv* env, jobject clazz, OpenGLRenderer* renderer, SkRegion* region, SkPaint* paint) { - SkRegion::Iterator it(*region); - while (!it.done()) { - const SkIRect& r = it.rect(); - renderer->drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint); - it.next(); + if (paint->getStyle() != SkPaint::kFill_Style || + (paint->isAntiAlias() && !renderer->isCurrentTransformSimple())) { + SkRegion::Iterator it(*region); + while (!it.done()) { + const SkIRect& r = it.rect(); + renderer->drawRect(r.fLeft, r.fTop, r.fRight, r.fBottom, paint); + it.next(); + } + } else { + int count = 0; + Vector<float> rects; + SkRegion::Iterator it(*region); + while (!it.done()) { + const SkIRect& r = it.rect(); + rects.push(r.fLeft); + rects.push(r.fTop); + rects.push(r.fRight); + rects.push(r.fBottom); + count++; + it.next(); + } + renderer->drawRects(rects.array(), count, paint); } } +static void android_view_GLES20Canvas_drawRects(JNIEnv* env, jobject clazz, + OpenGLRenderer* renderer, jfloatArray rects, jint count, SkPaint* paint) { + jfloat* storage = env->GetFloatArrayElements(rects, NULL); + renderer->drawRects(storage, count, paint); + env->ReleaseFloatArrayElements(rects, storage, 0); +} + static void android_view_GLES20Canvas_drawPoints(JNIEnv* env, jobject clazz, OpenGLRenderer* renderer, jfloatArray points, jint offset, jint count, SkPaint* paint) { jfloat* storage = env->GetFloatArrayElements(points, NULL); @@ -958,7 +982,8 @@ static JNINativeMethod gMethods[] = { { "nDrawColor", "(III)V", (void*) android_view_GLES20Canvas_drawColor }, { "nDrawRect", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawRect }, - { "nDrawRects", "(III)V", (void*) android_view_GLES20Canvas_drawRects }, + { "nDrawRects", "(III)V", (void*) android_view_GLES20Canvas_drawRegionAsRects }, + { "nDrawRects", "(I[FII)V", (void*) android_view_GLES20Canvas_drawRects }, { "nDrawRoundRect", "(IFFFFFFI)V", (void*) android_view_GLES20Canvas_drawRoundRect }, { "nDrawCircle", "(IFFFI)V", (void*) android_view_GLES20Canvas_drawCircle }, { "nDrawOval", "(IFFFFI)V", (void*) android_view_GLES20Canvas_drawOval }, diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 7a38b40..747856c 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -64,6 +64,7 @@ const char* DisplayList::OP_NAMES[] = { "DrawTextOnPath", "DrawPosText", "DrawText", + "DrawRects", "ResetShader", "SetupShader", "ResetColorFilter", @@ -633,6 +634,13 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) { text.text(), text.length(), count, paint); } break; + case DrawRects: { + int32_t count = 0; + float* rects = getFloats(count); + SkPaint* paint = getPaint(renderer); + ALOGD("%s%s %d, %p", (char*) indent, OP_NAMES[op], count / 4, paint); + } + break; case ResetShader: { ALOGD("%s%s", (char*) indent, OP_NAMES[op]); } @@ -1277,6 +1285,14 @@ status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flag x, y, positions, paint, length); } break; + case DrawRects: { + int32_t count = 0; + float* rects = getFloats(count); + SkPaint* paint = getPaint(renderer); + DISPLAY_LIST_LOGD("%s%s %d, %p", (char*) indent, OP_NAMES[op], count, paint); + drawGlStatus |= renderer.drawRects(rects, count / 4, paint); + } + break; case ResetShader: { DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]); renderer.resetShader(); @@ -1814,6 +1830,15 @@ status_t DisplayListRenderer::drawText(const char* text, int bytesCount, int cou return DrawGlInfo::kStatusDone; } +status_t DisplayListRenderer::drawRects(const float* rects, int count, SkPaint* paint) { + if (count <= 0) return DrawGlInfo::kStatusDone; + + addOp(DisplayList::DrawRects); + addFloats(rects, count * 4); + addPaint(paint); + return DrawGlInfo::kStatusDone; +} + void DisplayListRenderer::resetShader() { addOp(DisplayList::ResetShader); } diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index e42def5..fb01753 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -106,6 +106,7 @@ public: DrawTextOnPath, DrawPosText, DrawText, + DrawRects, ResetShader, SetupShader, ResetColorFilter, @@ -608,6 +609,7 @@ public: const float* positions, SkPaint* paint); virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y, const float* positions, SkPaint* paint, float length); + virtual status_t drawRects(const float* rects, int count, SkPaint* paint); virtual void resetShader(); virtual void setupShader(SkiaShader* shader); diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index ca9a38e..4b1d8ec 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1254,7 +1254,8 @@ bool OpenGLRenderer::quickRejectNoScissor(float left, float top, float right, fl return !clip.intersects(transformed); } -bool OpenGLRenderer::quickRejectPreStroke(float left, float top, float right, float bottom, SkPaint* paint) { +bool OpenGLRenderer::quickRejectPreStroke(float left, float top, float right, float bottom, + SkPaint* paint) { if (paint->getStyle() != SkPaint::kFill_Style) { float outset = paint->getStrokeWidth() * 0.5f; return quickReject(left - outset, top - outset, right + outset, bottom + outset); @@ -3030,6 +3031,76 @@ void OpenGLRenderer::drawTextDecorations(const char* text, int bytesCount, float } } +status_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint) { + if (mSnapshot->isIgnored()) { + return DrawGlInfo::kStatusDone; + } + + float left = FLT_MAX; + float top = FLT_MAX; + float right = FLT_MIN; + float bottom = FLT_MIN; + + int vertexCount = 0; + Vertex mesh[count * 6]; + Vertex* vertex = mesh; + + for (int i = 0; i < count; i++) { + int index = i * 4; + float l = rects[index + 0]; + float t = rects[index + 1]; + float r = rects[index + 2]; + float b = rects[index + 3]; + + if (!quickRejectNoScissor(left, top, right, bottom)) { + Vertex::set(vertex++, l, b); + Vertex::set(vertex++, l, t); + Vertex::set(vertex++, r, t); + Vertex::set(vertex++, l, b); + Vertex::set(vertex++, r, t); + Vertex::set(vertex++, r, b); + + vertexCount += 6; + + left = fminf(left, l); + top = fminf(top, t); + right = fmaxf(right, r); + bottom = fmaxf(bottom, b); + } + } + + if (count == 0) return DrawGlInfo::kStatusDone; + + int color = paint->getColor(); + // If a shader is set, preserve only the alpha + if (mShader) { + color |= 0x00ffffff; + } + SkXfermode::Mode mode = getXfermode(paint->getXfermode()); + + setupDraw(); + setupDrawNoTexture(); + setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha); + setupDrawShader(); + setupDrawColorFilter(); + setupDrawBlending(mode); + setupDrawProgram(); + setupDrawDirtyRegionsDisabled(); + setupDrawModelView(0.0f, 0.0f, 1.0f, 1.0f); + setupDrawColorUniforms(); + setupDrawShaderUniforms(); + setupDrawColorFilterUniforms(); + setupDrawVertices((GLvoid*) &mesh[0].position[0]); + + if (hasLayer()) { + dirtyLayer(left, top, right, bottom, *mSnapshot->transform); + } + + glDrawArrays(GL_TRIANGLES, 0, vertexCount); + + return DrawGlInfo::kStatusDrew; +} + 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 f165581..b1d3cc3 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -201,6 +201,7 @@ public: const float* positions, SkPaint* paint); virtual status_t drawText(const char* text, int bytesCount, int count, float x, float y, const float* positions, SkPaint* paint, float length = -1.0f); + virtual status_t drawRects(const float* rects, int count, SkPaint* paint); virtual void resetShader(); virtual void setupShader(SkiaShader* shader); @@ -216,6 +217,10 @@ public: SkPaint* filterPaint(SkPaint* paint); + ANDROID_API bool isCurrentTransformSimple() { + return mSnapshot->transform->isSimple(); + } + /** * Sets the alpha on the current snapshot. This alpha value will be modulated * with other alpha values when drawing primitives. |