Bug #4092053 The problem always existed but was made visible by partial invalidation. When saving a layer, the renderer would try to postpone glClear() operations until the next drawing command. This however does not work since the clip might have changed. The fix is rather simple and simply gets rid of this "optimization" (that turned out to be usless anyway given how View issues saveLayer() calls.) This change also fixes an issue with gradients (color stops where not properly computed when using a null stops array) and optimizes display lists rendering (quickly rejects larger portions of the tree to avoid executing unnecessary code.) Change-Id: I0f5b5f6e1220d41a09cc2fa84c212b0b4afd9c46
847 lines
28 KiB
C++
847 lines
28 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, 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
|
|
|
|
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, 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;
|
|
|
|
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, 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::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
|