diff options
-rw-r--r-- | core/java/android/view/GLES20Canvas.java | 7 | ||||
-rw-r--r-- | core/java/android/view/HardwareCanvas.java | 8 | ||||
-rw-r--r-- | core/java/android/view/ViewDebug.java | 8 | ||||
-rw-r--r-- | core/java/android/view/ViewRoot.java | 14 | ||||
-rw-r--r-- | core/jni/android_view_GLES20Canvas.cpp | 7 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.cpp | 325 | ||||
-rw-r--r-- | libs/hwui/DisplayListRenderer.h | 2 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.cpp | 6 | ||||
-rw-r--r-- | libs/hwui/OpenGLRenderer.h | 1 | ||||
-rw-r--r-- | services/java/com/android/server/wm/ViewServer.java | 2 |
10 files changed, 378 insertions, 2 deletions
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java index 984102a..2b79a76 100644 --- a/core/java/android/view/GLES20Canvas.java +++ b/core/java/android/view/GLES20Canvas.java @@ -261,6 +261,13 @@ class GLES20Canvas extends HardwareCanvas { private static native boolean nDrawDisplayList(int renderer, int displayList, int width, int height, Rect dirty); + @Override + void outputDisplayList(DisplayList displayList) { + nOutputDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList); + } + + private static native void nOutputDisplayList(int renderer, int displayList); + /////////////////////////////////////////////////////////////////////////// // Hardware layer /////////////////////////////////////////////////////////////////////////// diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java index caa7b74..23b3abc 100644 --- a/core/java/android/view/HardwareCanvas.java +++ b/core/java/android/view/HardwareCanvas.java @@ -64,6 +64,14 @@ public abstract class HardwareCanvas extends Canvas { abstract boolean drawDisplayList(DisplayList displayList, int width, int height, Rect dirty); /** + * Outputs the specified display list to the log. This method exists for use by + * tools to output display lists for selected nodes to the log. + * + * @param displayList The display list to be logged. + */ + abstract void outputDisplayList(DisplayList displayList); + + /** * Draws the specified layer onto this canvas. * * @param layer The layer to composite on this canvas diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java index 881cb76..3b351b1 100644 --- a/core/java/android/view/ViewDebug.java +++ b/core/java/android/view/ViewDebug.java @@ -375,6 +375,7 @@ public class ViewDebug { private static final String REMOTE_COMMAND_REQUEST_LAYOUT = "REQUEST_LAYOUT"; private static final String REMOTE_PROFILE = "PROFILE"; private static final String REMOTE_COMMAND_CAPTURE_LAYERS = "CAPTURE_LAYERS"; + private static final String REMOTE_COMMAND_OUTPUT_DISPLAYLIST = "OUTPUT_DISPLAYLIST"; private static HashMap<Class<?>, Field[]> sFieldsForClasses; private static HashMap<Class<?>, Method[]> sMethodsForClasses; @@ -885,6 +886,8 @@ public class ViewDebug { final String[] params = parameters.split(" "); if (REMOTE_COMMAND_CAPTURE.equalsIgnoreCase(command)) { capture(view, clientStream, params[0]); + } else if (REMOTE_COMMAND_OUTPUT_DISPLAYLIST.equalsIgnoreCase(command)) { + outputDisplayList(view, params[0]); } else if (REMOTE_COMMAND_INVALIDATE.equalsIgnoreCase(command)) { invalidate(view, params[0]); } else if (REMOTE_COMMAND_REQUEST_LAYOUT.equalsIgnoreCase(command)) { @@ -1156,6 +1159,11 @@ public class ViewDebug { } } + private static void outputDisplayList(View root, String parameter) throws IOException { + final View view = findView(root, parameter); + view.getViewRoot().outputDisplayList(view); + } + private static void capture(View root, final OutputStream clientStream, String parameter) throws IOException { diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java index f02daba..e662b9e 100644 --- a/core/java/android/view/ViewRoot.java +++ b/core/java/android/view/ViewRoot.java @@ -1507,6 +1507,20 @@ public final class ViewRoot extends Handler implements ViewParent, } } + /** + * @hide + */ + void outputDisplayList(View view) { + if (mAttachInfo != null && mAttachInfo.mHardwareCanvas != null) { + + HardwareCanvas canvas = (HardwareCanvas) mAttachInfo.mHardwareCanvas; + DisplayList displayList = view.getDisplayList(); + if (displayList != null) { + canvas.outputDisplayList(displayList); + } + } + } + private void draw(boolean fullRedrawNeeded) { Surface surface = mSurface; if (surface == null || !surface.isValid()) { diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp index f929a0e..d43a27f 100644 --- a/core/jni/android_view_GLES20Canvas.cpp +++ b/core/jni/android_view_GLES20Canvas.cpp @@ -519,6 +519,11 @@ static bool android_view_GLES20Canvas_drawDisplayList(JNIEnv* env, return redraw; } +static void android_view_GLES20Canvas_outputDisplayList(JNIEnv* env, + jobject clazz, OpenGLRenderer* renderer, DisplayList* displayList) { + renderer->outputDisplayList(displayList); +} + // ---------------------------------------------------------------------------- // Layers // ---------------------------------------------------------------------------- @@ -714,7 +719,7 @@ static JNINativeMethod gMethods[] = { { "nGetDisplayListRenderer", "(I)I", (void*) android_view_GLES20Canvas_getDisplayListRenderer }, { "nDrawDisplayList", "(IIIILandroid/graphics/Rect;)Z", (void*) android_view_GLES20Canvas_drawDisplayList }, - + { "nOutputDisplayList", "(II)V", (void*) android_view_GLES20Canvas_outputDisplayList }, { "nInterrupt", "(I)V", (void*) android_view_GLES20Canvas_interrupt }, { "nResume", "(I)V", (void*) android_view_GLES20Canvas_resume }, diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp index 34dda9a..f8582d8 100644 --- a/libs/hwui/DisplayListRenderer.cpp +++ b/libs/hwui/DisplayListRenderer.cpp @@ -177,6 +177,331 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde void DisplayList::init() { } +/** + * This function is a simplified version of replay(), where we simply retrieve and log the + * display list. This function should remain in sync with the replay() function. + */ +void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) { + TextContainer text; + + uint32_t count = (level + 1) * 2; + char indent[count + 1]; + for (uint32_t i = 0; i < count; i++) { + indent[i] = ' '; + } + indent[count] = '\0'; + LOGD("%sStart display list (%p)", (char*) indent + 2, this); + + int saveCount = renderer.getSaveCount() - 1; + + mReader.rewind(); + + while (!mReader.eof()) { + int op = mReader.readInt(); + + switch (op) { + case DrawGLFunction: { + Functor *functor = (Functor *) getInt(); + LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor); + } + break; + case Save: { + int rendererNum = getInt(); + LOGD("%s%s %d", (char*) indent, OP_NAMES[op], rendererNum); + } + break; + case Restore: { + LOGD("%s%s", (char*) indent, OP_NAMES[op]); + } + break; + case RestoreToCount: { + int restoreCount = saveCount + getInt(); + LOGD("%s%s %d", (char*) indent, OP_NAMES[op], restoreCount); + } + break; + case SaveLayer: { + float f1 = getFloat(); + float f2 = getFloat(); + float f3 = getFloat(); + float f4 = getFloat(); + SkPaint* paint = getPaint(); + int flags = getInt(); + LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p, 0x%x", (char*) indent, + OP_NAMES[op], f1, f2, f3, f4, paint, flags); + } + break; + case SaveLayerAlpha: { + float f1 = getFloat(); + float f2 = getFloat(); + float f3 = getFloat(); + float f4 = getFloat(); + int alpha = getInt(); + int flags = getInt(); + LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", (char*) indent, + OP_NAMES[op], f1, f2, f3, f4, alpha, flags); + } + break; + case Translate: { + float f1 = getFloat(); + float f2 = getFloat(); + LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], f1, f2); + } + break; + case Rotate: { + float rotation = getFloat(); + LOGD("%s%s %.2f", (char*) indent, OP_NAMES[op], rotation); + } + break; + case Scale: { + float sx = getFloat(); + float sy = getFloat(); + LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy); + } + break; + case Skew: { + float sx = getFloat(); + float sy = getFloat(); + LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy); + } + break; + case SetMatrix: { + SkMatrix* matrix = getMatrix(); + LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix); + } + break; + case ConcatMatrix: { + SkMatrix* matrix = getMatrix(); + LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix); + } + break; + case ClipRect: { + float f1 = getFloat(); + float f2 = getFloat(); + float f3 = getFloat(); + float f4 = getFloat(); + int regionOp = getInt(); + LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d", (char*) indent, OP_NAMES[op], + f1, f2, f3, f4, regionOp); + } + break; + case DrawDisplayList: { + DisplayList* displayList = getDisplayList(); + uint32_t width = getUInt(); + uint32_t height = getUInt(); + LOGD("%s%s %p, %dx%d, %d", (char*) indent, OP_NAMES[op], + displayList, width, height, level + 1); + renderer.outputDisplayList(displayList, level + 1); + } + break; + case DrawLayer: { + Layer* layer = (Layer*) getInt(); + float x = getFloat(); + float y = getFloat(); + SkPaint* paint = getPaint(); + LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op], + layer, x, y, paint); + } + break; + case DrawBitmap: { + SkBitmap* bitmap = getBitmap(); + float x = getFloat(); + float y = getFloat(); + SkPaint* paint = getPaint(); + LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op], + bitmap, x, y, paint); + } + break; + case DrawBitmapMatrix: { + SkBitmap* bitmap = getBitmap(); + SkMatrix* matrix = getMatrix(); + SkPaint* paint = getPaint(); + LOGD("%s%s %p, %p, %p", (char*) indent, OP_NAMES[op], + bitmap, matrix, paint); + } + break; + case DrawBitmapRect: { + SkBitmap* bitmap = getBitmap(); + float f1 = getFloat(); + float f2 = getFloat(); + float f3 = getFloat(); + float f4 = getFloat(); + float f5 = getFloat(); + float f6 = getFloat(); + float f7 = getFloat(); + float f8 = getFloat(); + SkPaint* paint = getPaint(); + LOGD("%s%s %p, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p", + (char*) indent, OP_NAMES[op], bitmap, f1, f2, f3, f4, f5, f6, f7, f8, paint); + } + break; + case DrawBitmapMesh: { + int verticesCount = 0; + uint32_t colorsCount = 0; + SkBitmap* bitmap = getBitmap(); + uint32_t meshWidth = getInt(); + uint32_t meshHeight = getInt(); + float* vertices = getFloats(verticesCount); + bool hasColors = getInt(); + int* colors = hasColors ? getInts(colorsCount) : NULL; + SkPaint* paint = getPaint(); + LOGD("%s%s", (char*) indent, OP_NAMES[op]); + } + break; + case DrawPatch: { + int32_t* xDivs = NULL; + int32_t* yDivs = NULL; + uint32_t* colors = NULL; + uint32_t xDivsCount = 0; + uint32_t yDivsCount = 0; + int8_t numColors = 0; + SkBitmap* bitmap = getBitmap(); + xDivs = getInts(xDivsCount); + yDivs = getInts(yDivsCount); + colors = getUInts(numColors); + DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]); + getFloat(); + getFloat(); + getFloat(); + getFloat(); + getPaint(); + } + break; + case DrawColor: { + int color = getInt(); + int xferMode = getInt(); + LOGD("%s%s 0x%x %d", (char*) indent, OP_NAMES[op], color, xferMode); + } + break; + case DrawRect: { + float f1 = getFloat(); + float f2 = getFloat(); + float f3 = getFloat(); + float f4 = getFloat(); + SkPaint* paint = getPaint(); + LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op], + f1, f2, f3, f4, paint); + } + break; + case DrawRoundRect: { + float f1 = getFloat(); + float f2 = getFloat(); + float f3 = getFloat(); + float f4 = getFloat(); + float f5 = getFloat(); + float f6 = getFloat(); + SkPaint* paint = getPaint(); + LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p", + (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint); + } + break; + case DrawCircle: { + float f1 = getFloat(); + float f2 = getFloat(); + float f3 = getFloat(); + SkPaint* paint = getPaint(); + LOGD("%s%s %.2f, %.2f, %.2f, %p", + (char*) indent, OP_NAMES[op], f1, f2, f3, paint); + } + break; + case DrawOval: { + float f1 = getFloat(); + float f2 = getFloat(); + float f3 = getFloat(); + float f4 = getFloat(); + SkPaint* paint = getPaint(); + LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p", + (char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint); + } + break; + case DrawArc: { + float f1 = getFloat(); + float f2 = getFloat(); + float f3 = getFloat(); + float f4 = getFloat(); + float f5 = getFloat(); + float f6 = getFloat(); + int i1 = getInt(); + SkPaint* paint = getPaint(); + LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p", + (char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint); + } + break; + case DrawPath: { + SkPath* path = getPath(); + SkPaint* paint = getPaint(); + LOGD("%s%s %p, %p", (char*) indent, OP_NAMES[op], path, paint); + } + break; + case DrawLines: { + int count = 0; + float* points = getFloats(count); + SkPaint* paint = getPaint(); + LOGD("%s%s", (char*) indent, OP_NAMES[op]); + } + break; + case DrawPoints: { + int count = 0; + float* points = getFloats(count); + SkPaint* paint = getPaint(); + LOGD("%s%s", (char*) indent, OP_NAMES[op]); + } + break; + case DrawText: { + getText(&text); + int count = getInt(); + float x = getFloat(); + float y = getFloat(); + SkPaint* paint = getPaint(); + LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op], + text.text(), text.length(), count, x, y, paint); + } + break; + case ResetShader: { + LOGD("%s%s", (char*) indent, OP_NAMES[op]); + } + break; + case SetupShader: { + SkiaShader* shader = getShader(); + LOGD("%s%s %p", (char*) indent, OP_NAMES[op], shader); + } + break; + case ResetColorFilter: { + LOGD("%s%s", (char*) indent, OP_NAMES[op]); + } + break; + case SetupColorFilter: { + SkiaColorFilter *colorFilter = getColorFilter(); + LOGD("%s%s %p", (char*) indent, OP_NAMES[op], colorFilter); + } + break; + case ResetShadow: { + LOGD("%s%s", (char*) indent, OP_NAMES[op]); + } + break; + case SetupShadow: { + float radius = getFloat(); + float dx = getFloat(); + float dy = getFloat(); + int color = getInt(); + LOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op], + radius, dx, dy, color); + } + break; + default: + LOGD("Display List error: op not handled: %s%s", + (char*) indent, OP_NAMES[op]); + break; + } + } + + LOGD("%sDone", (char*) indent + 2); +} + +/** + * Changes to replay(), specifically those involving opcode or parameter changes, should be mimicked + * in the output() function, since that function processes the same list of opcodes for the + * purposes of logging display list info for a given view. + */ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level) { bool needsInvalidate = false; TextContainer text; diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h index b782103..dcf2cf2 100644 --- a/libs/hwui/DisplayListRenderer.h +++ b/libs/hwui/DisplayListRenderer.h @@ -107,6 +107,8 @@ public: bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0); + void output(OpenGLRenderer& renderer, uint32_t level = 0); + static void outputLogBuffer(int fd); private: diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp index 6f751e8..f6a21d4 100644 --- a/libs/hwui/OpenGLRenderer.cpp +++ b/libs/hwui/OpenGLRenderer.cpp @@ -1185,6 +1185,12 @@ bool OpenGLRenderer::drawDisplayList(DisplayList* displayList, uint32_t width, u return false; } +void OpenGLRenderer::outputDisplayList(DisplayList* displayList, uint32_t level) { + if (displayList) { + displayList->output(*this, level); + } +} + void OpenGLRenderer::drawAlphaBitmap(Texture* texture, float left, float top, SkPaint* paint) { int alpha; SkXfermode::Mode mode; diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h index b5c37c2..271e4b1 100644 --- a/libs/hwui/OpenGLRenderer.h +++ b/libs/hwui/OpenGLRenderer.h @@ -98,6 +98,7 @@ public: virtual bool drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height, Rect& dirty, uint32_t level = 0); + virtual void outputDisplayList(DisplayList* displayList, uint32_t level = 0); virtual void drawLayer(Layer* layer, float x, float y, SkPaint* paint); virtual void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint); virtual void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint); diff --git a/services/java/com/android/server/wm/ViewServer.java b/services/java/com/android/server/wm/ViewServer.java index cebd5e7..9fb35b9 100644 --- a/services/java/com/android/server/wm/ViewServer.java +++ b/services/java/com/android/server/wm/ViewServer.java @@ -49,7 +49,7 @@ class ViewServer implements Runnable { // Debug facility private static final String LOG_TAG = "ViewServer"; - private static final String VALUE_PROTOCOL_VERSION = "3"; + private static final String VALUE_PROTOCOL_VERSION = "4"; private static final String VALUE_SERVER_VERSION = "4"; // Protocol commands |