Files
frameworks_base/libs/hwui/DisplayListRenderer.cpp
Jeff Brown 162a021756 Decouple GLES20RecordingCanvas lifetime from GLES20DisplayList.
Bug: 5062011

Previously, each GLES20DisplayList would hold onto an instance of
GLES20RecordingCanvas.  In turn, each GLES20RecordingCanvas
held onto an SkWriter with a 16Kb buffer along with several other
objects.  With one display list per view and hundreds of views,
the overhead could add up to a few megabytes.

Ensured that the GLES20RecordingCanvas is reset as soon as
the display list has been constructed, thereby promptly freeing
the 16Kb buffer.

Changed GLES20DisplayList so that it acquires a GLES20RecordingCanvas
from a pool as needed and recycles it when done.

Removed some dead code and cruft related to the construction of
GLES20Canvas objects in general.  Some code was written with the
assumption that the underlying renderer object could change
behind the scenes or might be lazily constructed, but that isn't
actually the case so we can simplify things.

Removed an unnecessary weak reference from GLES20DisplayList
to the View.  It isn't actually used anywhere.

Fixed a bug in GLES20DisplayList where isValid() would return
true while the display list was being recorded.  This is incorrect
because the native display list might not actually exist.  Worse,
even if the native display list does exist, it is stale and
potentially refers to old Bitmaps that have been GC'd (because the
mBitmaps list was cleared when recording started).

Change-Id: Ib12d5483688cb253478edeb0156d34c476c2566b
2011-07-21 17:15:48 -07:00

1220 lines
41 KiB
C++

