487 lines
14 KiB
C++
487 lines
14 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.
|
|
*/
|
|
|
|
#ifndef ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
|
|
#define ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
|
|
|
|
#include <SkChunkAlloc.h>
|
|
#include <SkFlattenable.h>
|
|
#include <SkMatrix.h>
|
|
#include <SkPaint.h>
|
|
#include <SkPath.h>
|
|
#include <SkRefCnt.h>
|
|
#include <SkTDArray.h>
|
|
#include <SkTSearch.h>
|
|
|
|
#include "DisplayListLogBuffer.h"
|
|
#include "OpenGLRenderer.h"
|
|
#include "utils/Functor.h"
|
|
|
|
namespace android {
|
|
namespace uirenderer {
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Defines
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#define MIN_WRITER_SIZE 16384
|
|
|
|
// Debug
|
|
#if DEBUG_DISPLAY_LIST
|
|
#define DISPLAY_LIST_LOGD(...) LOGD(__VA_ARGS__)
|
|
#else
|
|
#define DISPLAY_LIST_LOGD(...)
|
|
#endif
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Display list
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
class DisplayListRenderer;
|
|
|
|
/**
|
|
* Replays recorded drawing commands.
|
|
*/
|
|
class DisplayList {
|
|
public:
|
|
DisplayList(const DisplayListRenderer& recorder);
|
|
~DisplayList();
|
|
|
|
// IMPORTANT: Update the intialization of OP_NAMES in the .cpp file
|
|
// when modifying this file
|
|
enum Op {
|
|
Save = 0,
|
|
Restore,
|
|
RestoreToCount,
|
|
SaveLayer,
|
|
SaveLayerAlpha,
|
|
Translate,
|
|
Rotate,
|
|
Scale,
|
|
Skew,
|
|
SetMatrix,
|
|
ConcatMatrix,
|
|
ClipRect,
|
|
DrawDisplayList,
|
|
DrawLayer,
|
|
DrawBitmap,
|
|
DrawBitmapMatrix,
|
|
DrawBitmapRect,
|
|
DrawBitmapMesh,
|
|
DrawPatch,
|
|
DrawColor,
|
|
DrawRect,
|
|
DrawRoundRect,
|
|
DrawCircle,
|
|
DrawOval,
|
|
DrawArc,
|
|
DrawPath,
|
|
DrawLines,
|
|
DrawPoints,
|
|
DrawText,
|
|
ResetShader,
|
|
SetupShader,
|
|
ResetColorFilter,
|
|
SetupColorFilter,
|
|
ResetShadow,
|
|
SetupShadow,
|
|
DrawGLFunction,
|
|
};
|
|
|
|
static const char* OP_NAMES[];
|
|
|
|
void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
|
|
|
|
bool replay(OpenGLRenderer& renderer, Rect& dirty, uint32_t level = 0);
|
|
|
|
static void outputLogBuffer(int fd);
|
|
|
|
private:
|
|
void init();
|
|
|
|
void clearResources();
|
|
|
|
class TextContainer {
|
|
public:
|
|
size_t length() const {
|
|
return mByteLength;
|
|
}
|
|
|
|
const char* text() const {
|
|
return (const char*) mText;
|
|
}
|
|
|
|
size_t mByteLength;
|
|
const char* mText;
|
|
};
|
|
|
|
SkBitmap* getBitmap() {
|
|
return (SkBitmap*) getInt();
|
|
}
|
|
|
|
SkiaShader* getShader() {
|
|
return (SkiaShader*) getInt();
|
|
}
|
|
|
|
SkiaColorFilter* getColorFilter() {
|
|
return (SkiaColorFilter*) getInt();
|
|
}
|
|
|
|
inline int getIndex() {
|
|
return mReader.readInt();
|
|
}
|
|
|
|
inline int getInt() {
|
|
return mReader.readInt();
|
|
}
|
|
|
|
inline uint32_t getUInt() {
|
|
return mReader.readU32();
|
|
}
|
|
|
|
SkMatrix* getMatrix() {
|
|
return (SkMatrix*) getInt();
|
|
}
|
|
|
|
SkPath* getPath() {
|
|
return (SkPath*) getInt();
|
|
}
|
|
|
|
SkPaint* getPaint() {
|
|
return (SkPaint*) getInt();
|
|
}
|
|
|
|
DisplayList* getDisplayList() {
|
|
return (DisplayList*) getInt();
|
|
}
|
|
|
|
inline float getFloat() {
|
|
return mReader.readScalar();
|
|
}
|
|
|
|
int32_t* getInts(uint32_t& count) {
|
|
count = getInt();
|
|
return (int32_t*) mReader.skip(count * sizeof(int32_t));
|
|
}
|
|
|
|
uint32_t* getUInts(int8_t& count) {
|
|
count = getInt();
|
|
return (uint32_t*) mReader.skip(count * sizeof(uint32_t));
|
|
}
|
|
|
|
float* getFloats(int& count) {
|
|
count = getInt();
|
|
return (float*) mReader.skip(count * sizeof(float));
|
|
}
|
|
|
|
void getText(TextContainer* text) {
|
|
size_t length = text->mByteLength = getInt();
|
|
text->mText = (const char*) mReader.skip(length);
|
|
}
|
|
|
|
Vector<SkBitmap*> mBitmapResources;
|
|
Vector<SkiaColorFilter*> mFilterResources;
|
|
|
|
Vector<SkPaint*> mPaints;
|
|
Vector<SkPath*> mPaths;
|
|
Vector<SkMatrix*> mMatrices;
|
|
Vector<SkiaShader*> mShaders;
|
|
|
|
mutable SkFlattenableReadBuffer mReader;
|
|
};
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// Renderer
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
/**
|
|
* Records drawing commands in a display list for latter playback.
|
|
*/
|
|
class DisplayListRenderer: public OpenGLRenderer {
|
|
public:
|
|
DisplayListRenderer();
|
|
~DisplayListRenderer();
|
|
|
|
DisplayList* getDisplayList();
|
|
|
|
void setViewport(int width, int height);
|
|
void prepareDirty(float left, float top, float right, float bottom, bool opaque);
|
|
void finish();
|
|
|
|
bool callDrawGLFunction(Functor *functor, Rect& dirty);
|
|
|
|
void interrupt();
|
|
void resume();
|
|
|
|
int save(int flags);
|
|
void restore();
|
|
void restoreToCount(int saveCount);
|
|
|
|
int saveLayer(float left, float top, float right, float bottom,
|
|
SkPaint* p, int flags);
|
|
int saveLayerAlpha(float left, float top, float right, float bottom,
|
|
int alpha, int flags);
|
|
|
|
void translate(float dx, float dy);
|
|
void rotate(float degrees);
|
|
void scale(float sx, float sy);
|
|
void skew(float sx, float sy);
|
|
|
|
void setMatrix(SkMatrix* matrix);
|
|
void concatMatrix(SkMatrix* matrix);
|
|
|
|
bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
|
|
|
|
bool drawDisplayList(DisplayList* displayList, uint32_t width, uint32_t height,
|
|
Rect& dirty, uint32_t level = 0);
|
|
void drawLayer(Layer* layer, float x, float y, SkPaint* paint);
|
|
void drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
|
|
void drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
|
|
void drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
|
|
float srcRight, float srcBottom, float dstLeft, float dstTop,
|
|
float dstRight, float dstBottom, SkPaint* paint);
|
|
void drawBitmapMesh(SkBitmap* bitmap, int meshWidth, int meshHeight,
|
|
float* vertices, int* colors, SkPaint* paint);
|
|
void 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);
|
|
void drawColor(int color, SkXfermode::Mode mode);
|
|
void drawRect(float left, float top, float right, float bottom, SkPaint* paint);
|
|
void drawRoundRect(float left, float top, float right, float bottom,
|
|
float rx, float ry, SkPaint* paint);
|
|
void drawCircle(float x, float y, float radius, SkPaint* paint);
|
|
void drawOval(float left, float top, float right, float bottom, SkPaint* paint);
|
|
void drawArc(float left, float top, float right, float bottom,
|
|
float startAngle, float sweepAngle, bool useCenter, SkPaint* paint);
|
|
void drawPath(SkPath* path, SkPaint* paint);
|
|
void drawLines(float* points, int count, SkPaint* paint);
|
|
void drawPoints(float* points, int count, SkPaint* paint);
|
|
void drawText(const char* text, int bytesCount, int count, float x, float y, SkPaint* paint);
|
|
|
|
void resetShader();
|
|
void setupShader(SkiaShader* shader);
|
|
|
|
void resetColorFilter();
|
|
void setupColorFilter(SkiaColorFilter* filter);
|
|
|
|
void resetShadow();
|
|
void setupShadow(float radius, float dx, float dy, int color);
|
|
|
|
void reset();
|
|
|
|
const SkWriter32& writeStream() const {
|
|
return mWriter;
|
|
}
|
|
|
|
const Vector<SkBitmap*>& getBitmapResources() const {
|
|
return mBitmapResources;
|
|
}
|
|
|
|
const Vector<SkiaShader*>& getShaders() const {
|
|
return mShaders;
|
|
}
|
|
|
|
const Vector<SkPaint*>& getPaints() const {
|
|
return mPaints;
|
|
}
|
|
|
|
const Vector<SkPath*>& getPaths() const {
|
|
return mPaths;
|
|
}
|
|
|
|
const Vector<SkMatrix*>& getMatrices() const {
|
|
return mMatrices;
|
|
}
|
|
|
|
const Vector<SkiaColorFilter*>& getFilterResources() const {
|
|
return mFilterResources;
|
|
}
|
|
|
|
private:
|
|
void insertRestoreToCount() {
|
|
if (mRestoreSaveCount >= 0) {
|
|
mWriter.writeInt(DisplayList::RestoreToCount);
|
|
addInt(mRestoreSaveCount);
|
|
mRestoreSaveCount = -1;
|
|
}
|
|
}
|
|
|
|
inline void addOp(DisplayList::Op drawOp) {
|
|
insertRestoreToCount();
|
|
mWriter.writeInt(drawOp);
|
|
}
|
|
|
|
inline void addInt(int value) {
|
|
mWriter.writeInt(value);
|
|
}
|
|
|
|
inline void addSize(uint32_t w, uint32_t h) {
|
|
mWriter.writeInt(w);
|
|
mWriter.writeInt(h);
|
|
}
|
|
|
|
void addInts(const int32_t* values, uint32_t count) {
|
|
mWriter.writeInt(count);
|
|
for (uint32_t i = 0; i < count; i++) {
|
|
mWriter.writeInt(values[i]);
|
|
}
|
|
}
|
|
|
|
void addUInts(const uint32_t* values, int8_t count) {
|
|
mWriter.writeInt(count);
|
|
for (int8_t i = 0; i < count; i++) {
|
|
mWriter.writeInt(values[i]);
|
|
}
|
|
}
|
|
|
|
inline void addFloat(float value) {
|
|
mWriter.writeScalar(value);
|
|
}
|
|
|
|
void addFloats(const float* values, int count) {
|
|
mWriter.writeInt(count);
|
|
for (int i = 0; i < count; i++) {
|
|
mWriter.writeScalar(values[i]);
|
|
}
|
|
}
|
|
|
|
inline void addPoint(float x, float y) {
|
|
mWriter.writeScalar(x);
|
|
mWriter.writeScalar(y);
|
|
}
|
|
|
|
inline void addBounds(float left, float top, float right, float bottom) {
|
|
mWriter.writeScalar(left);
|
|
mWriter.writeScalar(top);
|
|
mWriter.writeScalar(right);
|
|
mWriter.writeScalar(bottom);
|
|
}
|
|
|
|
inline void addText(const void* text, size_t byteLength) {
|
|
mWriter.writeInt(byteLength);
|
|
mWriter.writePad(text, byteLength);
|
|
}
|
|
|
|
inline void addPath(SkPath* path) {
|
|
if (!path) {
|
|
addInt((int) NULL);
|
|
return;
|
|
}
|
|
|
|
SkPath* pathCopy = mPathMap.valueFor(path);
|
|
if (pathCopy == NULL || pathCopy->getGenerationID() != path->getGenerationID()) {
|
|
pathCopy = new SkPath(*path);
|
|
mPathMap.add(path, pathCopy);
|
|
mPaths.add(pathCopy);
|
|
}
|
|
|
|
addInt((int) pathCopy);
|
|
}
|
|
|
|
inline void addPaint(SkPaint* paint) {
|
|
if (!paint) {
|
|
addInt((int) NULL);
|
|
return;
|
|
}
|
|
|
|
SkPaint* paintCopy = mPaintMap.valueFor(paint);
|
|
if (paintCopy == NULL || paintCopy->getGenerationID() != paint->getGenerationID()) {
|
|
paintCopy = new SkPaint(*paint);
|
|
mPaintMap.add(paint, paintCopy);
|
|
mPaints.add(paintCopy);
|
|
}
|
|
|
|
addInt((int) paintCopy);
|
|
}
|
|
|
|
inline void addDisplayList(DisplayList* displayList) {
|
|
// TODO: To be safe, the display list should be ref-counted in the
|
|
// resources cache, but we rely on the caller (UI toolkit) to
|
|
// do the right thing for now
|
|
addInt((int) displayList);
|
|
}
|
|
|
|
inline void addMatrix(SkMatrix* matrix) {
|
|
// Copying the matrix is cheap and prevents against the user changing the original
|
|
// matrix before the operation that uses it
|
|
addInt((int) new SkMatrix(*matrix));
|
|
}
|
|
|
|
inline void addBitmap(SkBitmap* bitmap) {
|
|
// Note that this assumes the bitmap is immutable. There are cases this won't handle
|
|
// correctly, such as creating the bitmap from scratch, drawing with it, changing its
|
|
// contents, and drawing again. The only fix would be to always copy it the first time,
|
|
// which doesn't seem worth the extra cycles for this unlikely case.
|
|
addInt((int) bitmap);
|
|
mBitmapResources.add(bitmap);
|
|
Caches& caches = Caches::getInstance();
|
|
caches.resourceCache.incrementRefcount(bitmap);
|
|
}
|
|
|
|
inline void addShader(SkiaShader* shader) {
|
|
if (!shader) {
|
|
addInt((int) NULL);
|
|
return;
|
|
}
|
|
|
|
SkiaShader* shaderCopy = mShaderMap.valueFor(shader);
|
|
// TODO: We also need to handle generation ID changes in compose shaders
|
|
if (shaderCopy == NULL || shaderCopy->getGenerationId() != shader->getGenerationId()) {
|
|
shaderCopy = shader->copy();
|
|
mShaderMap.add(shader, shaderCopy);
|
|
mShaders.add(shaderCopy);
|
|
Caches::getInstance().resourceCache.incrementRefcount(shaderCopy);
|
|
}
|
|
|
|
addInt((int) shaderCopy);
|
|
}
|
|
|
|
inline void addColorFilter(SkiaColorFilter* colorFilter) {
|
|
addInt((int) colorFilter);
|
|
mFilterResources.add(colorFilter);
|
|
Caches& caches = Caches::getInstance();
|
|
caches.resourceCache.incrementRefcount(colorFilter);
|
|
}
|
|
|
|
Vector<SkBitmap*> mBitmapResources;
|
|
Vector<SkiaColorFilter*> mFilterResources;
|
|
|
|
Vector<SkPaint*> mPaints;
|
|
DefaultKeyedVector<SkPaint*, SkPaint*> mPaintMap;
|
|
|
|
Vector<SkPath*> mPaths;
|
|
DefaultKeyedVector<SkPath*, SkPath*> mPathMap;
|
|
|
|
Vector<SkiaShader*> mShaders;
|
|
DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
|
|
|
|
Vector<SkMatrix*> mMatrices;
|
|
|
|
SkWriter32 mWriter;
|
|
|
|
DisplayList *mDisplayList;
|
|
|
|
int mRestoreSaveCount;
|
|
|
|
friend class DisplayList;
|
|
|
|
}; // class DisplayListRenderer
|
|
|
|
}; // namespace uirenderer
|
|
}; // namespace android
|
|
|
|
#endif // ANDROID_HWUI_DISPLAY_LIST_RENDERER_H
|