summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorChet Haase <chet@google.com>2011-03-24 10:51:31 -0700
committerChet Haase <chet@google.com>2011-04-01 13:24:53 -0700
commit9c1e23baf5bfbebd1aebbd6d9a18c225325567ce (patch)
tree00eeed008fc5b296391adfcb20a610e37849cf87 /libs
parent827107f4ec7d9a53d7bb6e4071858252f263fa8c (diff)
downloadframeworks_base-9c1e23baf5bfbebd1aebbd6d9a18c225325567ce.zip
frameworks_base-9c1e23baf5bfbebd1aebbd6d9a18c225325567ce.tar.gz
frameworks_base-9c1e23baf5bfbebd1aebbd6d9a18c225325567ce.tar.bz2
Add logging of graphics acceleration info to bugreports
Change-Id: I9fa4cda6ccf92df9d1c644ccdc0e7274a30106e0
Diffstat (limited to 'libs')
-rw-r--r--libs/hwui/Android.mk1
-rw-r--r--libs/hwui/Caches.cpp49
-rw-r--r--libs/hwui/Caches.h1
-rw-r--r--libs/hwui/DisplayListLogBuffer.cpp124
-rw-r--r--libs/hwui/DisplayListLogBuffer.h52
-rw-r--r--libs/hwui/DisplayListRenderer.cpp21
-rw-r--r--libs/hwui/DisplayListRenderer.h3
7 files changed, 233 insertions, 18 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk
index b465fee..a98e4cd 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -9,6 +9,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
FontRenderer.cpp \
GammaFontRenderer.cpp \
Caches.cpp \
+ DisplayListLogBuffer.cpp \
DisplayListRenderer.cpp \
FboCache.cpp \
GradientCache.cpp \
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 4f5edd5..cd48429 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "OpenGLRenderer"
#include <utils/Log.h>
+#include <utils/String8.h>
#include "Caches.h"
#include "Properties.h"
@@ -69,30 +70,43 @@ Caches::~Caches() {
///////////////////////////////////////////////////////////////////////////////
void Caches::dumpMemoryUsage() {
- LOGD("Current memory usage / total memory usage (bytes):");
- LOGD(" TextureCache %8d / %8d", textureCache.getSize(), textureCache.getMaxSize());
- LOGD(" LayerCache %8d / %8d", layerCache.getSize(), layerCache.getMaxSize());
- LOGD(" GradientCache %8d / %8d", gradientCache.getSize(), gradientCache.getMaxSize());
- LOGD(" PathCache %8d / %8d", pathCache.getSize(), pathCache.getMaxSize());
- LOGD(" CircleShapeCache %8d / %8d",
+ String8 stringLog;
+ dumpMemoryUsage(stringLog);
+ LOGD("%s", stringLog.string());
+ delete stringLog;
+}
+
+void Caches::dumpMemoryUsage(String8 &log) {
+ log.appendFormat("Current memory usage / total memory usage (bytes):\n");
+ log.appendFormat(" TextureCache %8d / %8d\n",
+ textureCache.getSize(), textureCache.getMaxSize());
+ log.appendFormat(" LayerCache %8d / %8d\n",
+ layerCache.getSize(), layerCache.getMaxSize());
+ log.appendFormat(" GradientCache %8d / %8d\n",
+ gradientCache.getSize(), gradientCache.getMaxSize());
+ log.appendFormat(" PathCache %8d / %8d\n",
+ pathCache.getSize(), pathCache.getMaxSize());
+ log.appendFormat(" CircleShapeCache %8d / %8d\n",
circleShapeCache.getSize(), circleShapeCache.getMaxSize());
- LOGD(" OvalShapeCache %8d / %8d",
+ log.appendFormat(" OvalShapeCache %8d / %8d\n",
ovalShapeCache.getSize(), ovalShapeCache.getMaxSize());
- LOGD(" RoundRectShapeCache %8d / %8d",
+ log.appendFormat(" RoundRectShapeCache %8d / %8d\n",
roundRectShapeCache.getSize(), roundRectShapeCache.getMaxSize());
- LOGD(" RectShapeCache %8d / %8d",
+ log.appendFormat(" RectShapeCache %8d / %8d\n",
rectShapeCache.getSize(), rectShapeCache.getMaxSize());
- LOGD(" ArcShapeCache %8d / %8d",
+ log.appendFormat(" ArcShapeCache %8d / %8d\n",
arcShapeCache.getSize(), arcShapeCache.getMaxSize());
- LOGD(" TextDropShadowCache %8d / %8d", dropShadowCache.getSize(),
+ log.appendFormat(" TextDropShadowCache %8d / %8d\n", dropShadowCache.getSize(),
dropShadowCache.getMaxSize());
for (uint32_t i = 0; i < fontRenderer.getFontRendererCount(); i++) {
const uint32_t size = fontRenderer.getFontRendererSize(i);
- LOGD(" FontRenderer %d %8d / %8d", i, size, size);
+ log.appendFormat(" FontRenderer %d %8d / %8d\n", i, size, size);
}
- LOGD("Other:");
- LOGD(" FboCache %8d / %8d", fboCache.getSize(), fboCache.getMaxSize());
- LOGD(" PatchCache %8d / %8d", patchCache.getSize(), patchCache.getMaxSize());
+ log.appendFormat("Other:");
+ log.appendFormat(" FboCache %8d / %8d\n",
+ fboCache.getSize(), fboCache.getMaxSize());
+ log.appendFormat(" PatchCache %8d / %8d\n",
+ patchCache.getSize(), patchCache.getMaxSize());
uint32_t total = 0;
total += textureCache.getSize();
@@ -109,9 +123,8 @@ void Caches::dumpMemoryUsage() {
total += fontRenderer.getFontRendererSize(i);
}
- LOGD("Total memory usage:");
- LOGD(" %d bytes, %.2f MB", total, total / 1024.0f / 1024.0f);
- LOGD("\n");
+ log.appendFormat("Total memory usage:\n");
+ log.appendFormat(" %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f);
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index 0a9335f..7d02cf8 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -140,6 +140,7 @@ public:
* Displays the memory usage of each cache and the total sum.
*/
void dumpMemoryUsage();
+ void dumpMemoryUsage(String8& log);
bool blend;
GLenum lastSrcMode;
diff --git a/libs/hwui/DisplayListLogBuffer.cpp b/libs/hwui/DisplayListLogBuffer.cpp
new file mode 100644
index 0000000..f204644
--- /dev/null
+++ b/libs/hwui/DisplayListLogBuffer.cpp
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#include "DisplayListLogBuffer.h"
+
+// BUFFER_SIZE size must be one more than a multiple of COMMAND_SIZE to ensure
+// that mStart always points at the next command, not just the next item
+#define COMMAND_SIZE 2
+#define NUM_COMMANDS 50
+#define BUFFER_SIZE ((NUM_COMMANDS * COMMAND_SIZE) + 1)
+
+/**
+ * DisplayListLogBuffer is a utility class which logs the most recent display
+ * list operations in a circular buffer. The log is process-wide, because we
+ * only care about the most recent operations, not the operations on a per-window
+ * basis for a given activity. The purpose of the log is to provide more debugging
+ * information in a bug report, by telling us not just where a process hung (which
+ * generally is just reported as a stack trace at the Java level) or crashed, but
+ * also what happened immediately before that hang or crash. This may help track down
+ * problems in the native rendering code or driver interaction related to the display
+ * list operations that led up to the hang or crash.
+ *
+ * The log is implemented as a circular buffer for both space and performance
+ * reasons - we only care about the last several operations to give us context
+ * leading up to the problem, and we don't want to constantly copy data around or do
+ * additional mallocs to keep the most recent operations logged. Only numbers are
+ * logged to make the operation fast. If and when the log is output, we process this
+ * data into meaningful strings.
+ *
+ * There is an assumption about the format of the command (currently 2 ints: the
+ * opcode and the nesting level). If the type of information logged changes (for example,
+ * we may want to save a timestamp), then the size of the buffer and the way the
+ * information is recorded in writeCommand() should change to suit.
+ */
+
+namespace android {
+
+#ifdef USE_OPENGL_RENDERER
+using namespace uirenderer;
+ANDROID_SINGLETON_STATIC_INSTANCE(DisplayListLogBuffer);
+#endif
+
+namespace uirenderer {
+
+
+DisplayListLogBuffer::DisplayListLogBuffer() {
+ mBufferFirst = (int*) malloc(BUFFER_SIZE * sizeof(int));
+ mStart = mBufferFirst;
+ mBufferLast = mBufferFirst + BUFFER_SIZE - 1;
+ mEnd = mStart;
+}
+
+DisplayListLogBuffer::~DisplayListLogBuffer() {
+ free(mBufferFirst);
+}
+
+/**
+ * Called from DisplayListRenderer to output the current buffer into the
+ * specified FILE. This only happens in a dumpsys/bugreport operation.
+ */
+void DisplayListLogBuffer::outputCommands(FILE *file, const char* opNames[])
+{
+ int *tmpBufferPtr = mStart;
+ while (true) {
+ if (tmpBufferPtr == mEnd) {
+ break;
+ }
+ int level = *tmpBufferPtr++;
+ if (tmpBufferPtr > mBufferLast) {
+ tmpBufferPtr = mBufferFirst;
+ }
+ int op = *tmpBufferPtr++;
+ if (tmpBufferPtr > mBufferLast) {
+ tmpBufferPtr = mBufferFirst;
+ }
+ uint32_t count = (level + 1) * 2;
+ char indent[count + 1];
+ for (uint32_t i = 0; i < count; i++) {
+ indent[i] = ' ';
+ }
+ indent[count] = '\0';
+ fprintf(file, "%s%s\n", indent, opNames[op]);
+ }
+}
+
+void DisplayListLogBuffer::writeCommand(int level, int op) {
+ writeInt(level);
+ writeInt(op);
+}
+
+/**
+ * Store the given value in the buffer and increment/wrap the mEnd
+ * and mStart values as appropriate.
+ */
+void DisplayListLogBuffer::writeInt(int value) {
+ *((int*)mEnd) = value;
+ if (mEnd == mBufferLast) {
+ mEnd = mBufferFirst;
+ } else {
+ mEnd++;
+ }
+ if (mEnd == mStart) {
+ mStart++;
+ if (mStart > mBufferLast) {
+ mStart = mBufferFirst;
+ }
+ }
+}
+
+}; // namespace uirenderer
+}; // namespace android
diff --git a/libs/hwui/DisplayListLogBuffer.h b/libs/hwui/DisplayListLogBuffer.h
new file mode 100644
index 0000000..bf16f29
--- /dev/null
+++ b/libs/hwui/DisplayListLogBuffer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 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_HWUI_DISPLAY_LIST_LOG_BUFFER_H
+#define ANDROID_HWUI_DISPLAY_LIST_LOG_BUFFER_H
+
+#include <utils/Singleton.h>
+#include <stdio.h>
+
+namespace android {
+namespace uirenderer {
+
+class DisplayListLogBuffer: public Singleton<DisplayListLogBuffer> {
+ DisplayListLogBuffer();
+ ~DisplayListLogBuffer();
+
+ friend class Singleton<DisplayListLogBuffer>;
+
+public:
+ void writeCommand(int level, int op);
+ void writeInt(int value);
+ void outputCommands(FILE *file, const char* opNames[]);
+
+ bool isEmpty() {
+ return (mStart == mEnd);
+ }
+
+private:
+ int *mBufferFirst; // where the memory starts
+ int* mStart; // where the current command stream starts
+ int* mEnd; // where the current commands end
+ int* mBufferLast; // where the buffer memory ends
+
+};
+
+}; // namespace uirenderer
+}; // namespace android
+
+#endif // ANDROID_HWUI_DISPLAY_LIST_LOG_BUFFER_H
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index c7459d1..34dda9a 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -16,11 +16,16 @@
#define LOG_TAG "OpenGLRenderer"
+
+#include "DisplayListLogBuffer.h"
#include "DisplayListRenderer.h"
+#include <utils/String8.h>
+#include "Caches.h"
namespace android {
namespace uirenderer {
+
///////////////////////////////////////////////////////////////////////////////
// Display list
///////////////////////////////////////////////////////////////////////////////
@@ -64,6 +69,20 @@ const char* DisplayList::OP_NAMES[] = {
"DrawGLFunction"
};
+void DisplayList::outputLogBuffer(int fd) {
+ DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
+ if (logBuffer.isEmpty()) {
+ return;
+ }
+ String8 cachesLog;
+ Caches::getInstance().dumpMemoryUsage(cachesLog);
+ FILE *file = fdopen(fd, "a");
+ fprintf(file, "\nCaches:\n%s", cachesLog.string());
+ fprintf(file, "\nRecent DisplayList operations\n");
+ logBuffer.outputCommands(file, OP_NAMES);
+ fflush(file);
+}
+
DisplayList::DisplayList(const DisplayListRenderer& recorder) {
initFromDisplayListRenderer(recorder);
}
@@ -173,9 +192,11 @@ bool DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level)
DISPLAY_LIST_LOGD("%sStart display list (%p)", (char*) indent + 2, this);
#endif
+ DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
int saveCount = renderer.getSaveCount() - 1;
while (!mReader.eof()) {
int op = mReader.readInt();
+ logBuffer.writeCommand(level, op);
switch (op) {
case DrawGLFunction: {
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index da57e4a..b782103 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -26,6 +26,7 @@
#include <SkTDArray.h>
#include <SkTSearch.h>
+#include "DisplayListLogBuffer.h"
#include "OpenGLRenderer.h"
#include "utils/Functor.h"
@@ -106,6 +107,8 @@ public:
bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0);
+ static void outputLogBuffer(int fd);
+
private:
void init();