android_frameworks_base/libs/hwui/DisplayListRenderer.cpp
Chet Haase a23eed808a Fix layer blending bug
Cached layers were sometimes retaining an obsolete blending
value, causing artifacts where translucent objects were disappearing
completely. Also, added extra tracing info for DisplayLists.

Issue #6303668 Flickering views during SwipeHelper drag

Change-Id: I66ce158652c4a3ed316040585b40b1744e1fad0c
2012-04-12 15:20:16 -07:00

1691 lines
62 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 <SkCamera.h>
#include <private/hwui/DrawGlInfo.h>
#include "DisplayListLogBuffer.h"
#include "DisplayListRenderer.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",
"DrawTextOnPath",
"DrawPosText",
"ResetShader",
"SetupShader",
"ResetColorFilter",
"SetupColorFilter",
"ResetShadow",
"SetupShadow",
"ResetPaintFilter",
"SetupPaintFilter",
"DrawGLFunction"
};
void DisplayList::outputLogBuffer(int fd) {
DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
if (logBuffer.isEmpty()) {
return;
}
FILE *file = fdopen(fd, "a");
fprintf(file, "\nRecent DisplayList operations\n");
logBuffer.outputCommands(file, OP_NAMES);
String8 cachesLog;
Caches::getInstance().dumpMemoryUsage(cachesLog);
fprintf(file, "\nCaches:\n%s", cachesLog.string());
fprintf(file, "\n");
fflush(file);
}
DisplayList::DisplayList(const DisplayListRenderer& recorder) :
mTransformMatrix(NULL), mTransformCamera(NULL), mTransformMatrix3D(NULL),
mStaticMatrix(NULL), mAnimationMatrix(NULL) {
initFromDisplayListRenderer(recorder);
}
DisplayList::~DisplayList() {
clearResources();
}
void DisplayList::initProperties() {
mLeft = 0;
mTop = 0;
mRight = 0;
mBottom = 0;
mClipChildren = true;
mAlpha = 1;
mMultipliedAlpha = 255;
mHasOverlappingRendering = true;
mTranslationX = 0;
mTranslationY = 0;
mRotation = 0;
mRotationX = 0;
mRotationY= 0;
mScaleX = 1;
mScaleY = 1;
mPivotX = 0;
mPivotY = 0;
mCameraDistance = 0;
mMatrixDirty = false;
mMatrixFlags = 0;
mPrevWidth = -1;
mPrevHeight = -1;
mWidth = 0;
mHeight = 0;
mPivotExplicitlySet = false;
mCaching = false;
}
void DisplayList::destroyDisplayListDeferred(DisplayList* displayList) {
if (displayList) {
DISPLAY_LIST_LOGD("Deferring display list destruction");
Caches::getInstance().deleteDisplayListDeferred(displayList);
}
}
void DisplayList::clearResources() {
sk_free((void*) mReader.base());
if (USE_DISPLAY_LIST_PROPERTIES) {
delete mTransformMatrix;
delete mTransformCamera;
delete mTransformMatrix3D;
delete mStaticMatrix;
delete mAnimationMatrix;
mTransformMatrix = NULL;
mTransformCamera = NULL;
mTransformMatrix3D = NULL;
mStaticMatrix = NULL;
mAnimationMatrix = NULL;
}
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();
}
initProperties();
mSize = writer.size();
void* buffer = sk_malloc_throw(mSize);
writer.flatten(buffer);
mReader.setMemory(buffer, mSize);
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() {
mSize = 0;
mIsRenderable = true;
}
size_t DisplayList::getSize() {
return mSize;
}
/**
* 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';
ALOGD("%sStart display list (%p, %s)", (char*) indent + 2, this, mName.string());
int saveCount = renderer.getSaveCount() - 1;
outputViewProperties(renderer, (char*) indent);
mReader.rewind();
while (!mReader.eof()) {
int op = mReader.readInt();
if (op & OP_MAY_BE_SKIPPED_MASK) {
int skip = mReader.readInt();
ALOGD("%sSkip %d", (char*) indent, skip);
op &= ~OP_MAY_BE_SKIPPED_MASK;
}
switch (op) {
case DrawGLFunction: {
Functor *functor = (Functor *) getInt();
ALOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
}
break;
case Save: {
int rendererNum = getInt();
ALOGD("%s%s %d", (char*) indent, OP_NAMES[op], rendererNum);
}
break;
case Restore: {
ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
}
break;
case RestoreToCount: {
int restoreCount = saveCount + getInt();
ALOGD("%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(renderer);
int flags = getInt();
ALOGD("%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();
ALOGD("%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();
ALOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], f1, f2);
}
break;
case Rotate: {
float rotation = getFloat();
ALOGD("%s%s %.2f", (char*) indent, OP_NAMES[op], rotation);
}
break;
case Scale: {
float sx = getFloat();
float sy = getFloat();
ALOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
}
break;
case Skew: {
float sx = getFloat();
float sy = getFloat();
ALOGD("%s%s %.2f, %.2f", (char*) indent, OP_NAMES[op], sx, sy);
}
break;
case SetMatrix: {
SkMatrix* matrix = getMatrix();
ALOGD("%s%s %p", (char*) indent, OP_NAMES[op], matrix);
}
break;
case ConcatMatrix: {
SkMatrix* matrix = getMatrix();
ALOGD("%s%s new concat %p: [%f, %f, %f] [%f, %f, %f] [%f, %f, %f]",
(char*) indent, OP_NAMES[op], matrix, matrix->get(0), matrix->get(1),
matrix->get(2), matrix->get(3), matrix->get(4), matrix->get(5),
matrix->get(6), matrix->get(7), matrix->get(8));
}
break;
case ClipRect: {
float f1 = getFloat();
float f2 = getFloat();
float f3 = getFloat();
float f4 = getFloat();
int regionOp = getInt();
ALOGD("%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();
int32_t flags = getInt();
ALOGD("%s%s %p, %dx%d, 0x%x %d", (char*) indent, OP_NAMES[op],
displayList, width, height, flags, level + 1);
renderer.outputDisplayList(displayList, level + 1);
}
break;
case DrawLayer: {
Layer* layer = (Layer*) getInt();
float x = getFloat();
float y = getFloat();
SkPaint* paint = getPaint(renderer);
ALOGD("%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(renderer);
ALOGD("%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(renderer);
ALOGD("%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(renderer);
ALOGD("%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(renderer);
ALOGD("%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);
float left = getFloat();
float top = getFloat();
float right = getFloat();
float bottom = getFloat();
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s %.2f, %.2f, %.2f, %.2f", (char*) indent, OP_NAMES[op],
left, top, right, bottom);
}
break;
case DrawColor: {
int color = getInt();
int xferMode = getInt();
ALOGD("%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(renderer);
ALOGD("%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(renderer);
ALOGD("%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(renderer);
ALOGD("%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(renderer);
ALOGD("%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(renderer);
ALOGD("%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(renderer);
ALOGD("%s%s %p, %p", (char*) indent, OP_NAMES[op], path, paint);
}
break;
case DrawLines: {
int count = 0;
float* points = getFloats(count);
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
}
break;
case DrawPoints: {
int count = 0;
float* points = getFloats(count);
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
}
break;
case DrawText: {
getText(&text);
int32_t count = getInt();
float x = getFloat();
float y = getFloat();
SkPaint* paint = getPaint(renderer);
float length = getFloat();
ALOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent, OP_NAMES[op],
text.text(), text.length(), count, x, y, paint, length);
}
break;
case DrawTextOnPath: {
getText(&text);
int32_t count = getInt();
SkPath* path = getPath();
float hOffset = getFloat();
float vOffset = getFloat();
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
text.text(), text.length(), count, paint);
}
break;
case DrawPosText: {
getText(&text);
int count = getInt();
int positionsCount = 0;
float* positions = getFloats(positionsCount);
SkPaint* paint = getPaint(renderer);
ALOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
text.text(), text.length(), count, paint);
}
case ResetShader: {
ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
}
break;
case SetupShader: {
SkiaShader* shader = getShader();
ALOGD("%s%s %p", (char*) indent, OP_NAMES[op], shader);
}
break;
case ResetColorFilter: {
ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
}
break;
case SetupColorFilter: {
SkiaColorFilter *colorFilter = getColorFilter();
ALOGD("%s%s %p", (char*) indent, OP_NAMES[op], colorFilter);
}
break;
case ResetShadow: {
ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
}
break;
case SetupShadow: {
float radius = getFloat();
float dx = getFloat();
float dy = getFloat();
int color = getInt();
ALOGD("%s%s %.2f, %.2f, %.2f, 0x%x", (char*) indent, OP_NAMES[op],
radius, dx, dy, color);
}
break;
case ResetPaintFilter: {
ALOGD("%s%s", (char*) indent, OP_NAMES[op]);
}
break;
case SetupPaintFilter: {
int clearBits = getInt();
int setBits = getInt();
ALOGD("%s%s 0x%x, 0x%x", (char*) indent, OP_NAMES[op], clearBits, setBits);
}
break;
default:
ALOGD("Display List error: op not handled: %s%s",
(char*) indent, OP_NAMES[op]);
break;
}
}
ALOGD("%sDone (%p, %s)", (char*) indent + 2, this, mName.string());
}
void DisplayList::updateMatrix() {
if (mMatrixDirty) {
if (!mTransformMatrix) {
mTransformMatrix = new SkMatrix();
}
if (mMatrixFlags == 0 || mMatrixFlags == TRANSLATION) {
mTransformMatrix->reset();
} else {
if (!mPivotExplicitlySet) {
if (mWidth != mPrevWidth || mHeight != mPrevHeight) {
mPrevWidth = mWidth;
mPrevHeight = mHeight;
mPivotX = mPrevWidth / 2;
mPivotY = mPrevHeight / 2;
}
}
if ((mMatrixFlags & ROTATION_3D) == 0) {
mTransformMatrix->setTranslate(mTranslationX, mTranslationY);
mTransformMatrix->preRotate(mRotation, mPivotX, mPivotY);
mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
} else {
if (!mTransformCamera) {
mTransformCamera = new Sk3DView();
mTransformMatrix3D = new SkMatrix();
}
mTransformMatrix->reset();
mTransformCamera->save();
mTransformMatrix->preScale(mScaleX, mScaleY, mPivotX, mPivotY);
mTransformCamera->rotateX(mRotationX);
mTransformCamera->rotateY(mRotationY);
mTransformCamera->rotateZ(-mRotation);
mTransformCamera->getMatrix(mTransformMatrix3D);
mTransformMatrix3D->preTranslate(-mPivotX, -mPivotY);
mTransformMatrix3D->postTranslate(mPivotX + mTranslationX,
mPivotY + mTranslationY);
mTransformMatrix->postConcat(*mTransformMatrix3D);
mTransformCamera->restore();
}
}
mMatrixDirty = false;
}
}
void DisplayList::outputViewProperties(OpenGLRenderer& renderer, char* indent) {
if (USE_DISPLAY_LIST_PROPERTIES) {
updateMatrix();
if (mLeft != 0 || mTop != 0) {
ALOGD("%s%s %d, %d", indent, "Translate (left, top)", mLeft, mTop);
}
if (mStaticMatrix) {
ALOGD("%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
indent, "ConcatMatrix (static)", mStaticMatrix,
mStaticMatrix->get(0), mStaticMatrix->get(1),
mStaticMatrix->get(2), mStaticMatrix->get(3),
mStaticMatrix->get(4), mStaticMatrix->get(5),
mStaticMatrix->get(6), mStaticMatrix->get(7),
mStaticMatrix->get(8));
}
if (mAnimationMatrix) {
ALOGD("%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
indent, "ConcatMatrix (animation)", mAnimationMatrix,
mAnimationMatrix->get(0), mAnimationMatrix->get(1),
mAnimationMatrix->get(2), mAnimationMatrix->get(3),
mAnimationMatrix->get(4), mAnimationMatrix->get(5),
mAnimationMatrix->get(6), mAnimationMatrix->get(7),
mAnimationMatrix->get(8));
}
if (mMatrixFlags != 0) {
if (mMatrixFlags == TRANSLATION) {
ALOGD("%s%s %f, %f", indent, "Translate", mTranslationX, mTranslationY);
} else {
ALOGD("%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
indent, "ConcatMatrix", mTransformMatrix,
mTransformMatrix->get(0), mTransformMatrix->get(1),
mTransformMatrix->get(2), mTransformMatrix->get(3),
mTransformMatrix->get(4), mTransformMatrix->get(5),
mTransformMatrix->get(6), mTransformMatrix->get(7),
mTransformMatrix->get(8));
}
}
if (mAlpha < 1 && !mCaching) {
// TODO: should be able to store the size of a DL at record time and not
// have to pass it into this call. In fact, this information might be in the
// location/size info that we store with the new native transform data.
int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
if (mClipChildren) {
flags |= SkCanvas::kClipToLayer_SaveFlag;
}
ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
(float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
mMultipliedAlpha, flags);
}
if (mClipChildren) {
ALOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f,
(float) mRight - mLeft, (float) mBottom - mTop);
}
}
}
void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t width, uint32_t height,
uint32_t level) {
if (USE_DISPLAY_LIST_PROPERTIES) {
#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';
#endif
updateMatrix();
if (mLeft != 0 || mTop != 0) {
DISPLAY_LIST_LOGD("%s%s %d, %d", indent, "Translate (left, top)", mLeft, mTop);
renderer.translate(mLeft, mTop);
}
if (mStaticMatrix) {
DISPLAY_LIST_LOGD(
"%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
indent, "ConcatMatrix (static)", mStaticMatrix,
mStaticMatrix->get(0), mStaticMatrix->get(1),
mStaticMatrix->get(2), mStaticMatrix->get(3),
mStaticMatrix->get(4), mStaticMatrix->get(5),
mStaticMatrix->get(6), mStaticMatrix->get(7),
mStaticMatrix->get(8));
renderer.concatMatrix(mStaticMatrix);
} else if (mAnimationMatrix) {
DISPLAY_LIST_LOGD(
"%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
indent, "ConcatMatrix (animation)", mAnimationMatrix,
mAnimationMatrix->get(0), mAnimationMatrix->get(1),
mAnimationMatrix->get(2), mAnimationMatrix->get(3),
mAnimationMatrix->get(4), mAnimationMatrix->get(5),
mAnimationMatrix->get(6), mAnimationMatrix->get(7),
mAnimationMatrix->get(8));
renderer.concatMatrix(mAnimationMatrix);
}
if (mMatrixFlags != 0) {
if (mMatrixFlags == TRANSLATION) {
DISPLAY_LIST_LOGD("%s%s %f, %f", indent, "Translate", mTranslationX, mTranslationY);
renderer.translate(mTranslationX, mTranslationY);
} else {
DISPLAY_LIST_LOGD(
"%s%s %p: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
indent, "ConcatMatrix", mTransformMatrix,
mTransformMatrix->get(0), mTransformMatrix->get(1),
mTransformMatrix->get(2), mTransformMatrix->get(3),
mTransformMatrix->get(4), mTransformMatrix->get(5),
mTransformMatrix->get(6), mTransformMatrix->get(7),
mTransformMatrix->get(8));
renderer.concatMatrix(mTransformMatrix);
}
}
if (mAlpha < 1 && !mCaching) {
if (!mHasOverlappingRendering) {
DISPLAY_LIST_LOGD("%s%s %.2f", indent, "SetAlpha", mAlpha);
renderer.setAlpha(mAlpha);
} else {
// TODO: should be able to store the size of a DL at record time and not
// have to pass it into this call. In fact, this information might be in the
// location/size info that we store with the new native transform data.
int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
if (mClipChildren) {
flags |= SkCanvas::kClipToLayer_SaveFlag;
}
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
(float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
mMultipliedAlpha, flags);
renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
mMultipliedAlpha, flags);
}
}
if (mClipChildren) {
DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f,
(float) mRight - mLeft, (float) mBottom - mTop);
renderer.clipRect(0, 0, mRight - mLeft, mBottom - mTop,
SkRegion::kIntersect_Op);
}
}
}
/**
* 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.
*/
status_t DisplayList::replay(OpenGLRenderer& renderer, uint32_t width,
uint32_t height, Rect& dirty, int32_t flags, uint32_t level) {
status_t drawGlStatus = 0;
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';
Rect* clipRect = renderer.getClipRect();
DISPLAY_LIST_LOGD("%sStart display list (%p, %s), clipRect: %.0f, %.f, %.0f, %.0f",
(char*) indent + 2, this, mName.string(), clipRect->left, clipRect->top,
clipRect->right, clipRect->bottom);
#endif
renderer.startMark(mName.string());
int restoreTo = 0;
if (USE_DISPLAY_LIST_PROPERTIES) {
DISPLAY_LIST_LOGD("%s%s %d", indent, "Save",
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
}
setViewProperties(renderer, width, height, level);
if (USE_DISPLAY_LIST_PROPERTIES && renderer.quickReject(0, 0, width, height)) {
DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, "RestoreToCount", restoreTo);
renderer.restoreToCount(restoreTo);
renderer.endMark();
return false;
}
DisplayListLogBuffer& logBuffer = DisplayListLogBuffer::getInstance();
int saveCount = renderer.getSaveCount() - 1;
while (!mReader.eof()) {
int op = mReader.readInt();
if (op & OP_MAY_BE_SKIPPED_MASK) {
int32_t skip = mReader.readInt();
if (CC_LIKELY(flags & kReplayFlag_ClipChildren)) {
mReader.skip(skip);
DISPLAY_LIST_LOGD("%s%s skipping %d bytes", (char*) indent,
OP_NAMES[op & ~OP_MAY_BE_SKIPPED_MASK], skip);
continue;
} else {
op &= ~OP_MAY_BE_SKIPPED_MASK;
}
}
logBuffer.writeCommand(level, op);
switch (op) {
case DrawGLFunction: {
Functor *functor = (Functor *) getInt();
DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
renderer.startMark("GL functor");
drawGlStatus |= renderer.callDrawGLFunction(functor, dirty);
renderer.endMark();
}
break;
case Save: {
int32_t 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: {
int32_t 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(renderer);
int32_t 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();
int32_t alpha = getInt();
int32_t 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: [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f] [%.2f, %.2f, %.2f]",
(char*) indent, OP_NAMES[op], matrix,
matrix->get(0), matrix->get(1), matrix->get(2),
matrix->get(3), matrix->get(4), matrix->get(5),
matrix->get(6), matrix->get(7), matrix->get(8));
renderer.concatMatrix(matrix);
}
break;
case ClipRect: {
float f1 = getFloat();
float f2 = getFloat();
float f3 = getFloat();
float f4 = getFloat();
int32_t 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();
int32_t flags = getInt();
DISPLAY_LIST_LOGD("%s%s %p, %dx%d, 0x%x %d", (char*) indent, OP_NAMES[op],
displayList, width, height, flags, level + 1);
drawGlStatus |= renderer.drawDisplayList(displayList, width,
height, dirty, flags, level + 1);
}
break;
case DrawLayer: {
Layer* layer = (Layer*) getInt();
float x = getFloat();
float y = getFloat();
SkPaint* paint = getPaint(renderer);
if (mCaching && mMultipliedAlpha < 255) {
paint->setAlpha(mMultipliedAlpha);
}
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(renderer);
if (mCaching && mMultipliedAlpha < 255) {
paint->setAlpha(mMultipliedAlpha);
}
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(renderer);
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(renderer);
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: {
int32_t verticesCount = 0;
uint32_t colorsCount = 0;
SkBitmap* bitmap = getBitmap();
uint32_t meshWidth = getInt();
uint32_t meshHeight = getInt();
float* vertices = getFloats(verticesCount);
bool hasColors = getInt();
int32_t* colors = hasColors ? getInts(colorsCount) : NULL;
SkPaint* paint = getPaint(renderer);
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(renderer);
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: {
int32_t color = getInt();
int32_t 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(renderer);
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(renderer);
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(renderer);
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(renderer);
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();
int32_t i1 = getInt();
SkPaint* paint = getPaint(renderer);
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(renderer);
DISPLAY_LIST_LOGD("%s%s %p, %p", (char*) indent, OP_NAMES[op], path, paint);
renderer.drawPath(path, paint);
}
break;
case DrawLines: {
int32_t count = 0;
float* points = getFloats(count);
SkPaint* paint = getPaint(renderer);
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.drawLines(points, count, paint);
}
break;
case DrawPoints: {
int32_t count = 0;
float* points = getFloats(count);
SkPaint* paint = getPaint(renderer);
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.drawPoints(points, count, paint);
}
break;
case DrawText: {
getText(&text);
int32_t count = getInt();
float x = getFloat();
float y = getFloat();
SkPaint* paint = getPaint(renderer);
float length = getFloat();
DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %.2f, %.2f, %p, %.2f", (char*) indent,
OP_NAMES[op], text.text(), text.length(), count, x, y, paint, length);
renderer.drawText(text.text(), text.length(), count, x, y, paint, length);
}
break;
case DrawTextOnPath: {
getText(&text);
int32_t count = getInt();
SkPath* path = getPath();
float hOffset = getFloat();
float vOffset = getFloat();
SkPaint* paint = getPaint(renderer);
DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %p", (char*) indent, OP_NAMES[op],
text.text(), text.length(), count, paint);
renderer.drawTextOnPath(text.text(), text.length(), count, path,
hOffset, vOffset, paint);
}
break;
case DrawPosText: {
getText(&text);
int32_t count = getInt();
int32_t positionsCount = 0;
float* positions = getFloats(positionsCount);
SkPaint* paint = getPaint(renderer);
DISPLAY_LIST_LOGD("%s%s %s, %d, %d, %p", (char*) indent,
OP_NAMES[op], text.text(), text.length(), count, paint);
renderer.drawPosText(text.text(), text.length(), count, positions, 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();
int32_t 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;
case ResetPaintFilter: {
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.resetPaintFilter();
}
break;
case SetupPaintFilter: {
int32_t clearBits = getInt();
int32_t setBits = getInt();
DISPLAY_LIST_LOGD("%s%s 0x%x, 0x%x", (char*) indent, OP_NAMES[op],
clearBits, setBits);
renderer.setupPaintFilter(clearBits, setBits);
}
break;
default:
DISPLAY_LIST_LOGD("Display List error: op not handled: %s%s",
(char*) indent, OP_NAMES[op]);
break;
}
}
if (USE_DISPLAY_LIST_PROPERTIES) {
DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, "RestoreToCount", restoreTo);
renderer.restoreToCount(restoreTo);
}
renderer.endMark();
DISPLAY_LIST_LOGD("%sDone (%p, %s), returning %d", (char*) indent + 2, this, mName.string(),
drawGlStatus);
return drawGlStatus;
}
///////////////////////////////////////////////////////////////////////////////
// Base structure
///////////////////////////////////////////////////////////////////////////////
DisplayListRenderer::DisplayListRenderer() : mWriter(MIN_WRITER_SIZE),
mTranslateX(0.0f), mTranslateY(0.0f), mHasTranslate(false), mHasDrawOps(false) {
}
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();
mHasDrawOps = false;
}
///////////////////////////////////////////////////////////////////////////////
// Operations
///////////////////////////////////////////////////////////////////////////////
DisplayList* DisplayListRenderer::getDisplayList(DisplayList* displayList) {
if (!displayList) {
displayList = new DisplayList(*this);
} else {
displayList->initFromDisplayListRenderer(*this, true);
}
displayList->setRenderable(mHasDrawOps);
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();
insertTranlate();
}
void DisplayListRenderer::interrupt() {
}
void DisplayListRenderer::resume() {
}
status_t DisplayListRenderer::callDrawGLFunction(Functor *functor, Rect& dirty) {
// Ignore dirty during recording, it matters only when we replay
addOp(DisplayList::DrawGLFunction);
addInt((int) functor);
return DrawGlInfo::kStatusDone; // No invalidate needed at record-time
}
int DisplayListRenderer::save(int flags) {
addOp(DisplayList::Save);
addInt(flags);
return OpenGLRenderer::save(flags);
}
void DisplayListRenderer::restore() {
if (mRestoreSaveCount < 0) {
restoreToCount(getSaveCount() - 1);
return;
}
mRestoreSaveCount--;
insertTranlate();
OpenGLRenderer::restore();
}
void DisplayListRenderer::restoreToCount(int saveCount) {
mRestoreSaveCount = saveCount;
insertTranlate();
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) {
mHasTranslate = true;
mTranslateX += dx;
mTranslateY += dy;
insertRestoreToCount();
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);
}
status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
uint32_t width, uint32_t height, Rect& dirty, int32_t flags, 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);
addInt(flags);
return DrawGlInfo::kStatusDone;
}
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) {
const bool reject = quickReject(left, top, left + bitmap->width(), top + bitmap->height());
uint32_t* location = addOp(DisplayList::DrawBitmap, reject);
addBitmap(bitmap);
addPoint(left, top);
addPaint(paint);
addSkip(location);
}
void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint) {
Rect r(0.0f, 0.0f, bitmap->width(), bitmap->height());
const mat4 transform(*matrix);
transform.mapRect(r);
const bool reject = quickReject(r.left, r.top, r.right, r.bottom);
uint32_t* location = addOp(DisplayList::DrawBitmapMatrix, reject);
addBitmap(bitmap);
addMatrix(matrix);
addPaint(paint);
addSkip(location);
}
void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
float srcRight, float srcBottom, float dstLeft, float dstTop,
float dstRight, float dstBottom, SkPaint* paint) {
const bool reject = quickReject(dstLeft, dstTop, dstRight, dstBottom);
uint32_t* location = addOp(DisplayList::DrawBitmapRect, reject);
addBitmap(bitmap);
addBounds(srcLeft, srcTop, srcRight, srcBottom);
addBounds(dstLeft, dstTop, dstRight, dstBottom);
addPaint(paint);
addSkip(location);
}
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) {
const bool reject = quickReject(left, top, right, bottom);
uint32_t* location = addOp(DisplayList::DrawPatch, reject);
addBitmap(bitmap);
addInts(xDivs, width);
addInts(yDivs, height);
addUInts(colors, numColors);
addBounds(left, top, right, bottom);
addPaint(paint);
addSkip(location);
}
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) {
const bool reject = paint->getStyle() == SkPaint::kFill_Style &&
quickReject(left, top, right, bottom);
uint32_t* location = addOp(DisplayList::DrawRect, reject);
addBounds(left, top, right, bottom);
addPaint(paint);
addSkip(location);
}
void DisplayListRenderer::drawRoundRect(float left, float top, float right, float bottom,
float rx, float ry, SkPaint* paint) {
const bool reject = paint->getStyle() == SkPaint::kFill_Style &&
quickReject(left, top, right, bottom);
uint32_t* location = addOp(DisplayList::DrawRoundRect, reject);
addBounds(left, top, right, bottom);
addPoint(rx, ry);
addPaint(paint);
addSkip(location);
}
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) {
float left, top, offset;
uint32_t width, height;
computePathBounds(path, paint, left, top, offset, width, height);
const bool reject = quickReject(left - offset, top - offset, width, height);
uint32_t* location = addOp(DisplayList::DrawPath, reject);
addPath(path);
addPaint(paint);
addSkip(location);
}
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, float length) {
if (!text || count <= 0) return;
// TODO: We should probably make a copy of the paint instead of modifying
// it; modifying the paint will change its generationID the first
// time, which might impact caches. More investigation needed to
// see if it matters.
// If we make a copy, then drawTextDecorations() should *not* make
// its own copy as it does right now.
// Beware: this needs Glyph encoding (already done on the Paint constructor)
paint->setAntiAlias(true);
if (length < 0.0f) length = paint->measureText(text, bytesCount);
bool reject = false;
if (CC_LIKELY(paint->getTextAlign() == SkPaint::kLeft_Align)) {
SkPaint::FontMetrics metrics;
paint->getFontMetrics(&metrics, 0.0f);
reject = quickReject(x, y + metrics.fTop, x + length, y + metrics.fBottom);
}
uint32_t* location = addOp(DisplayList::DrawText, reject);
addText(text, bytesCount);
addInt(count);
addPoint(x, y);
addPaint(paint);
addFloat(length);
addSkip(location);
}
void DisplayListRenderer::drawTextOnPath(const char* text, int bytesCount, int count,
SkPath* path, float hOffset, float vOffset, SkPaint* paint) {
if (!text || count <= 0) return;
addOp(DisplayList::DrawTextOnPath);
addText(text, bytesCount);
addInt(count);
addPath(path);
addFloat(hOffset);
addFloat(vOffset);
paint->setAntiAlias(true);
addPaint(paint);
}
void DisplayListRenderer::drawPosText(const char* text, int bytesCount, int count,
const float* positions, SkPaint* paint) {
if (!text || count <= 0) return;
addOp(DisplayList::DrawPosText);
addText(text, bytesCount);
addInt(count);
addFloats(positions, count * 2);
paint->setAntiAlias(true);
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);
}
void DisplayListRenderer::resetPaintFilter() {
addOp(DisplayList::ResetPaintFilter);
}
void DisplayListRenderer::setupPaintFilter(int clearBits, int setBits) {
addOp(DisplayList::SetupPaintFilter);
addInt(clearBits);
addInt(setBits);
}
}; // namespace uirenderer
}; // namespace android