/*
* Copyright (C) 2010 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.
*/
#define LOG_TAG "OpenGLRenderer"
#include "DisplayListLogBuffer.h"
#include "DisplayListRenderer.h"
#include <utils/String8.h>
#include "Caches.h"
namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Display list
///////////////////////////////////////////////////////////////////////////////
const char* DisplayList::OP_NAMES[] = {
"Save",
"Restore",
"RestoreToCount",
"SaveLayer",
"SaveLayerAlpha",
"Translate",
"Rotate",
"Scale",
"Skew",
"SetMatrix",
"ConcatMatrix",
"ClipRect",
"DrawDisplayList",
"DrawLayer",
"DrawBitmap",
"DrawBitmapMatrix",
"DrawBitmapRect",
"DrawBitmapMesh",
"DrawPatch",
"DrawColor",
"DrawRect",
"DrawRoundRect",
"DrawCircle",
"DrawOval",
"DrawArc",
"DrawPath",
"DrawLines",
"DrawPoints",
"DrawText",
"ResetShader",
"SetupShader",
"ResetColorFilter",
"SetupColorFilter",
"ResetShadow",
"SetupShadow",
"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);
}
DisplayList::~DisplayList() {
clearResources();
}
void DisplayList::clearResources() {
sk_free((void*) mReader.base());
Caches& caches = Caches::getInstance();
for (size_t i = 0; i < mBitmapResources.size(); i++) {
caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i));
}
mBitmapResources.clear();
for (size_t i = 0; i < mFilterResources.size(); i++) {
caches.resourceCache.decrementRefcount(mFilterResources.itemAt(i));
}
mFilterResources.clear();
for (size_t i = 0; i < mShaders.size(); i++) {
caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
caches.resourceCache.destructor(mShaders.itemAt(i));
}
mShaders.clear();
for (size_t i = 0; i < mPaints.size(); i++) {
delete mPaints.itemAt(i);
}
mPaints.clear();
for (size_t i = 0; i < mPaths.size(); i++) {
SkPath* path = mPaths.itemAt(i);
caches.pathCache.remove(path);
delete path;
}
mPaths.clear();
for (size_t i = 0; i < mMatrices.size(); i++) {
delete mMatrices.itemAt(i);
}
mMatrices.clear();
}
void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing) {
const SkWriter32& writer = recorder.writeStream();
init();
if (writer.size() == 0) {
return;
}
if (reusing) {
// re-using display list - clear out previous allocations
clearResources();
}
size_t size = writer.size();
void* buffer = sk_malloc_throw(size);
writer.flatten(buffer);
mReader.setMemory(buffer, size);
Caches& caches = Caches::getInstance();
const Vector<SkBitmap*> &bitmapResources = recorder.getBitmapResources();
for (size_t i = 0; i < bitmapResources.size(); i++) {
SkBitmap* resource = bitmapResources.itemAt(i);
mBitmapResources.add(resource);
caches.resourceCache.incrementRefcount(resource);
}
const Vector<SkiaColorFilter*> &filterResources = recorder.getFilterResources();
for (size_t i = 0; i < filterResources.size(); i++) {
SkiaColorFilter* resource = filterResources.itemAt(i);
mFilterResources.add(resource);
caches.resourceCache.incrementRefcount(resource);
}
const Vector<SkiaShader*> &shaders = recorder.getShaders();
for (size_t i = 0; i < shaders.size(); i++) {
SkiaShader* resource = shaders.itemAt(i);
mShaders.add(resource);
caches.resourceCache.incrementRefcount(resource);
}
const Vector<SkPaint*> &paints = recorder.getPaints();
for (size_t i = 0; i < paints.size(); i++) {
mPaints.add(paints.itemAt(i));
}
const Vector<SkPath*> &paths = recorder.getPaths();
for (size_t i = 0; i < paths.size(); i++) {
mPaths.add(paths.itemAt(i));
}
const Vector<SkMatrix*> &matrices = recorder.getMatrices();
for (size_t i = 0; i < matrices.size(); i++) {
mMatrices.add(matrices.itemAt(i));
}
}
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;
mReader.rewind();
#if DEBUG_DISPLAY_LIST
uint32_t count = (level + 1) * 2;
char indent[count + 1];
for (uint32_t i = 0; i < count; i++) {
indent[i] = ' ';
}
indent[count] = '\0';
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: {
Functor *functor = (Functor *) getInt();
DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
needsInvalidate |= renderer.callDrawGLFunction(functor, dirty);
}
break;
case Save: {
int rendererNum = getInt();
DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], rendererNum);
renderer.save(rendererNum);
}
break;
case Restore: {
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.restore();
}
break;
case RestoreToCount: {
int restoreCount = saveCount + getInt();
DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], restoreCount);
renderer.restoreToCount(restoreCount);
}
break;
case SaveLayer: {
float f1 = getFloat();
float f2 = getFloat();
float f3 = getFloat();
float f4 = getFloat();
SkPaint* paint = getPaint();
int flags = getInt();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p, 0x%x", (char*) indent,
OP_NAMES[op], f1, f2, f3, f4, paint, flags);
renderer.saveLayer(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();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", (char*) indent,
OP_NAMES[op], f1, f2, f3, f4, alpha, flags);
renderer.saveLayerAlpha(f1, f2, f3, f4, alpha, flags);
}
break;
case Translate: {
float f1 = getFloat();
float f2 = getFloat();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], f1, f2);
renderer.translate(f1, f2);
}
break;
case Rotate: {
float rotation = getFloat();
DISPLAY_LIST_LOGD("%s%s %.2f", (char*) indent, OP_NAMES[op], rotation);
renderer.rotate(rotation);
}
break;
case Scale: {
float sx = getFloat();
float sy = getFloat();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
renderer.scale(sx, sy);
}
break;
case Skew: {
float sx = getFloat();
float sy = getFloat();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
renderer.skew(sx, sy);
}
break;
case SetMatrix: {
SkMatrix* matrix = getMatrix();
DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
renderer.setMatrix(matrix);
}
break;
case ConcatMatrix: {
SkMatrix* matrix = getMatrix();
DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
renderer.concatMatrix(matrix);
}
break;
case ClipRect: {
float f1 = getFloat();
float f2 = getFloat();
float f3 = getFloat();
float f4 = getFloat();
int regionOp = getInt();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d", (char*) indent, OP_NAMES[op],
f1, f2, f3, f4, regionOp);
renderer.clipRect(f1, f2, f3, f4, (SkRegion::Op) regionOp);
}
break;
case DrawDisplayList: {
DisplayList* displayList = getDisplayList();
uint32_t width = getUInt();
uint32_t height = getUInt();
DISPLAY_LIST_LOGD("%s%s %p, %dx%d, %d", (char*) indent, OP_NAMES[op],
displayList, width, height, level + 1);
needsInvalidate |= renderer.drawDisplayList(displayList, width, height,
dirty, level + 1);
}
break;
case DrawLayer: {
Layer* layer = (Layer*) getInt();
float x = getFloat();
float y = getFloat();
SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
layer, x, y, paint);
renderer.drawLayer(layer, x, y, paint);
}
break;
case DrawBitmap: {
SkBitmap* bitmap = getBitmap();
float x = getFloat();
float y = getFloat();
SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s %p, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
bitmap, x, y, paint);
renderer.drawBitmap(bitmap, x, y, paint);
}
break;
case DrawBitmapMatrix: {
SkBitmap* bitmap = getBitmap();
SkMatrix* matrix = getMatrix();
SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s %p, %p, %p", (char*) indent, OP_NAMES[op],
bitmap, matrix, paint);
renderer.drawBitmap(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();
DISPLAY_LIST_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);
renderer.drawBitmap(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();
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, paint);
}
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);
float left = getFloat();
float top = getFloat();
float right = getFloat();
float bottom = getFloat();
SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.drawPatch(bitmap, xDivs, yDivs, colors, xDivsCount, yDivsCount,
numColors, left, top, right, bottom, paint);
}
break;
case DrawColor: {
int color = getInt();
int xferMode = getInt();
DISPLAY_LIST_LOGD("%s%s 0x%x %d", (char*) indent, OP_NAMES[op], color, xferMode);
renderer.drawColor(color, (SkXfermode::Mode) xferMode);
}
break;
case DrawRect: {
float f1 = getFloat();
float f2 = getFloat();
float f3 = getFloat();
float f4 = getFloat();
SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
f1, f2, f3, f4, paint);
renderer.drawRect(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();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %p",
(char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, paint);
renderer.drawRoundRect(f1, f2, f3, f4, f5, f6, paint);
}
break;
case DrawCircle: {
float f1 = getFloat();
float f2 = getFloat();
float f3 = getFloat();
SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %p",
(char*) indent, OP_NAMES[op], f1, f2, f3, paint);
renderer.drawCircle(f1, f2, f3, paint);
}
break;
case DrawOval: {
float f1 = getFloat();
float f2 = getFloat();
float f3 = getFloat();
float f4 = getFloat();
SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %p",
(char*) indent, OP_NAMES[op], f1, f2, f3, f4, paint);
renderer.drawOval(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();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %.2f, %.2f, %d, %p",
(char*) indent, OP_NAMES[op], f1, f2, f3, f4, f5, f6, i1, paint);
renderer.drawArc(f1, f2, f3, f4, f5, f6, i1 == 1, paint);
}
break;
case DrawPath: {
SkPath* path = getPath();
SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s %p, %p", (char*) indent, OP_NAMES[op], path, paint);
renderer.drawPath(path, paint);
}
break;
case DrawLines: {
int count = 0;
float* points = getFloats(count);
SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.drawLines(points, count, paint);
}
break;
case DrawPoints: {
int count = 0;
float* points = getFloats(count);
SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.drawPoints(points, count, paint);
}
break;
case DrawText: {
getText(&text);
int count = getInt();
float x = getFloat();
float y = getFloat();
SkPaint* paint = getPaint();
DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p", (char*) indent, OP_NAMES[op],
text.text(), text.length(), count, x, y, paint);
renderer.drawText(text.text(), text.length(), count, x, y, paint);
}
break;
case ResetShader: {
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.resetShader();
}
break;
case SetupShader: {
SkiaShader* shader = getShader();
DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], shader);
renderer.setupShader(shader);
}
break;
case ResetColorFilter: {
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.resetColorFilter();
}
break;
case SetupColorFilter: {
SkiaColorFilter *colorFilter = getColorFilter();
DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], colorFilter);
renderer.setupColorFilter(colorFilter);
}
break;
case ResetShadow: {
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.resetShadow();
}
break;
case SetupShadow: {
float radius = getFloat();
float dx = getFloat();
float dy = getFloat();
int color = getInt();
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op],
radius, dx, dy, color);
renderer.setupShadow(radius, dx, dy, color);
}
break;
default:
DISPLAY_LIST_LOGD("Display List error: op not handled: %s%s",
(char*) indent, OP_NAMES[op]);
break;
}
}
DISPLAY_LIST_LOGD("%sDone, returning %d", (char*) indent + 2, needsInvalidate);
return needsInvalidate;
}
///////////////////////////////////////////////////////////////////////////////
// Base structure
///////////////////////////////////////////////////////////////////////////////
DisplayListRenderer::DisplayListRenderer(): mWriter(MIN_WRITER_SIZE) {
}
DisplayListRenderer::~DisplayListRenderer() {
reset();
}
void DisplayListRenderer::reset() {
mWriter.reset();
Caches& caches = Caches::getInstance();
for (size_t i = 0; i < mBitmapResources.size(); i++) {
caches.resourceCache.decrementRefcount(mBitmapResources.itemAt(i));
}
mBitmapResources.clear();
for (size_t i = 0; i < mFilterResources.size(); i++) {
caches.resourceCache.decrementRefcount(mFilterResources.itemAt(i));
}
mFilterResources.clear();
for (size_t i = 0; i < mShaders.size(); i++) {
caches.resourceCache.decrementRefcount(mShaders.itemAt(i));
}
mShaders.clear();
mShaderMap.clear();
mPaints.clear();
mPaintMap.clear();
mPaths.clear();
mPathMap.clear();
mMatrices.clear();
}
///////////////////////////////////////////////////////////////////////////////
// Operations
///////////////////////////////////////////////////////////////////////////////
DisplayList* DisplayListRenderer::getDisplayList(DisplayList* displayList) {
if (!displayList) {
displayList = new DisplayList(*this);
} else {
displayList->initFromDisplayListRenderer(*this, true);
}
return displayList;
}
void DisplayListRenderer::setViewport(int width, int height) {
mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
mWidth = width;
mHeight = height;
}
void DisplayListRenderer::prepareDirty(float left, float top,
float right, float bottom, bool opaque) {
mSnapshot = new Snapshot(mFirstSnapshot,
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
mSaveCount = 1;
mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
mRestoreSaveCount = -1;
}
void DisplayListRenderer::finish() {
insertRestoreToCount();
OpenGLRenderer::finish();
}
void DisplayListRenderer::interrupt() {
}
void DisplayListRenderer::resume() {
}
bool DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
// Ignore dirty during recording, it matters only when we replay
addOp(DisplayList::DrawGLFunction);
addInt((int) functor);
return false; // No invalidate needed at record-time
}
int DisplayListRenderer::save(int flags) {
addOp(DisplayList::Save);
addInt(flags);
return OpenGLRenderer::save(flags);
}
void DisplayListRenderer::restore() {
addOp(DisplayList::Restore);
OpenGLRenderer::restore();
}
void DisplayListRenderer::restoreToCount(int saveCount) {
mRestoreSaveCount = saveCount;
OpenGLRenderer::restoreToCount(saveCount);
}
int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
SkPaint* p, int flags) {
addOp(DisplayList::SaveLayer);
addBounds(left, top, right, bottom);
addPaint(p);
addInt(flags);
return OpenGLRenderer::save(flags);
}
int DisplayListRenderer::saveLayerAlpha(float left, float top, float right, float bottom,
int alpha, int flags) {
addOp(DisplayList::SaveLayerAlpha);
addBounds(left, top, right, bottom);
addInt(alpha);
addInt(flags);
return OpenGLRenderer::save(flags);
}
void DisplayListRenderer::translate(float dx, float dy) {
addOp(DisplayList::Translate);
addPoint(dx, dy);
OpenGLRenderer::translate(dx, dy);
}
void DisplayListRenderer::rotate(float degrees) {
addOp(DisplayList::Rotate);
addFloat(degrees);
OpenGLRenderer::rotate(degrees);
}
void DisplayListRenderer::scale(float sx, float sy) {
addOp(DisplayList::Scale);
addPoint(sx, sy);
OpenGLRenderer::scale(sx, sy);
}
void DisplayListRenderer::skew(float sx, float sy) {
addOp(DisplayList::Skew);
addPoint(sx, sy);
OpenGLRenderer::skew(sx, sy);
}
void DisplayListRenderer::setMatrix(SkMatrix* matrix) {
addOp(DisplayList::SetMatrix);
addMatrix(matrix);
OpenGLRenderer::setMatrix(matrix);
}
void DisplayListRenderer::concatMatrix(SkMatrix* matrix) {
addOp(DisplayList::ConcatMatrix);
addMatrix(matrix);
OpenGLRenderer::concatMatrix(matrix);
}
bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
SkRegion::Op op) {
addOp(DisplayList::ClipRect);
addBounds(left, top, right, bottom);
addInt(op);
return OpenGLRenderer::clipRect(left, top, right, bottom, op);
}
bool DisplayListRenderer::drawDisplayList(DisplayList* displayList,
uint32_t width, uint32_t height, Rect& dirty, uint32_t level) {
// dirty is an out parameter and should not be recorded,
// it matters only when replaying the display list
addOp(DisplayList::DrawDisplayList);
addDisplayList(displayList);
addSize(width, height);
return false;
}
void DisplayListRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* paint) {
addOp(DisplayList::DrawLayer);
addInt((int) layer);
addPoint(x, y);
addPaint(paint);
}
void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
SkPaint* paint) {
addOp(DisplayList::DrawBitmap);
addBitmap(bitmap);
addPoint(left, top);
addPaint(paint);
}
void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix,
SkPaint* paint) {
addOp(DisplayList::DrawBitmapMatrix);
addBitmap(bitmap);
addMatrix(matrix);
addPaint(paint);
}
void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
float dstRight, float dstBottom, SkPaint* paint) {
addOp(DisplayList::DrawBitmapRect);
addBitmap(bitmap);
addBounds(srcLeft, srcTop, srcRight, srcBottom);
addBounds(dstLeft, dstTop, dstRight, dstBottom);
addPaint(paint);
}
void DisplayListRenderer::drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
float* vertices, int* colors, SkPaint* paint) {
addOp(DisplayList::DrawBitmapMesh);
addBitmap(bitmap);
addInt(meshWidth);
addInt(meshHeight);
addFloats(vertices, (meshWidth + 1) * (meshHeight + 1) * 2);
if (colors) {
addInt(1);
addInts(colors, (meshWidth + 1) * (meshHeight + 1));
} else {
addInt(0);
}
addPaint(paint);
}
void DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
const uint32_t* colors, uint32_t width, uint32_t height, int8_t numColors,
float left, float top, float right, float bottom, SkPaint* paint) {
addOp(DisplayList::DrawPatch);
addBitmap(bitmap);
addInts(xDivs, width);
addInts(yDivs, height);
addUInts(colors, numColors);
addBounds(left, top, right, bottom);
addPaint(paint);
}
void DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) {
addOp(DisplayList::DrawColor);
addInt(color);
addInt(mode);
}
void DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
SkPaint* paint) {
addOp(DisplayList::DrawRect);
addBounds(left, top, right, bottom);
addPaint(paint);
}
void DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
float rx, float ry, SkPaint* paint) {
addOp(DisplayList::DrawRoundRect);
addBounds(left, top, right, bottom);
addPoint(rx, ry);
addPaint(paint);
}
void DisplayListRenderer::drawCircle(float x, float y, float radius, SkPaint* paint) {
addOp(DisplayList::DrawCircle);
addPoint(x, y);
addFloat(radius);
addPaint(paint);
}
void DisplayListRenderer::drawOval(float left, float top, float right, float bottom,
SkPaint* paint) {
addOp(DisplayList::DrawOval);
addBounds(left, top, right, bottom);
addPaint(paint);
}
void DisplayListRenderer::drawArc(float left, float top, float right, float bottom,
float startAngle, float sweepAngle, bool useCenter, SkPaint* paint) {
addOp(DisplayList::DrawArc);
addBounds(left, top, right, bottom);
addPoint(startAngle, sweepAngle);
addInt(useCenter ? 1 : 0);
addPaint(paint);
}
void DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) {
addOp(DisplayList::DrawPath);
addPath(path);
addPaint(paint);
}
void DisplayListRenderer::drawLines(float* points, int count, SkPaint* paint) {
addOp(DisplayList::DrawLines);
addFloats(points, count);
addPaint(paint);
}
void DisplayListRenderer::drawPoints(float* points, int count, SkPaint* paint) {
addOp(DisplayList::DrawPoints);
addFloats(points, count);
addPaint(paint);
}
void DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
float x, float y, SkPaint* paint) {
if (count <= 0) return;
addOp(DisplayList::DrawText);
addText(text, bytesCount);
addInt(count);
addPoint(x, y);
addPaint(paint);
}
void DisplayListRenderer::resetShader() {
addOp(DisplayList::ResetShader);
}
void DisplayListRenderer::setupShader(SkiaShader* shader) {
addOp(DisplayList::SetupShader);
addShader(shader);
}
void DisplayListRenderer::resetColorFilter() {
addOp(DisplayList::ResetColorFilter);
}
void DisplayListRenderer::setupColorFilter(SkiaColorFilter* filter) {
addOp(DisplayList::SetupColorFilter);
addColorFilter(filter);
}
void DisplayListRenderer::resetShadow() {
addOp(DisplayList::ResetShadow);
}
void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
addOp(DisplayList::SetupShadow);
addFloat(radius);
addPoint(dx, dy);
addInt(color);
}
}; // namespace uirenderer
}; // namespace android