android_frameworks_base/libs/hwui/DisplayListRenderer.cpp
Chet Haase 5a7e828842 Fix crash when Paths are GCd in hw accelerated apps
A recent change to optimize path rendering didn't account for
the destruction of native objects by the VM finalizer. We may be
done with the Java level version before we're done with the native
structure that's used by the display list. For example, a drawing
method on a View that creates a temporary path to render into the
canvas will implicitly create a native structure that is put onto
the GL display list. That temporary path may go away, but the native
version should stick around as long as the display list does.

The fix is to refcount the original native version of the path
and only delete it when the refcoutn reaches zero (which means that
it is no longer needed by any display list). This is a similar mechanism
used for bitmaps and shaders.

Change-Id: I4de1047415066d425d1c689aa60827f97729b470
2011-02-04 12:50:55 -08:00

839 lines
27 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 "DisplayListRenderer.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",
"DrawText",
"ResetShader",
"SetupShader",
"ResetColorFilter",
"SetupColorFilter",
"ResetShadow",
"SetupShadow",
"DrawGLFunction"
};
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 < mShaders.size(); i++) {
caches.resourceCache.decrementRefcount(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++) {
delete mPaths.itemAt(i);
}
mPaths.clear();
for (size_t i = 0; i < mOriginalPaths.size(); i++) {
caches.resourceCache.decrementRefcount(mOriginalPaths.itemAt(i));
}
mOriginalPaths.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<SkiaShader*> &shaders = recorder.getShaders();
for (size_t i = 0; i < shaders.size(); i++) {
SkiaShader* shader = shaders.itemAt(i);
mShaders.add(shader);
caches.resourceCache.incrementRefcount(shader);
}
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<SkPath*> &originalPaths = recorder.getOriginalPaths();
for (size_t i = 0; i < originalPaths.size(); i++) {
SkPath* path = originalPaths.itemAt(i);
mOriginalPaths.add(path);
caches.resourceCache.incrementRefcount(path);
}
const Vector<SkMatrix*> &matrices = recorder.getMatrices();
for (size_t i = 0; i < matrices.size(); i++) {
mMatrices.add(matrices.itemAt(i));
}
}
void DisplayList::init() {
}
bool DisplayList::replay(OpenGLRenderer& renderer, 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
int saveCount = renderer.getSaveCount() - 1;
while (!mReader.eof()) {
int op = mReader.readInt();
switch (op) {
case DrawGLFunction: {
Functor *functor = (Functor *) getInt();
DISPLAY_LIST_LOGD("%s%s %p", (char*) indent, OP_NAMES[op], functor);
needsInvalidate |= renderer.callDrawGLFunction(functor);
}
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();
DISPLAY_LIST_LOGD("%s%s %p, %d", (char*) indent, OP_NAMES[op],
displayList, level + 1);
needsInvalidate |= renderer.drawDisplayList(displayList, 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;
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.drawBitmapMesh(bitmap, meshWidth, meshHeight, vertices, colors, getPaint());
}
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]);
renderer.drawPatch(bitmap, xDivs, yDivs, colors, xDivsCount, yDivsCount,
numColors, getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
}
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);
DISPLAY_LIST_LOGD("%s%s", (char*) indent, OP_NAMES[op]);
renderer.drawLines(points, count, getPaint());
}
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) {
mDisplayList = NULL;
}
DisplayListRenderer::~DisplayListRenderer() {
reset();
}
void DisplayListRenderer::reset() {
mWriter.reset();
Caches& caches = Caches::getInstance();
for (size_t i = 0; i < mBitmapResources.size(); i++) {
SkBitmap* resource = mBitmapResources.itemAt(i);
caches.resourceCache.decrementRefcount(resource);
}
mBitmapResources.clear();
for (size_t i = 0; i < mOriginalPaths.size(); i++) {
SkPath* resource = mOriginalPaths.itemAt(i);
caches.resourceCache.decrementRefcount(resource);
}
mOriginalPaths.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() {
if (mDisplayList == NULL) {
mDisplayList = new DisplayList(*this);
} else {
mDisplayList->initFromDisplayListRenderer(*this, true);
}
return mDisplayList;
}
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) {
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 level) {
addOp(DisplayList::DrawDisplayList);
addDisplayList(displayList);
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::drawText(const char* text, int bytesCount, int count,
float x, float y, SkPaint* paint) {
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