The new implementation relies on OpenGLRenderer's existing layer code instead of duplicating it. The new code is much cleaner, with simpler and better APIs and allows tracking of drawn regions inside layers. Region tracking is not yet enabled but this will be done in a future CL. Change-Id: Ie826121a2227de8252c77b992a61218defea5143
600 lines
17 KiB
C++
600 lines
17 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 {
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Defines
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define PATH_HEAP_SIZE 64
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Helpers
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
PathHeap::PathHeap(): mHeap(PATH_HEAP_SIZE * sizeof(SkPath)) {
|
|
}
|
|
|
|
PathHeap::PathHeap(SkFlattenableReadBuffer& buffer): mHeap(PATH_HEAP_SIZE * sizeof(SkPath)) {
|
|
int count = buffer.readS32();
|
|
|
|
mPaths.setCount(count);
|
|
SkPath** ptr = mPaths.begin();
|
|
SkPath* p = (SkPath*) mHeap.allocThrow(count * sizeof(SkPath));
|
|
|
|
for (int i = 0; i < count; i++) {
|
|
new (p) SkPath;
|
|
p->unflatten(buffer);
|
|
*ptr++ = p;
|
|
p++;
|
|
}
|
|
}
|
|
|
|
PathHeap::~PathHeap() {
|
|
SkPath** iter = mPaths.begin();
|
|
SkPath** stop = mPaths.end();
|
|
while (iter < stop) {
|
|
(*iter)->~SkPath();
|
|
iter++;
|
|
}
|
|
}
|
|
|
|
int PathHeap::append(const SkPath& path) {
|
|
SkPath* p = (SkPath*) mHeap.allocThrow(sizeof(SkPath));
|
|
new (p) SkPath(path);
|
|
*mPaths.append() = p;
|
|
return mPaths.count();
|
|
}
|
|
|
|
void PathHeap::flatten(SkFlattenableWriteBuffer& buffer) const {
|
|
int count = mPaths.count();
|
|
|
|
buffer.write32(count);
|
|
SkPath** iter = mPaths.begin();
|
|
SkPath** stop = mPaths.end();
|
|
while (iter < stop) {
|
|
(*iter)->flatten(buffer);
|
|
iter++;
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Display list
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
DisplayList::DisplayList(const DisplayListRenderer& recorder) {
|
|
initFromDisplayListRenderer(recorder);
|
|
}
|
|
|
|
DisplayList::~DisplayList() {
|
|
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 < mShaderResources.size(); i++) {
|
|
caches.resourceCache.decrementRefcount(mShaderResources.itemAt(i));
|
|
}
|
|
mShaderResources.clear();
|
|
|
|
for (size_t i = 0; i < mPaints.size(); i++) {
|
|
delete mPaints.itemAt(i);
|
|
}
|
|
mPaints.clear();
|
|
|
|
for (size_t i = 0; i < mMatrices.size(); i++) {
|
|
delete mMatrices.itemAt(i);
|
|
}
|
|
mMatrices.clear();
|
|
|
|
if (mPathHeap) {
|
|
for (int i = 0; i < mPathHeap->count(); i++) {
|
|
caches.pathCache.removeDeferred(&(*mPathHeap)[i]);
|
|
}
|
|
mPathHeap->safeUnref();
|
|
}
|
|
}
|
|
|
|
void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorder) {
|
|
const SkWriter32& writer = recorder.writeStream();
|
|
init();
|
|
|
|
if (writer.size() == 0) {
|
|
return;
|
|
}
|
|
|
|
size_t size = writer.size();
|
|
void* buffer = sk_malloc_throw(size);
|
|
writer.flatten(buffer);
|
|
mReader.setMemory(buffer, size);
|
|
|
|
mRCPlayback.reset(&recorder.mRCRecorder);
|
|
mRCPlayback.setupBuffer(mReader);
|
|
|
|
mTFPlayback.reset(&recorder.mTFRecorder);
|
|
mTFPlayback.setupBuffer(mReader);
|
|
|
|
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*> &shaderResources = recorder.getShaderResources();
|
|
for (size_t i = 0; i < shaderResources.size(); i++) {
|
|
SkiaShader* resource = shaderResources.itemAt(i);
|
|
mShaderResources.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<SkMatrix*> &matrices = recorder.getMatrices();
|
|
for (size_t i = 0; i < matrices.size(); i++) {
|
|
mMatrices.add(matrices.itemAt(i));
|
|
}
|
|
|
|
mPathHeap = recorder.mPathHeap;
|
|
if (mPathHeap) {
|
|
mPathHeap->safeRef();
|
|
}
|
|
}
|
|
|
|
void DisplayList::init() {
|
|
mPathHeap = NULL;
|
|
}
|
|
|
|
void DisplayList::replay(OpenGLRenderer& renderer) {
|
|
TextContainer text;
|
|
mReader.rewind();
|
|
|
|
int saveCount = renderer.getSaveCount() - 1;
|
|
|
|
while (!mReader.eof()) {
|
|
int op = mReader.readInt();
|
|
switch (op) {
|
|
case AcquireContext: {
|
|
renderer.acquireContext();
|
|
}
|
|
break;
|
|
case ReleaseContext: {
|
|
renderer.releaseContext();
|
|
}
|
|
break;
|
|
case Save: {
|
|
renderer.save(getInt());
|
|
}
|
|
break;
|
|
case Restore: {
|
|
renderer.restore();
|
|
}
|
|
break;
|
|
case RestoreToCount: {
|
|
renderer.restoreToCount(saveCount + getInt());
|
|
}
|
|
break;
|
|
case SaveLayer: {
|
|
renderer.saveLayer(getFloat(), getFloat(), getFloat(), getFloat(),
|
|
getPaint(), getInt());
|
|
}
|
|
break;
|
|
case SaveLayerAlpha: {
|
|
renderer.saveLayerAlpha(getFloat(), getFloat(), getFloat(), getFloat(),
|
|
getInt(), getInt());
|
|
}
|
|
break;
|
|
case Translate: {
|
|
renderer.translate(getFloat(), getFloat());
|
|
}
|
|
break;
|
|
case Rotate: {
|
|
renderer.rotate(getFloat());
|
|
}
|
|
break;
|
|
case Scale: {
|
|
renderer.scale(getFloat(), getFloat());
|
|
}
|
|
break;
|
|
case SetMatrix: {
|
|
renderer.setMatrix(getMatrix());
|
|
}
|
|
break;
|
|
case ConcatMatrix: {
|
|
renderer.concatMatrix(getMatrix());
|
|
}
|
|
break;
|
|
case ClipRect: {
|
|
renderer.clipRect(getFloat(), getFloat(), getFloat(), getFloat(),
|
|
(SkRegion::Op) getInt());
|
|
}
|
|
break;
|
|
case DrawDisplayList: {
|
|
renderer.drawDisplayList(getDisplayList());
|
|
}
|
|
break;
|
|
case DrawLayer: {
|
|
renderer.drawLayer((Layer*) getInt(), getFloat(), getFloat(), getPaint());
|
|
}
|
|
break;
|
|
case DrawBitmap: {
|
|
renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getPaint());
|
|
}
|
|
break;
|
|
case DrawBitmapMatrix: {
|
|
renderer.drawBitmap(getBitmap(), getMatrix(), getPaint());
|
|
}
|
|
break;
|
|
case DrawBitmapRect: {
|
|
renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getFloat(), getFloat(),
|
|
getFloat(), getFloat(), getFloat(), getFloat(), 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);
|
|
|
|
renderer.drawPatch(bitmap, xDivs, yDivs, colors, xDivsCount, yDivsCount,
|
|
numColors, getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
|
|
}
|
|
break;
|
|
case DrawColor: {
|
|
renderer.drawColor(getInt(), (SkXfermode::Mode) getInt());
|
|
}
|
|
break;
|
|
case DrawRect: {
|
|
renderer.drawRect(getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
|
|
}
|
|
break;
|
|
case DrawPath: {
|
|
renderer.drawPath(getPath(), getPaint());
|
|
}
|
|
break;
|
|
case DrawLines: {
|
|
int count = 0;
|
|
float* points = getFloats(count);
|
|
renderer.drawLines(points, count, getPaint());
|
|
}
|
|
break;
|
|
case DrawText: {
|
|
getText(&text);
|
|
renderer.drawText(text.text(), text.length(), getInt(),
|
|
getFloat(), getFloat(), getPaint());
|
|
}
|
|
break;
|
|
case ResetShader: {
|
|
renderer.resetShader();
|
|
}
|
|
break;
|
|
case SetupShader: {
|
|
renderer.setupShader(getShader());
|
|
}
|
|
break;
|
|
case ResetColorFilter: {
|
|
renderer.resetColorFilter();
|
|
}
|
|
break;
|
|
case SetupColorFilter: {
|
|
renderer.setupColorFilter(getColorFilter());
|
|
}
|
|
break;
|
|
case ResetShadow: {
|
|
renderer.resetShadow();
|
|
}
|
|
break;
|
|
case SetupShadow: {
|
|
renderer.setupShadow(getFloat(), getFloat(), getFloat(), getInt());
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Base structure
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
DisplayListRenderer::DisplayListRenderer():
|
|
mHeap(HEAP_BLOCK_SIZE), mWriter(MIN_WRITER_SIZE) {
|
|
mPathHeap = NULL;
|
|
mDisplayList = NULL;
|
|
}
|
|
|
|
DisplayListRenderer::~DisplayListRenderer() {
|
|
reset();
|
|
}
|
|
|
|
void DisplayListRenderer::reset() {
|
|
if (mPathHeap) {
|
|
mPathHeap->unref();
|
|
mPathHeap = NULL;
|
|
}
|
|
|
|
mWriter.reset();
|
|
mHeap.reset();
|
|
|
|
mRCRecorder.reset();
|
|
mTFRecorder.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 < mShaderResources.size(); i++) {
|
|
SkiaShader* resource = mShaderResources.itemAt(i);
|
|
caches.resourceCache.decrementRefcount(resource);
|
|
}
|
|
mShaderResources.clear();
|
|
|
|
mPaints.clear();
|
|
mPaintMap.clear();
|
|
mMatrices.clear();
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Operations
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
DisplayList* DisplayListRenderer::getDisplayList() {
|
|
if (mDisplayList == NULL) {
|
|
mDisplayList = new DisplayList(*this);
|
|
} else {
|
|
mDisplayList->initFromDisplayListRenderer(*this);
|
|
}
|
|
return mDisplayList;
|
|
}
|
|
|
|
void DisplayListRenderer::setViewport(int width, int height) {
|
|
mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
|
|
|
|
mWidth = width;
|
|
mHeight = height;
|
|
}
|
|
|
|
void DisplayListRenderer::prepare(bool opaque) {
|
|
mSnapshot = new Snapshot(mFirstSnapshot,
|
|
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
|
|
mSaveCount = 1;
|
|
mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
|
|
}
|
|
|
|
void DisplayListRenderer::acquireContext() {
|
|
addOp(DisplayList::AcquireContext);
|
|
OpenGLRenderer::acquireContext();
|
|
}
|
|
|
|
void DisplayListRenderer::releaseContext() {
|
|
addOp(DisplayList::ReleaseContext);
|
|
OpenGLRenderer::releaseContext();
|
|
}
|
|
|
|
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) {
|
|
addOp(DisplayList::RestoreToCount);
|
|
addInt(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::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);
|
|
}
|
|
|
|
void DisplayListRenderer::drawDisplayList(DisplayList* displayList) {
|
|
addOp(DisplayList::DrawDisplayList);
|
|
addDisplayList(displayList);
|
|
}
|
|
|
|
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::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::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
|