summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/GLES20Canvas.java7
-rw-r--r--core/java/android/view/HardwareCanvas.java8
-rw-r--r--core/java/android/view/ViewDebug.java8
-rw-r--r--core/java/android/view/ViewRoot.java14
-rw-r--r--core/jni/android_view_GLES20Canvas.cpp7
-rw-r--r--libs/hwui/DisplayListRenderer.cpp325
-rw-r--r--libs/hwui/DisplayListRenderer.h2
-rw-r--r--libs/hwui/OpenGLRenderer.cpp6
-rw-r--r--libs/hwui/OpenGLRenderer.h1
-rw-r--r--services/java/com/android/server/wm/ViewServer.java2
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