am ad82f20d: Merge "DisplayList draw operation reordering"
* commit 'ad82f20d2382396f5ac75fdf6f7db5c4da1c4c23': DisplayList draw operation reordering
This commit is contained in:
@@ -12,6 +12,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
|
||||
GammaFontRenderer.cpp \
|
||||
Caches.cpp \
|
||||
DisplayList.cpp \
|
||||
DeferredDisplayList.cpp \
|
||||
DisplayListLogBuffer.cpp \
|
||||
DisplayListRenderer.cpp \
|
||||
Dither.cpp \
|
||||
|
||||
@@ -74,6 +74,9 @@
|
||||
// Turn on to enable additional debugging in the font renderers
|
||||
#define DEBUG_FONT_RENDERER 0
|
||||
|
||||
// Turn on to log draw operation batching and deferral information
|
||||
#define DEBUG_DEFER 0
|
||||
|
||||
// Turn on to dump display list state
|
||||
#define DEBUG_DISPLAY_LIST 0
|
||||
|
||||
|
||||
176
libs/hwui/DeferredDisplayList.cpp
Normal file
176
libs/hwui/DeferredDisplayList.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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"
|
||||
#define ATRACE_TAG ATRACE_TAG_VIEW
|
||||
|
||||
#include <utils/Trace.h>
|
||||
|
||||
#include "Debug.h"
|
||||
#include "DisplayListOp.h"
|
||||
#include "OpenGLRenderer.h"
|
||||
|
||||
#if DEBUG_DEFER
|
||||
#define DEFER_LOGD(...) ALOGD(__VA_ARGS__)
|
||||
#else
|
||||
#define DEFER_LOGD(...)
|
||||
#endif
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
class DrawOpBatch {
|
||||
public:
|
||||
DrawOpBatch() {
|
||||
mOps.clear();
|
||||
}
|
||||
|
||||
~DrawOpBatch() {
|
||||
mOps.clear();
|
||||
}
|
||||
|
||||
void add(DrawOp* op) {
|
||||
// NOTE: ignore empty bounds special case, since we don't merge across those ops
|
||||
mBounds.unionWith(op->state.mBounds);
|
||||
mOps.add(op);
|
||||
}
|
||||
|
||||
bool intersects(Rect& rect) {
|
||||
if (!rect.intersects(mBounds)) return false;
|
||||
for (unsigned int i = 0; i < mOps.size(); i++) {
|
||||
if (rect.intersects(mOps[i]->state.mBounds)) {
|
||||
#if DEBUG_DEFER
|
||||
DEFER_LOGD("op intersects with op %p with bounds %f %f %f %f:", mOps[i],
|
||||
mOps[i]->state.mBounds.left, mOps[i]->state.mBounds.top,
|
||||
mOps[i]->state.mBounds.right, mOps[i]->state.mBounds.bottom);
|
||||
mOps[i]->output(2);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Vector<DrawOp*> mOps;
|
||||
private:
|
||||
Rect mBounds;
|
||||
};
|
||||
|
||||
void DeferredDisplayList::clear() {
|
||||
for (int i = 0; i < kOpBatch_Count; i++) {
|
||||
mBatchIndices[i] = -1;
|
||||
}
|
||||
for (unsigned int i = 0; i < mBatches.size(); i++) {
|
||||
delete mBatches[i];
|
||||
}
|
||||
mBatches.clear();
|
||||
}
|
||||
|
||||
void DeferredDisplayList::add(DrawOp* op, bool disallowReorder) {
|
||||
if (CC_UNLIKELY(disallowReorder)) {
|
||||
if (!mBatches.isEmpty()) {
|
||||
mBatches[0]->add(op);
|
||||
return;
|
||||
}
|
||||
DrawOpBatch* b = new DrawOpBatch();
|
||||
b->add(op);
|
||||
mBatches.add(b);
|
||||
return;
|
||||
}
|
||||
|
||||
// disallowReorder isn't set, so find the latest batch of the new op's type, and try to merge
|
||||
// the new op into it
|
||||
DrawOpBatch* targetBatch = NULL;
|
||||
int batchId = op->getBatchId();
|
||||
|
||||
if (!mBatches.isEmpty()) {
|
||||
if (op->state.mBounds.isEmpty()) {
|
||||
// don't know the bounds for op, so add to last batch and start from scratch on next op
|
||||
mBatches.top()->add(op);
|
||||
for (int i = 0; i < kOpBatch_Count; i++) {
|
||||
mBatchIndices[i] = -1;
|
||||
}
|
||||
#if DEBUG_DEFER
|
||||
DEFER_LOGD("Warning: Encountered op with empty bounds, resetting batches");
|
||||
op->output(2);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (batchId >= 0 && mBatchIndices[batchId] != -1) {
|
||||
int targetIndex = mBatchIndices[batchId];
|
||||
targetBatch = mBatches[targetIndex];
|
||||
// iterate back toward target to see if anything drawn since should overlap the new op
|
||||
for (int i = mBatches.size() - 1; i > targetIndex; i--) {
|
||||
DrawOpBatch* overBatch = mBatches[i];
|
||||
if (overBatch->intersects(op->state.mBounds)) {
|
||||
targetBatch = NULL;
|
||||
#if DEBUG_DEFER
|
||||
DEFER_LOGD("op couldn't join batch %d, was intersected by batch %d",
|
||||
targetIndex, i);
|
||||
op->output(2);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!targetBatch) {
|
||||
targetBatch = new DrawOpBatch();
|
||||
mBatches.add(targetBatch);
|
||||
if (batchId >= 0) {
|
||||
mBatchIndices[batchId] = mBatches.size() - 1;
|
||||
}
|
||||
}
|
||||
targetBatch->add(op);
|
||||
}
|
||||
|
||||
status_t DeferredDisplayList::flush(OpenGLRenderer& renderer, Rect& dirty, int32_t flags,
|
||||
uint32_t level) {
|
||||
ATRACE_CALL();
|
||||
status_t status = DrawGlInfo::kStatusDone;
|
||||
|
||||
if (isEmpty()) return status; // nothing to flush
|
||||
|
||||
DEFER_LOGD("--flushing");
|
||||
DrawModifiers restoreDrawModifiers = renderer.getDrawModifiers();
|
||||
int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
|
||||
int opCount = 0;
|
||||
for (unsigned int i = 0; i < mBatches.size(); i++) {
|
||||
DrawOpBatch* batch = mBatches[i];
|
||||
for (unsigned int j = 0; j < batch->mOps.size(); j++) {
|
||||
DrawOp* op = batch->mOps[j];
|
||||
|
||||
renderer.restoreDisplayState(op->state);
|
||||
|
||||
#if DEBUG_DEFER
|
||||
op->output(2);
|
||||
#endif
|
||||
status |= op->applyDraw(renderer, dirty, level,
|
||||
op->state.mMultipliedAlpha >= 0, op->state.mMultipliedAlpha);
|
||||
opCount++;
|
||||
}
|
||||
}
|
||||
|
||||
DEFER_LOGD("--flushed, drew %d batches (total %d ops)", mBatches.size(), opCount);
|
||||
renderer.restoreToCount(restoreTo);
|
||||
renderer.setDrawModifiers(restoreDrawModifiers);
|
||||
clear();
|
||||
return status;
|
||||
}
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
78
libs/hwui/DeferredDisplayList.h
Normal file
78
libs/hwui/DeferredDisplayList.h
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (C) 2013 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_DEFERRED_DISPLAY_LIST_H
|
||||
#define ANDROID_HWUI_DEFERRED_DISPLAY_LIST_H
|
||||
|
||||
#include <utils/Errors.h>
|
||||
#include <utils/Vector.h>
|
||||
|
||||
#include "Matrix.h"
|
||||
#include "Rect.h"
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
class DrawOp;
|
||||
class DrawOpBatch;
|
||||
class OpenGLRenderer;
|
||||
class SkiaShader;
|
||||
|
||||
class DeferredDisplayList {
|
||||
public:
|
||||
DeferredDisplayList() { clear(); }
|
||||
~DeferredDisplayList() { clear(); }
|
||||
|
||||
enum OpBatchId {
|
||||
kOpBatch_None = -1, // Don't batch
|
||||
kOpBatch_Bitmap,
|
||||
kOpBatch_Patch,
|
||||
kOpBatch_AlphaVertices,
|
||||
kOpBatch_Vertices,
|
||||
kOpBatch_AlphaMaskTexture,
|
||||
kOpBatch_Text,
|
||||
kOpBatch_ColorText,
|
||||
|
||||
kOpBatch_Count, // Add other batch ids before this
|
||||
};
|
||||
|
||||
bool isEmpty() { return mBatches.isEmpty(); }
|
||||
|
||||
/**
|
||||
* Plays back all of the draw ops recorded into batches to the renderer.
|
||||
* Adjusts the state of the renderer as necessary, and restores it when complete
|
||||
*/
|
||||
status_t flush(OpenGLRenderer& renderer, Rect& dirty, int32_t flags,
|
||||
uint32_t level);
|
||||
|
||||
/**
|
||||
* Add a draw op into the DeferredDisplayList, reordering as needed (for performance) if
|
||||
* disallowReorder is false, respecting draw order when overlaps occur
|
||||
*/
|
||||
void add(DrawOp* op, bool disallowReorder);
|
||||
|
||||
private:
|
||||
void clear();
|
||||
|
||||
|
||||
Vector<DrawOpBatch*> mBatches;
|
||||
int mBatchIndices[kOpBatch_Count];
|
||||
};
|
||||
|
||||
}; // namespace uirenderer
|
||||
}; // namespace android
|
||||
|
||||
#endif // ANDROID_HWUI_DEFERRED_DISPLAY_LIST_H
|
||||
@@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "Debug.h"
|
||||
#include "DisplayList.h"
|
||||
#include "DisplayListOp.h"
|
||||
#include "DisplayListLogBuffer.h"
|
||||
@@ -386,7 +387,8 @@ void DisplayList::setViewProperties(OpenGLRenderer& renderer, uint32_t level) {
|
||||
}
|
||||
}
|
||||
|
||||
status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level) {
|
||||
status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level,
|
||||
DeferredDisplayList* deferredList) {
|
||||
status_t drawGlStatus = DrawGlInfo::kStatusDone;
|
||||
|
||||
#if DEBUG_DISPLAY_LIST
|
||||
@@ -401,6 +403,12 @@ status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flag
|
||||
int restoreTo = renderer.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
|
||||
DISPLAY_LIST_LOGD("%*sSave %d %d", level * 2, "",
|
||||
SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag, restoreTo);
|
||||
|
||||
if (mAlpha < 1 && !mCaching && CC_LIKELY(deferredList)) {
|
||||
// flush before a saveLayerAlpha/setAlpha
|
||||
// TODO: make this cleaner
|
||||
drawGlStatus |= deferredList->flush(renderer, dirty, flags, level);
|
||||
}
|
||||
setViewProperties(renderer, level);
|
||||
|
||||
if (renderer.quickRejectNoScissor(0, 0, mWidth, mHeight)) {
|
||||
@@ -418,8 +426,13 @@ status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flag
|
||||
Caches::getInstance().eventMark(strlen(op->name()), op->name());
|
||||
#endif
|
||||
|
||||
drawGlStatus |= op->replay(renderer, dirty, flags,
|
||||
saveCount, level, mCaching, mMultipliedAlpha);
|
||||
if (deferredList) {
|
||||
drawGlStatus |= op->replay(renderer, dirty, flags,
|
||||
saveCount, level, mCaching, mMultipliedAlpha, *deferredList);
|
||||
} else {
|
||||
drawGlStatus |= op->replay(renderer, dirty, flags,
|
||||
saveCount, level, mCaching, mMultipliedAlpha);
|
||||
}
|
||||
logBuffer.writeCommand(level, op->name());
|
||||
}
|
||||
|
||||
@@ -429,6 +442,11 @@ status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flag
|
||||
|
||||
DISPLAY_LIST_LOGD("%*sDone (%p, %s), returning %d", (level + 1) * 2, "", this, mName.string(),
|
||||
drawGlStatus);
|
||||
|
||||
if (!level && CC_LIKELY(deferredList)) {
|
||||
drawGlStatus |= deferredList->flush(renderer, dirty, flags, level);
|
||||
}
|
||||
|
||||
return drawGlStatus;
|
||||
}
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ class SkRegion;
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
class DeferredDisplayList;
|
||||
class DisplayListOp;
|
||||
class DisplayListRenderer;
|
||||
class OpenGLRenderer;
|
||||
@@ -83,7 +84,8 @@ public:
|
||||
|
||||
void initFromDisplayListRenderer(const DisplayListRenderer& recorder, bool reusing = false);
|
||||
|
||||
status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level = 0);
|
||||
status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, uint32_t level = 0,
|
||||
DeferredDisplayList* deferredList = NULL);
|
||||
|
||||
void output(uint32_t level = 0);
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <private/hwui/DrawGlInfo.h>
|
||||
|
||||
#include "OpenGLRenderer.h"
|
||||
#include "DeferredDisplayList.h"
|
||||
#include "DisplayListRenderer.h"
|
||||
#include "utils/LinearAllocator.h"
|
||||
|
||||
@@ -43,7 +44,6 @@
|
||||
#define OP_LOGS(s) OP_LOG("%s", s)
|
||||
#define OP_LOG(s, ...) ALOGD( "%*s" s, level * 2, "", __VA_ARGS__ )
|
||||
|
||||
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
@@ -74,11 +74,15 @@ public:
|
||||
kOpLogFlag_JSON = 0x2 // TODO: add?
|
||||
};
|
||||
|
||||
//TODO: for draw batching, DrawOps should override a virtual sub-method, with
|
||||
// DrawOps::apply deferring operations to a different list if possible
|
||||
virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
|
||||
uint32_t level, bool caching, int multipliedAlpha) = 0;
|
||||
|
||||
// same as replay above, but draw operations will defer into the deferredList if possible
|
||||
// NOTE: colorfilters, paintfilters, shaders, shadow, and complex clips prevent deferral
|
||||
virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
|
||||
uint32_t level, bool caching, int multipliedAlpha,
|
||||
DeferredDisplayList& deferredList) = 0;
|
||||
|
||||
virtual void output(int level, uint32_t flags = 0) = 0;
|
||||
|
||||
// NOTE: it would be nice to declare constants and overriding the implementation in each op to
|
||||
@@ -98,7 +102,28 @@ public:
|
||||
return DrawGlInfo::kStatusDone;
|
||||
}
|
||||
|
||||
/**
|
||||
* State operations are applied directly to the renderer, but can cause the deferred drawing op
|
||||
* list to flush
|
||||
*/
|
||||
virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
|
||||
uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList& deferredList) {
|
||||
status_t status = DrawGlInfo::kStatusDone;
|
||||
if (requiresDrawOpFlush()) {
|
||||
// will be setting renderer state that affects ops in deferredList, so flush list first
|
||||
status |= deferredList.flush(renderer, dirty, flags, level);
|
||||
}
|
||||
applyState(renderer, saveCount);
|
||||
return status;
|
||||
}
|
||||
|
||||
virtual void applyState(OpenGLRenderer& renderer, int saveCount) = 0;
|
||||
|
||||
/**
|
||||
* Returns true if it affects renderer drawing state in such a way to break deferral
|
||||
* see OpenGLRenderer::disallowDeferral()
|
||||
*/
|
||||
virtual bool requiresDrawOpFlush() { return false; }
|
||||
};
|
||||
|
||||
class DrawOp : public DisplayListOp {
|
||||
@@ -115,6 +140,33 @@ public:
|
||||
return applyDraw(renderer, dirty, level, caching, multipliedAlpha);
|
||||
}
|
||||
|
||||
/** Draw operations are stored in the deferredList with information necessary for playback */
|
||||
virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
|
||||
uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList& deferredList) {
|
||||
if (mQuickRejected && CC_LIKELY(flags & DisplayList::kReplayFlag_ClipChildren)) {
|
||||
return DrawGlInfo::kStatusDone;
|
||||
}
|
||||
|
||||
if (renderer.disallowDeferral()) {
|
||||
// dispatch draw immediately, since the renderer's state is too complex for deferral
|
||||
return applyDraw(renderer, dirty, level, caching, multipliedAlpha);
|
||||
}
|
||||
|
||||
if (!caching) multipliedAlpha = -1;
|
||||
state.mMultipliedAlpha = multipliedAlpha;
|
||||
if (!getLocalBounds(state.mBounds)) {
|
||||
// empty bounds signify bounds can't be calculated
|
||||
state.mBounds.setEmpty();
|
||||
}
|
||||
|
||||
if (!renderer.storeDisplayState(state)) {
|
||||
// op wasn't quick-rejected, so defer
|
||||
deferredList.add(this, renderer.disallowReorder());
|
||||
}
|
||||
|
||||
return DrawGlInfo::kStatusDone;
|
||||
}
|
||||
|
||||
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
|
||||
bool caching, int multipliedAlpha) = 0;
|
||||
|
||||
@@ -125,6 +177,19 @@ public:
|
||||
void setQuickRejected(bool quickRejected) { mQuickRejected = quickRejected; }
|
||||
bool getQuickRejected() { return mQuickRejected; }
|
||||
|
||||
/** Batching disabled by default, turned on for individual ops */
|
||||
virtual DeferredDisplayList::OpBatchId getBatchId() {
|
||||
return DeferredDisplayList::kOpBatch_None;
|
||||
}
|
||||
|
||||
float strokeWidthOutset() { return mPaint->getStrokeWidth() * 0.5f; }
|
||||
|
||||
public:
|
||||
/**
|
||||
* Stores the relevant canvas state of the object between deferral and replay (if the canvas
|
||||
* state supports being stored) See OpenGLRenderer::simpleClipAndState()
|
||||
*/
|
||||
DeferredDisplayState state;
|
||||
protected:
|
||||
SkPaint* getPaint(OpenGLRenderer& renderer) {
|
||||
return renderer.filterPaint(mPaint);
|
||||
@@ -191,6 +256,8 @@ public:
|
||||
}
|
||||
|
||||
virtual const char* name() { return "RestoreToCount"; }
|
||||
// Note: don't have to return true for requiresDrawOpFlush - even though restore can create a
|
||||
// complex clip, the clip and matrix are overridden by DeferredDisplayList::flush()
|
||||
|
||||
private:
|
||||
int mCount;
|
||||
@@ -211,6 +278,7 @@ public:
|
||||
}
|
||||
|
||||
virtual const char* name() { return "SaveLayer"; }
|
||||
virtual bool requiresDrawOpFlush() { return true; }
|
||||
|
||||
private:
|
||||
Rect mArea;
|
||||
@@ -232,6 +300,8 @@ public:
|
||||
}
|
||||
|
||||
virtual const char* name() { return "SaveLayerAlpha"; }
|
||||
virtual bool requiresDrawOpFlush() { return true; }
|
||||
|
||||
private:
|
||||
Rect mArea;
|
||||
int mAlpha;
|
||||
@@ -391,6 +461,7 @@ public:
|
||||
}
|
||||
|
||||
virtual const char* name() { return "ClipPath"; }
|
||||
virtual bool requiresDrawOpFlush() { return true; }
|
||||
|
||||
private:
|
||||
SkPath* mPath;
|
||||
@@ -413,6 +484,7 @@ public:
|
||||
}
|
||||
|
||||
virtual const char* name() { return "ClipRegion"; }
|
||||
virtual bool requiresDrawOpFlush() { return true; }
|
||||
|
||||
private:
|
||||
SkRegion* mRegion;
|
||||
@@ -582,6 +654,9 @@ public:
|
||||
}
|
||||
|
||||
virtual const char* name() { return "DrawBitmap"; }
|
||||
virtual DeferredDisplayList::OpBatchId getBatchId() {
|
||||
return DeferredDisplayList::kOpBatch_Bitmap;
|
||||
}
|
||||
|
||||
protected:
|
||||
SkBitmap* mBitmap;
|
||||
@@ -606,6 +681,9 @@ public:
|
||||
}
|
||||
|
||||
virtual const char* name() { return "DrawBitmap"; }
|
||||
virtual DeferredDisplayList::OpBatchId getBatchId() {
|
||||
return DeferredDisplayList::kOpBatch_Bitmap;
|
||||
}
|
||||
|
||||
private:
|
||||
SkBitmap* mBitmap;
|
||||
@@ -632,6 +710,9 @@ public:
|
||||
}
|
||||
|
||||
virtual const char* name() { return "DrawBitmapRect"; }
|
||||
virtual DeferredDisplayList::OpBatchId getBatchId() {
|
||||
return DeferredDisplayList::kOpBatch_Bitmap;
|
||||
}
|
||||
|
||||
private:
|
||||
SkBitmap* mBitmap;
|
||||
@@ -654,6 +735,9 @@ public:
|
||||
}
|
||||
|
||||
virtual const char* name() { return "DrawBitmapData"; }
|
||||
virtual DeferredDisplayList::OpBatchId getBatchId() {
|
||||
return DeferredDisplayList::kOpBatch_Bitmap;
|
||||
}
|
||||
};
|
||||
|
||||
class DrawBitmapMeshOp : public DrawOp {
|
||||
@@ -674,6 +758,9 @@ public:
|
||||
}
|
||||
|
||||
virtual const char* name() { return "DrawBitmapMesh"; }
|
||||
virtual DeferredDisplayList::OpBatchId getBatchId() {
|
||||
return DeferredDisplayList::kOpBatch_Bitmap;
|
||||
}
|
||||
|
||||
private:
|
||||
SkBitmap* mBitmap;
|
||||
@@ -708,6 +795,9 @@ public:
|
||||
}
|
||||
|
||||
virtual const char* name() { return "DrawPatch"; }
|
||||
virtual DeferredDisplayList::OpBatchId getBatchId() {
|
||||
return DeferredDisplayList::kOpBatch_Patch;
|
||||
}
|
||||
|
||||
private:
|
||||
SkBitmap* mBitmap;
|
||||
@@ -748,15 +838,21 @@ public:
|
||||
: DrawBoundedOp(left, top, right, bottom, paint) {};
|
||||
|
||||
bool getLocalBounds(Rect& localBounds) {
|
||||
localBounds.set(mLocalBounds);
|
||||
if (mPaint && mPaint->getStyle() != SkPaint::kFill_Style) {
|
||||
float outset = mPaint->getStrokeWidth() * 0.5f;
|
||||
localBounds.set(mLocalBounds.left - outset, mLocalBounds.top - outset,
|
||||
mLocalBounds.right + outset, mLocalBounds.bottom + outset);
|
||||
} else {
|
||||
localBounds.set(mLocalBounds);
|
||||
localBounds.outset(strokeWidthOutset());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual DeferredDisplayList::OpBatchId getBatchId() {
|
||||
if (mPaint->getPathEffect()) {
|
||||
return DeferredDisplayList::kOpBatch_AlphaMaskTexture;
|
||||
}
|
||||
return mPaint->isAntiAlias() ?
|
||||
DeferredDisplayList::kOpBatch_AlphaVertices :
|
||||
DeferredDisplayList::kOpBatch_Vertices;
|
||||
}
|
||||
};
|
||||
|
||||
class DrawRectOp : public DrawStrokableOp {
|
||||
@@ -793,6 +889,10 @@ public:
|
||||
|
||||
virtual const char* name() { return "DrawRects"; }
|
||||
|
||||
virtual DeferredDisplayList::OpBatchId getBatchId() {
|
||||
return DeferredDisplayList::kOpBatch_Vertices;
|
||||
}
|
||||
|
||||
private:
|
||||
const float* mRects;
|
||||
int mCount;
|
||||
@@ -912,22 +1012,24 @@ public:
|
||||
|
||||
virtual const char* name() { return "DrawPath"; }
|
||||
|
||||
virtual DeferredDisplayList::OpBatchId getBatchId() {
|
||||
return DeferredDisplayList::kOpBatch_AlphaMaskTexture;
|
||||
}
|
||||
private:
|
||||
SkPath* mPath;
|
||||
};
|
||||
|
||||
class DrawLinesOp : public DrawOp {
|
||||
class DrawLinesOp : public DrawBoundedOp {
|
||||
public:
|
||||
DrawLinesOp(float* points, int count, SkPaint* paint)
|
||||
: DrawOp(paint), mPoints(points), mCount(count) {
|
||||
/* TODO: inherit from DrawBoundedOp and calculate localbounds something like:
|
||||
: DrawBoundedOp(paint), mPoints(points), mCount(count) {
|
||||
for (int i = 0; i < count; i += 2) {
|
||||
mLocalBounds.left = fminf(mLocalBounds.left, points[i]);
|
||||
mLocalBounds.right = fmaxf(mLocalBounds.right, points[i]);
|
||||
mLocalBounds.top = fminf(mLocalBounds.top, points[i+1]);
|
||||
mLocalBounds.bottom = fmaxf(mLocalBounds.bottom, points[i+1]);
|
||||
}
|
||||
*/
|
||||
mLocalBounds.outset(strokeWidthOutset());
|
||||
}
|
||||
|
||||
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
|
||||
@@ -941,6 +1043,12 @@ public:
|
||||
|
||||
virtual const char* name() { return "DrawLines"; }
|
||||
|
||||
virtual DeferredDisplayList::OpBatchId getBatchId() {
|
||||
return mPaint->isAntiAlias() ?
|
||||
DeferredDisplayList::kOpBatch_AlphaVertices :
|
||||
DeferredDisplayList::kOpBatch_Vertices;
|
||||
}
|
||||
|
||||
protected:
|
||||
float* mPoints;
|
||||
int mCount;
|
||||
@@ -971,6 +1079,12 @@ public:
|
||||
virtual void output(int level, uint32_t flags) {
|
||||
OP_LOG("Draw some text, %d bytes", mBytesCount);
|
||||
}
|
||||
|
||||
virtual DeferredDisplayList::OpBatchId getBatchId() {
|
||||
return mPaint->getColor() == 0xff000000 ?
|
||||
DeferredDisplayList::kOpBatch_Text :
|
||||
DeferredDisplayList::kOpBatch_ColorText;
|
||||
}
|
||||
protected:
|
||||
const char* mText;
|
||||
int mBytesCount;
|
||||
@@ -1042,6 +1156,12 @@ public:
|
||||
|
||||
virtual const char* name() { return "DrawText"; }
|
||||
|
||||
virtual DeferredDisplayList::OpBatchId getBatchId() {
|
||||
return mPaint->getColor() == 0xff000000 ?
|
||||
DeferredDisplayList::kOpBatch_Text :
|
||||
DeferredDisplayList::kOpBatch_ColorText;
|
||||
}
|
||||
|
||||
private:
|
||||
const char* mText;
|
||||
int mBytesCount;
|
||||
@@ -1083,9 +1203,21 @@ class DrawDisplayListOp : public DrawOp {
|
||||
public:
|
||||
DrawDisplayListOp(DisplayList* displayList, int flags)
|
||||
: DrawOp(0), mDisplayList(displayList), mFlags(flags) {}
|
||||
|
||||
virtual status_t replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flags, int saveCount,
|
||||
uint32_t level, bool caching, int multipliedAlpha, DeferredDisplayList& deferredList) {
|
||||
if (mDisplayList && mDisplayList->isRenderable()) {
|
||||
return mDisplayList->replay(renderer, dirty, mFlags, level + 1, &deferredList);
|
||||
}
|
||||
return DrawGlInfo::kStatusDone;
|
||||
}
|
||||
|
||||
virtual status_t applyDraw(OpenGLRenderer& renderer, Rect& dirty, uint32_t level,
|
||||
bool caching, int multipliedAlpha) {
|
||||
return renderer.drawDisplayList(mDisplayList, dirty, mFlags, level + 1);
|
||||
if (mDisplayList && mDisplayList->isRenderable()) {
|
||||
return mDisplayList->replay(renderer, dirty, mFlags, level + 1);
|
||||
}
|
||||
return DrawGlInfo::kStatusDone;
|
||||
}
|
||||
|
||||
virtual void output(int level, uint32_t flags) {
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
#include <private/hwui/DrawGlInfo.h>
|
||||
|
||||
#include "DisplayList.h"
|
||||
#include "DeferredDisplayList.h"
|
||||
#include "DisplayListLogBuffer.h"
|
||||
#include "DisplayListOp.h"
|
||||
#include "DisplayListRenderer.h"
|
||||
@@ -239,7 +240,7 @@ bool DisplayListRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
|
||||
}
|
||||
|
||||
status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
|
||||
Rect& dirty, int32_t flags, uint32_t level) {
|
||||
Rect& dirty, int32_t flags) {
|
||||
// dirty is an out parameter and should not be recorded,
|
||||
// it matters only when replaying the display list
|
||||
|
||||
|
||||
@@ -47,15 +47,12 @@ namespace uirenderer {
|
||||
// Display list
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class DeferredDisplayList;
|
||||
class DisplayListRenderer;
|
||||
class DisplayListOp;
|
||||
class DrawOp;
|
||||
class StateOp;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Renderer
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Records drawing commands in a display list for latter playback.
|
||||
*/
|
||||
@@ -98,8 +95,7 @@ public:
|
||||
virtual bool clipPath(SkPath* path, SkRegion::Op op);
|
||||
virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
|
||||
|
||||
virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags,
|
||||
uint32_t level = 0);
|
||||
virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags);
|
||||
virtual status_t drawLayer(Layer* layer, float x, float y, SkPaint* paint);
|
||||
virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
|
||||
virtual status_t drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <ui/Rect.h>
|
||||
|
||||
#include "OpenGLRenderer.h"
|
||||
#include "DeferredDisplayList.h"
|
||||
#include "DisplayListRenderer.h"
|
||||
#include "PathTessellator.h"
|
||||
#include "Properties.h"
|
||||
@@ -111,16 +112,18 @@ static const Blender gBlendsSwap[] = {
|
||||
|
||||
OpenGLRenderer::OpenGLRenderer():
|
||||
mCaches(Caches::getInstance()), mExtensions(Extensions::getInstance()) {
|
||||
mShader = NULL;
|
||||
mColorFilter = NULL;
|
||||
mHasShadow = false;
|
||||
mHasDrawFilter = false;
|
||||
mDrawModifiers.mShader = NULL;
|
||||
mDrawModifiers.mColorFilter = NULL;
|
||||
mDrawModifiers.mHasShadow = false;
|
||||
mDrawModifiers.mHasDrawFilter = false;
|
||||
|
||||
memcpy(mMeshVertices, gMeshVertices, sizeof(gMeshVertices));
|
||||
|
||||
mFirstSnapshot = new Snapshot;
|
||||
|
||||
mScissorOptimizationDisabled = false;
|
||||
mDrawDeferDisabled = false;
|
||||
mDrawReorderDisabled = false;
|
||||
}
|
||||
|
||||
OpenGLRenderer::~OpenGLRenderer() {
|
||||
@@ -137,6 +140,20 @@ void OpenGLRenderer::initProperties() {
|
||||
} else {
|
||||
INIT_LOGD(" Scissor optimization enabled");
|
||||
}
|
||||
|
||||
if (property_get(PROPERTY_DISABLE_DRAW_DEFER, property, "false")) {
|
||||
mDrawDeferDisabled = !strcasecmp(property, "true");
|
||||
INIT_LOGD(" Draw defer %s", mDrawDeferDisabled ? "disabled" : "enabled");
|
||||
} else {
|
||||
INIT_LOGD(" Draw defer enabled");
|
||||
}
|
||||
|
||||
if (property_get(PROPERTY_DISABLE_DRAW_REORDER, property, "false")) {
|
||||
mDrawReorderDisabled = !strcasecmp(property, "true");
|
||||
INIT_LOGD(" Draw reorder %s", mDrawReorderDisabled ? "disabled" : "enabled");
|
||||
} else {
|
||||
INIT_LOGD(" Draw reorder enabled");
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -770,7 +787,7 @@ bool OpenGLRenderer::createLayer(float left, float top, float right, float botto
|
||||
layer->layer.set(bounds);
|
||||
layer->texCoords.set(0.0f, bounds.getHeight() / float(layer->getHeight()),
|
||||
bounds.getWidth() / float(layer->getWidth()), 0.0f);
|
||||
layer->setColorFilter(mColorFilter);
|
||||
layer->setColorFilter(mDrawModifiers.mColorFilter);
|
||||
layer->setBlend(true);
|
||||
layer->setDirty(false);
|
||||
|
||||
@@ -1203,6 +1220,40 @@ void OpenGLRenderer::clearLayerRegions() {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// State Deferral
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool OpenGLRenderer::storeDisplayState(DeferredDisplayState& state) {
|
||||
const Rect& currentClip = *(mSnapshot->clipRect);
|
||||
const mat4& currentMatrix = *(mSnapshot->transform);
|
||||
|
||||
// state only has bounds initialized in local coordinates
|
||||
if (!state.mBounds.isEmpty()) {
|
||||
currentMatrix.mapRect(state.mBounds);
|
||||
if (!state.mBounds.intersect(currentClip)) {
|
||||
// quick rejected
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
state.mClip.set(currentClip);
|
||||
state.mMatrix.load(currentMatrix);
|
||||
state.mDrawModifiers = mDrawModifiers;
|
||||
return false;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::restoreDisplayState(const DeferredDisplayState& state) {
|
||||
mSnapshot->transform->load(state.mMatrix);
|
||||
|
||||
// NOTE: a clip RECT will be saved and restored, but DeferredDisplayState doesn't support
|
||||
// complex clips. In the future, we should add support for deferral of operations clipped by
|
||||
// these. for now, we don't defer with complex clips (see OpenGLRenderer::disallowDeferral())
|
||||
mSnapshot->setClip(state.mClip.left, state.mClip.top, state.mClip.right, state.mClip.bottom);
|
||||
dirtyClip();
|
||||
mDrawModifiers = state.mDrawModifiers;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Transforms
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -1452,7 +1503,7 @@ void OpenGLRenderer::setupDraw(bool clear) {
|
||||
if (clear) clearLayerRegions();
|
||||
// Make sure setScissor & setStencil happen at the beginning of
|
||||
// this method
|
||||
if (mDirtyClip) {
|
||||
if (mDirtyClip && mCaches.scissorEnabled) {
|
||||
setScissorFromClip();
|
||||
setStencilFromClip();
|
||||
}
|
||||
@@ -1524,14 +1575,14 @@ void OpenGLRenderer::setupDrawColor(float r, float g, float b, float a) {
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupDrawShader() {
|
||||
if (mShader) {
|
||||
mShader->describe(mDescription, mExtensions);
|
||||
if (mDrawModifiers.mShader) {
|
||||
mDrawModifiers.mShader->describe(mDescription, mExtensions);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupDrawColorFilter() {
|
||||
if (mColorFilter) {
|
||||
mColorFilter->describe(mDescription, mExtensions);
|
||||
if (mDrawModifiers.mColorFilter) {
|
||||
mDrawModifiers.mColorFilter->describe(mDescription, mExtensions);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1547,16 +1598,19 @@ void OpenGLRenderer::setupDrawBlending(SkXfermode::Mode mode, bool swapSrcDst) {
|
||||
// When the blending mode is kClear_Mode, we need to use a modulate color
|
||||
// argb=1,0,0,0
|
||||
accountForClear(mode);
|
||||
chooseBlending((mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()), mode,
|
||||
mDescription, swapSrcDst);
|
||||
bool blend = (mColorSet && mColorA < 1.0f) ||
|
||||
(mDrawModifiers.mShader && mDrawModifiers.mShader->blend());
|
||||
chooseBlending(blend, mode, mDescription, swapSrcDst);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupDrawBlending(bool blend, SkXfermode::Mode mode, bool swapSrcDst) {
|
||||
// When the blending mode is kClear_Mode, we need to use a modulate color
|
||||
// argb=1,0,0,0
|
||||
accountForClear(mode);
|
||||
chooseBlending(blend || (mColorSet && mColorA < 1.0f) || (mShader && mShader->blend()) ||
|
||||
(mColorFilter && mColorFilter->blend()), mode, mDescription, swapSrcDst);
|
||||
blend |= (mColorSet && mColorA < 1.0f) ||
|
||||
(mDrawModifiers.mShader && mDrawModifiers.mShader->blend()) ||
|
||||
(mDrawModifiers.mColorFilter && mDrawModifiers.mColorFilter->blend());
|
||||
chooseBlending(blend, mode, mDescription, swapSrcDst);
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupDrawProgram() {
|
||||
@@ -1609,7 +1663,7 @@ void OpenGLRenderer::setupDrawPointUniforms() {
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupDrawColorUniforms() {
|
||||
if ((mColorSet && !mShader) || (mShader && mSetShaderColor)) {
|
||||
if ((mColorSet && !mDrawModifiers.mShader) || (mDrawModifiers.mShader && mSetShaderColor)) {
|
||||
mCaches.currentProgram->setColor(mColorR, mColorG, mColorB, mColorA);
|
||||
}
|
||||
}
|
||||
@@ -1621,23 +1675,25 @@ void OpenGLRenderer::setupDrawPureColorUniforms() {
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupDrawShaderUniforms(bool ignoreTransform) {
|
||||
if (mShader) {
|
||||
if (mDrawModifiers.mShader) {
|
||||
if (ignoreTransform) {
|
||||
mModelView.loadInverse(*mSnapshot->transform);
|
||||
}
|
||||
mShader->setupProgram(mCaches.currentProgram, mModelView, *mSnapshot, &mTextureUnit);
|
||||
mDrawModifiers.mShader->setupProgram(mCaches.currentProgram,
|
||||
mModelView, *mSnapshot, &mTextureUnit);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupDrawShaderIdentityUniforms() {
|
||||
if (mShader) {
|
||||
mShader->setupProgram(mCaches.currentProgram, mIdentity, *mSnapshot, &mTextureUnit);
|
||||
if (mDrawModifiers.mShader) {
|
||||
mDrawModifiers.mShader->setupProgram(mCaches.currentProgram,
|
||||
mIdentity, *mSnapshot, &mTextureUnit);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupDrawColorFilterUniforms() {
|
||||
if (mColorFilter) {
|
||||
mColorFilter->setupProgram(mCaches.currentProgram);
|
||||
if (mDrawModifiers.mColorFilter) {
|
||||
mDrawModifiers.mColorFilter->setupProgram(mCaches.currentProgram);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1726,21 +1782,24 @@ void OpenGLRenderer::finishDrawTexture() {
|
||||
// Drawing
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
status_t OpenGLRenderer::drawDisplayList(DisplayList* displayList,
|
||||
Rect& dirty, int32_t flags, uint32_t level) {
|
||||
|
||||
status_t OpenGLRenderer::drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags) {
|
||||
// All the usual checks and setup operations (quickReject, setupDraw, etc.)
|
||||
// will be performed by the display list itself
|
||||
if (displayList && displayList->isRenderable()) {
|
||||
return displayList->replay(*this, dirty, flags, level);
|
||||
if (CC_UNLIKELY(mDrawDeferDisabled)) {
|
||||
return displayList->replay(*this, dirty, flags, 0);
|
||||
}
|
||||
|
||||
DeferredDisplayList deferredList;
|
||||
return displayList->replay(*this, dirty, flags, 0, &deferredList);
|
||||
}
|
||||
|
||||
return DrawGlInfo::kStatusDone;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::outputDisplayList(DisplayList* displayList, uint32_t level) {
|
||||
void OpenGLRenderer::outputDisplayList(DisplayList* displayList) {
|
||||
if (displayList) {
|
||||
displayList->output(level);
|
||||
displayList->output(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1990,7 +2049,7 @@ status_t OpenGLRenderer::drawBitmap(SkBitmap* bitmap,
|
||||
// Apply a scale transform on the canvas only when a shader is in use
|
||||
// Skia handles the ratio between the dst and src rects as a scale factor
|
||||
// when a shader is set
|
||||
bool useScaleTransform = mShader && scaled;
|
||||
bool useScaleTransform = mDrawModifiers.mShader && scaled;
|
||||
bool ignoreTransform = false;
|
||||
|
||||
if (CC_LIKELY(mSnapshot->transform->isPureTranslate() && !useScaleTransform)) {
|
||||
@@ -2445,15 +2504,15 @@ void OpenGLRenderer::drawTextShadow(SkPaint* paint, const char* text, int bytesC
|
||||
// if shader-based correction is enabled
|
||||
mCaches.dropShadowCache.setFontRenderer(fontRenderer);
|
||||
const ShadowTexture* shadow = mCaches.dropShadowCache.get(
|
||||
paint, text, bytesCount, count, mShadowRadius, positions);
|
||||
paint, text, bytesCount, count, mDrawModifiers.mShadowRadius, positions);
|
||||
const AutoTexture autoCleanup(shadow);
|
||||
|
||||
const float sx = x - shadow->left + mShadowDx;
|
||||
const float sy = y - shadow->top + mShadowDy;
|
||||
const float sx = x - shadow->left + mDrawModifiers.mShadowDx;
|
||||
const float sy = y - shadow->top + mDrawModifiers.mShadowDy;
|
||||
|
||||
const int shadowAlpha = ((mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
|
||||
int shadowColor = mShadowColor;
|
||||
if (mShader) {
|
||||
const int shadowAlpha = ((mDrawModifiers.mShadowColor >> 24) & 0xFF) * mSnapshot->alpha;
|
||||
int shadowColor = mDrawModifiers.mShadowColor;
|
||||
if (mDrawModifiers.mShader) {
|
||||
shadowColor = 0xffffffff;
|
||||
}
|
||||
|
||||
@@ -2501,7 +2560,7 @@ status_t OpenGLRenderer::drawPosText(const char* text, int bytesCount, int count
|
||||
SkXfermode::Mode mode;
|
||||
getAlphaAndMode(paint, &alpha, &mode);
|
||||
|
||||
if (CC_UNLIKELY(mHasShadow)) {
|
||||
if (CC_UNLIKELY(mDrawModifiers.mHasShadow)) {
|
||||
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer,
|
||||
alpha, mode, 0.0f, 0.0f);
|
||||
}
|
||||
@@ -2592,7 +2651,7 @@ status_t OpenGLRenderer::drawText(const char* text, int bytesCount, int count,
|
||||
SkXfermode::Mode mode;
|
||||
getAlphaAndMode(paint, &alpha, &mode);
|
||||
|
||||
if (CC_UNLIKELY(mHasShadow)) {
|
||||
if (CC_UNLIKELY(mDrawModifiers.mHasShadow)) {
|
||||
drawTextShadow(paint, text, bytesCount, count, positions, fontRenderer, alpha, mode,
|
||||
oldX, oldY);
|
||||
}
|
||||
@@ -2748,8 +2807,8 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* pain
|
||||
mCaches.activeTexture(0);
|
||||
|
||||
if (CC_LIKELY(!layer->region.isEmpty())) {
|
||||
SkiaColorFilter* oldFilter = mColorFilter;
|
||||
mColorFilter = layer->getColorFilter();
|
||||
SkiaColorFilter* oldFilter = mDrawModifiers.mColorFilter;
|
||||
mDrawModifiers.mColorFilter = layer->getColorFilter();
|
||||
|
||||
if (layer->region.isRect()) {
|
||||
composeLayerRect(layer, layer->regionRect);
|
||||
@@ -2788,7 +2847,7 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* pain
|
||||
#endif
|
||||
}
|
||||
|
||||
mColorFilter = oldFilter;
|
||||
mDrawModifiers.mColorFilter = oldFilter;
|
||||
|
||||
if (layer->debugDrawUpdate) {
|
||||
layer->debugDrawUpdate = false;
|
||||
@@ -2809,13 +2868,13 @@ status_t OpenGLRenderer::drawLayer(Layer* layer, float x, float y, SkPaint* pain
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void OpenGLRenderer::resetShader() {
|
||||
mShader = NULL;
|
||||
mDrawModifiers.mShader = NULL;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupShader(SkiaShader* shader) {
|
||||
mShader = shader;
|
||||
if (mShader) {
|
||||
mShader->set(&mCaches.textureCache, &mCaches.gradientCache);
|
||||
mDrawModifiers.mShader = shader;
|
||||
if (mDrawModifiers.mShader) {
|
||||
mDrawModifiers.mShader->set(&mCaches.textureCache, &mCaches.gradientCache);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2824,11 +2883,11 @@ void OpenGLRenderer::setupShader(SkiaShader* shader) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void OpenGLRenderer::resetColorFilter() {
|
||||
mColorFilter = NULL;
|
||||
mDrawModifiers.mColorFilter = NULL;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupColorFilter(SkiaColorFilter* filter) {
|
||||
mColorFilter = filter;
|
||||
mDrawModifiers.mColorFilter = filter;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -2836,15 +2895,15 @@ void OpenGLRenderer::setupColorFilter(SkiaColorFilter* filter) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void OpenGLRenderer::resetShadow() {
|
||||
mHasShadow = false;
|
||||
mDrawModifiers.mHasShadow = false;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) {
|
||||
mHasShadow = true;
|
||||
mShadowRadius = radius;
|
||||
mShadowDx = dx;
|
||||
mShadowDy = dy;
|
||||
mShadowColor = color;
|
||||
mDrawModifiers.mHasShadow = true;
|
||||
mDrawModifiers.mShadowRadius = radius;
|
||||
mDrawModifiers.mShadowDx = dx;
|
||||
mDrawModifiers.mShadowDy = dy;
|
||||
mDrawModifiers.mShadowColor = color;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -2852,22 +2911,23 @@ void OpenGLRenderer::setupShadow(float radius, float dx, float dy, int color) {
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void OpenGLRenderer::resetPaintFilter() {
|
||||
mHasDrawFilter = false;
|
||||
mDrawModifiers.mHasDrawFilter = false;
|
||||
}
|
||||
|
||||
void OpenGLRenderer::setupPaintFilter(int clearBits, int setBits) {
|
||||
mHasDrawFilter = true;
|
||||
mPaintFilterClearBits = clearBits & SkPaint::kAllFlags;
|
||||
mPaintFilterSetBits = setBits & SkPaint::kAllFlags;
|
||||
mDrawModifiers.mHasDrawFilter = true;
|
||||
mDrawModifiers.mPaintFilterClearBits = clearBits & SkPaint::kAllFlags;
|
||||
mDrawModifiers.mPaintFilterSetBits = setBits & SkPaint::kAllFlags;
|
||||
}
|
||||
|
||||
SkPaint* OpenGLRenderer::filterPaint(SkPaint* paint) {
|
||||
if (CC_LIKELY(!mHasDrawFilter || !paint)) return paint;
|
||||
if (CC_LIKELY(!mDrawModifiers.mHasDrawFilter || !paint)) return paint;
|
||||
|
||||
uint32_t flags = paint->getFlags();
|
||||
|
||||
mFilteredPaint = *paint;
|
||||
mFilteredPaint.setFlags((flags & ~mPaintFilterClearBits) | mPaintFilterSetBits);
|
||||
mFilteredPaint.setFlags((flags & ~mDrawModifiers.mPaintFilterClearBits) |
|
||||
mDrawModifiers.mPaintFilterSetBits);
|
||||
|
||||
return &mFilteredPaint;
|
||||
}
|
||||
@@ -2967,7 +3027,7 @@ status_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint
|
||||
|
||||
int color = paint->getColor();
|
||||
// If a shader is set, preserve only the alpha
|
||||
if (mShader) {
|
||||
if (mDrawModifiers.mShader) {
|
||||
color |= 0x00ffffff;
|
||||
}
|
||||
SkXfermode::Mode mode = getXfermode(paint->getXfermode());
|
||||
@@ -3040,7 +3100,7 @@ status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color
|
||||
void OpenGLRenderer::drawColorRect(float left, float top, float right, float bottom,
|
||||
int color, SkXfermode::Mode mode, bool ignoreTransform) {
|
||||
// If a shader is set, preserve only the alpha
|
||||
if (mShader) {
|
||||
if (mDrawModifiers.mShader) {
|
||||
color |= 0x00ffffff;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,34 @@
|
||||
namespace android {
|
||||
namespace uirenderer {
|
||||
|
||||
struct DrawModifiers {
|
||||
SkiaShader* mShader;
|
||||
SkiaColorFilter* mColorFilter;
|
||||
|
||||
// Drop shadow
|
||||
bool mHasShadow;
|
||||
float mShadowRadius;
|
||||
float mShadowDx;
|
||||
float mShadowDy;
|
||||
int mShadowColor;
|
||||
|
||||
// Draw filters
|
||||
bool mHasDrawFilter;
|
||||
int mPaintFilterClearBits;
|
||||
int mPaintFilterSetBits;
|
||||
};
|
||||
|
||||
struct DeferredDisplayState {
|
||||
Rect mBounds; // local bounds, mapped with matrix to be in screen space coordinates, clipped.
|
||||
int mMultipliedAlpha; // -1 if invalid (because caching not set)
|
||||
|
||||
// the below are set and used by the OpenGLRenderer at record and deferred playback
|
||||
Rect mClip;
|
||||
mat4 mMatrix;
|
||||
SkiaShader* mShader;
|
||||
DrawModifiers mDrawModifiers;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Renderer
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@@ -182,9 +210,8 @@ public:
|
||||
virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
|
||||
virtual Rect* getClipRect();
|
||||
|
||||
virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags,
|
||||
uint32_t level = 0);
|
||||
virtual void outputDisplayList(DisplayList* displayList, uint32_t level = 0);
|
||||
virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags);
|
||||
virtual void outputDisplayList(DisplayList* displayList);
|
||||
virtual status_t drawLayer(Layer* layer, float x, float y, SkPaint* paint);
|
||||
virtual status_t drawBitmap(SkBitmap* bitmap, float left, float top, SkPaint* paint);
|
||||
virtual status_t drawBitmap(SkBitmap* bitmap, SkMatrix* matrix, SkPaint* paint);
|
||||
@@ -233,6 +260,23 @@ public:
|
||||
|
||||
SkPaint* filterPaint(SkPaint* paint);
|
||||
|
||||
bool disallowDeferral() {
|
||||
// returns true if the OpenGLRenderer's state can be completely represented by
|
||||
// a DeferredDisplayState object
|
||||
return !mSnapshot->clipRegion->isEmpty() ||
|
||||
mSnapshot->alpha < 1.0 ||
|
||||
(mSnapshot->flags & Snapshot::kFlagIsLayer) ||
|
||||
(mSnapshot->flags & Snapshot::kFlagFboTarget); // ensure we're not in a layer
|
||||
}
|
||||
|
||||
bool disallowReorder() { return mDrawReorderDisabled; }
|
||||
|
||||
bool storeDisplayState(DeferredDisplayState& state);
|
||||
void restoreDisplayState(const DeferredDisplayState& state);
|
||||
|
||||
const DrawModifiers& getDrawModifiers() { return mDrawModifiers; }
|
||||
void setDrawModifiers(const DrawModifiers& drawModifiers) { mDrawModifiers = drawModifiers; }
|
||||
|
||||
ANDROID_API bool isCurrentTransformSimple() {
|
||||
return mSnapshot->transform->isSimple();
|
||||
}
|
||||
@@ -868,26 +912,11 @@ private:
|
||||
// State used to define the clipping region
|
||||
sp<Snapshot> mTilingSnapshot;
|
||||
|
||||
// Shaders
|
||||
SkiaShader* mShader;
|
||||
|
||||
// Color filters
|
||||
SkiaColorFilter* mColorFilter;
|
||||
|
||||
// Used to draw textured quads
|
||||
TextureVertex mMeshVertices[4];
|
||||
|
||||
// Drop shadow
|
||||
bool mHasShadow;
|
||||
float mShadowRadius;
|
||||
float mShadowDx;
|
||||
float mShadowDy;
|
||||
int mShadowColor;
|
||||
|
||||
// Draw filters
|
||||
bool mHasDrawFilter;
|
||||
int mPaintFilterClearBits;
|
||||
int mPaintFilterSetBits;
|
||||
// shader, filters, and shadow
|
||||
DrawModifiers mDrawModifiers;
|
||||
SkPaint mFilteredPaint;
|
||||
|
||||
// Various caches
|
||||
@@ -925,6 +954,8 @@ private:
|
||||
// See PROPERTY_DISABLE_SCISSOR_OPTIMIZATION in
|
||||
// Properties.h
|
||||
bool mScissorOptimizationDisabled;
|
||||
bool mDrawDeferDisabled;
|
||||
bool mDrawReorderDisabled;
|
||||
|
||||
// No-ops start/endTiling when set
|
||||
bool mSuppressTiling;
|
||||
|
||||
@@ -82,6 +82,19 @@ enum DebugLevel {
|
||||
*/
|
||||
#define PROPERTY_DISABLE_SCISSOR_OPTIMIZATION "ro.hwui.disable_scissor_opt"
|
||||
|
||||
/**
|
||||
* Disables draw operation deferral if set to "true", forcing draw
|
||||
* commands to be issued to OpenGL in order, and processed in sequence
|
||||
* with state-manipulation canvas commands.
|
||||
*/
|
||||
#define PROPERTY_DISABLE_DRAW_DEFER "debug.hwui.disable_draw_defer"
|
||||
|
||||
/**
|
||||
* Used to disable draw operation reordering when deferring draw operations
|
||||
* Has no effect if PROPERTY_DISABLE_DRAW_DEFER is set to "true"
|
||||
*/
|
||||
#define PROPERTY_DISABLE_DRAW_REORDER "debug.hwui.disable_draw_reorder"
|
||||
|
||||
// These properties are defined in mega-bytes
|
||||
#define PROPERTY_TEXTURE_CACHE_SIZE "ro.hwui.texture_cache_size"
|
||||
#define PROPERTY_LAYER_CACHE_SIZE "ro.hwui.layer_cache_size"
|
||||
|
||||
@@ -159,6 +159,13 @@ public:
|
||||
bottom += dy;
|
||||
}
|
||||
|
||||
void outset(float delta) {
|
||||
left -= delta;
|
||||
top -= delta;
|
||||
right += delta;
|
||||
bottom += delta;
|
||||
}
|
||||
|
||||
void snapToPixelBoundaries() {
|
||||
left = floorf(left + 0.5f);
|
||||
top = floorf(top + 0.5f);
|
||||
|
||||
Reference in New Issue
Block a user