Loading core/java/android/view/GLES20Canvas.java +11 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading core/java/android/view/HardwareRenderer.java +268 −97 Original line number Diff line number Diff line Loading @@ -93,6 +93,21 @@ public abstract class HardwareRenderer { */ 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. Loading Loading @@ -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); } Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -1175,6 +1206,63 @@ public abstract class HardwareRenderer { mProfileLock.lock(); } dirty = beginFrame(canvas, dirty, surfaceState); int saveCount = 0; int status = DisplayList.STATUS_DONE; try { view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED) == View.PFLAG_INVALIDATED; view.mPrivateFlags &= ~View.PFLAG_INVALIDATED; long buildDisplayListStartTime = startBuildDisplayListProfiling(); canvas.clearLayerUpdates(); DisplayList displayList = buildDisplayList(view); status = prepareFrame(dirty); saveCount = canvas.save(); callbacks.onHardwarePreDraw(canvas); endBuildDisplayListProfiling(buildDisplayListStartTime); if (displayList != null) { status = drawDisplayList(attachInfo, canvas, displayList, status); } else { // Shouldn't reach here view.draw(canvas); } } finally { callbacks.onHardwarePostDraw(canvas); canvas.restoreToCount(saveCount); view.mRecreateDisplayList = false; mFrameCount++; debugDirtyRegions(dirty, canvas); drawProfileData(); } onPostDraw(); swapBuffers(status); if (mProfileEnabled) { mProfileLock.unlock(); } attachInfo.mIgnoreDirtyState = false; return dirty == null; } } 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; Loading @@ -1193,26 +1281,33 @@ public abstract class HardwareRenderer { } } int saveCount = 0; int status = DisplayList.STATUS_DONE; if (mProfileEnabled && mProfileVisualizerEnabled) dirty = null; try { view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED) == View.PFLAG_INVALIDATED; view.mPrivateFlags &= ~View.PFLAG_INVALIDATED; return dirty; } long getDisplayListStartTime = 0; private long startBuildDisplayListProfiling() { if (mProfileEnabled) { mProfileCurrentFrame += PROFILE_FRAME_DATA_COUNT; if (mProfileCurrentFrame >= mProfileData.length) { mProfileCurrentFrame = 0; } getDisplayListStartTime = System.nanoTime(); return System.nanoTime(); } return 0; } canvas.clearLayerUpdates(); 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 { Loading @@ -1220,24 +1315,23 @@ public abstract class HardwareRenderer { } 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); } saveCount = canvas.save(); callbacks.onHardwarePreDraw(canvas); if (mProfileEnabled) { long now = System.nanoTime(); float total = (now - getDisplayListStartTime) * 0.000001f; //noinspection PointlessArithmeticExpression mProfileData[mProfileCurrentFrame] = total; return status; } if (displayList != null) { private int drawDisplayList(View.AttachInfo attachInfo, HardwareCanvas canvas, DisplayList displayList, int status) { long drawDisplayListStartTime = 0; if (mProfileEnabled) { drawDisplayListStartTime = System.nanoTime(); Loading @@ -1258,33 +1352,10 @@ public abstract class HardwareRenderer { } handleFunctorStatus(attachInfo, status); } else { // Shouldn't reach here view.draw(canvas); return status; } } finally { callbacks.onHardwarePostDraw(canvas); canvas.restoreToCount(saveCount); view.mRecreateDisplayList = false; mFrameCount++; if (mDebugDirtyRegions) { if (mDebugPaint == null) { mDebugPaint = new Paint(); mDebugPaint.setColor(0x7fff0000); } if (dirty != null && (mFrameCount & 1) == 0) { canvas.drawRect(dirty, mDebugPaint); } } } onPostDraw(); attachInfo.mIgnoreDirtyState = false; private void swapBuffers(int status) { if ((status & DisplayList.STATUS_DREW) == DisplayList.STATUS_DREW) { long eglSwapBuffersStartTime = 0; if (mProfileEnabled) { Loading @@ -1301,16 +1372,19 @@ public abstract class HardwareRenderer { checkEglErrors(); } } if (mProfileEnabled) { mProfileLock.unlock(); private void debugDirtyRegions(Rect dirty, HardwareCanvas canvas) { if (mDebugDirtyRegions) { if (mDebugPaint == null) { mDebugPaint = new Paint(); mDebugPaint.setColor(0x7fff0000); } return dirty == null; if (dirty != null && (mFrameCount & 1) == 0) { canvas.drawRect(dirty, mDebugPaint); } } return false; } private void handleFunctorStatus(View.AttachInfo attachInfo, int status) { Loading Loading @@ -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; Loading Loading @@ -1493,6 +1576,94 @@ public abstract class HardwareRenderer { mGlCanvas.onPostDraw(); } @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 { Loading core/jni/android_view_GLES20Canvas.cpp +32 −7 Original line number Diff line number Diff line Loading @@ -449,14 +449,38 @@ 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) { 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, Loading Loading @@ -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 }, Loading libs/hwui/DisplayListRenderer.cpp +25 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ const char* DisplayList::OP_NAMES[] = { "DrawTextOnPath", "DrawPosText", "DrawText", "DrawRects", "ResetShader", "SetupShader", "ResetColorFilter", Loading Loading @@ -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]); } Loading Loading @@ -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(); Loading Loading @@ -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); } Loading libs/hwui/DisplayListRenderer.h +2 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ public: DrawTextOnPath, DrawPosText, DrawText, DrawRects, ResetShader, SetupShader, ResetColorFilter, Loading Loading @@ -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); Loading Loading
core/java/android/view/GLES20Canvas.java +11 −0 Original line number Diff line number Diff line Loading @@ -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) { Loading
core/java/android/view/HardwareRenderer.java +268 −97 Original line number Diff line number Diff line Loading @@ -93,6 +93,21 @@ public abstract class HardwareRenderer { */ 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. Loading Loading @@ -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); } Loading Loading @@ -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; Loading Loading @@ -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); Loading Loading @@ -1175,6 +1206,63 @@ public abstract class HardwareRenderer { mProfileLock.lock(); } dirty = beginFrame(canvas, dirty, surfaceState); int saveCount = 0; int status = DisplayList.STATUS_DONE; try { view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED) == View.PFLAG_INVALIDATED; view.mPrivateFlags &= ~View.PFLAG_INVALIDATED; long buildDisplayListStartTime = startBuildDisplayListProfiling(); canvas.clearLayerUpdates(); DisplayList displayList = buildDisplayList(view); status = prepareFrame(dirty); saveCount = canvas.save(); callbacks.onHardwarePreDraw(canvas); endBuildDisplayListProfiling(buildDisplayListStartTime); if (displayList != null) { status = drawDisplayList(attachInfo, canvas, displayList, status); } else { // Shouldn't reach here view.draw(canvas); } } finally { callbacks.onHardwarePostDraw(canvas); canvas.restoreToCount(saveCount); view.mRecreateDisplayList = false; mFrameCount++; debugDirtyRegions(dirty, canvas); drawProfileData(); } onPostDraw(); swapBuffers(status); if (mProfileEnabled) { mProfileLock.unlock(); } attachInfo.mIgnoreDirtyState = false; return dirty == null; } } 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; Loading @@ -1193,26 +1281,33 @@ public abstract class HardwareRenderer { } } int saveCount = 0; int status = DisplayList.STATUS_DONE; if (mProfileEnabled && mProfileVisualizerEnabled) dirty = null; try { view.mRecreateDisplayList = (view.mPrivateFlags & View.PFLAG_INVALIDATED) == View.PFLAG_INVALIDATED; view.mPrivateFlags &= ~View.PFLAG_INVALIDATED; return dirty; } long getDisplayListStartTime = 0; private long startBuildDisplayListProfiling() { if (mProfileEnabled) { mProfileCurrentFrame += PROFILE_FRAME_DATA_COUNT; if (mProfileCurrentFrame >= mProfileData.length) { mProfileCurrentFrame = 0; } getDisplayListStartTime = System.nanoTime(); return System.nanoTime(); } return 0; } canvas.clearLayerUpdates(); 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 { Loading @@ -1220,24 +1315,23 @@ public abstract class HardwareRenderer { } 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); } saveCount = canvas.save(); callbacks.onHardwarePreDraw(canvas); if (mProfileEnabled) { long now = System.nanoTime(); float total = (now - getDisplayListStartTime) * 0.000001f; //noinspection PointlessArithmeticExpression mProfileData[mProfileCurrentFrame] = total; return status; } if (displayList != null) { private int drawDisplayList(View.AttachInfo attachInfo, HardwareCanvas canvas, DisplayList displayList, int status) { long drawDisplayListStartTime = 0; if (mProfileEnabled) { drawDisplayListStartTime = System.nanoTime(); Loading @@ -1258,33 +1352,10 @@ public abstract class HardwareRenderer { } handleFunctorStatus(attachInfo, status); } else { // Shouldn't reach here view.draw(canvas); return status; } } finally { callbacks.onHardwarePostDraw(canvas); canvas.restoreToCount(saveCount); view.mRecreateDisplayList = false; mFrameCount++; if (mDebugDirtyRegions) { if (mDebugPaint == null) { mDebugPaint = new Paint(); mDebugPaint.setColor(0x7fff0000); } if (dirty != null && (mFrameCount & 1) == 0) { canvas.drawRect(dirty, mDebugPaint); } } } onPostDraw(); attachInfo.mIgnoreDirtyState = false; private void swapBuffers(int status) { if ((status & DisplayList.STATUS_DREW) == DisplayList.STATUS_DREW) { long eglSwapBuffersStartTime = 0; if (mProfileEnabled) { Loading @@ -1301,16 +1372,19 @@ public abstract class HardwareRenderer { checkEglErrors(); } } if (mProfileEnabled) { mProfileLock.unlock(); private void debugDirtyRegions(Rect dirty, HardwareCanvas canvas) { if (mDebugDirtyRegions) { if (mDebugPaint == null) { mDebugPaint = new Paint(); mDebugPaint.setColor(0x7fff0000); } return dirty == null; if (dirty != null && (mFrameCount & 1) == 0) { canvas.drawRect(dirty, mDebugPaint); } } return false; } private void handleFunctorStatus(View.AttachInfo attachInfo, int status) { Loading Loading @@ -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; Loading Loading @@ -1493,6 +1576,94 @@ public abstract class HardwareRenderer { mGlCanvas.onPostDraw(); } @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 { Loading
core/jni/android_view_GLES20Canvas.cpp +32 −7 Original line number Diff line number Diff line Loading @@ -449,14 +449,38 @@ 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) { 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, Loading Loading @@ -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 }, Loading
libs/hwui/DisplayListRenderer.cpp +25 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ const char* DisplayList::OP_NAMES[] = { "DrawTextOnPath", "DrawPosText", "DrawText", "DrawRects", "ResetShader", "SetupShader", "ResetColorFilter", Loading Loading @@ -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]); } Loading Loading @@ -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(); Loading Loading @@ -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); } Loading
libs/hwui/DisplayListRenderer.h +2 −0 Original line number Diff line number Diff line Loading @@ -106,6 +106,7 @@ public: DrawTextOnPath, DrawPosText, DrawText, DrawRects, ResetShader, SetupShader, ResetColorFilter, Loading Loading @@ -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); Loading