Merge "Preliminary Support for region clipping"
This commit is contained in:
@@ -433,20 +433,16 @@ class GLES20Canvas extends HardwareCanvas {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean clipPath(Path path) {
|
public boolean clipPath(Path path) {
|
||||||
// TODO: Implement
|
return nClipPath(mRenderer, path.mNativePath, Region.Op.INTERSECT.nativeInt);
|
||||||
path.computeBounds(mPathBounds, true);
|
|
||||||
return nClipRect(mRenderer, mPathBounds.left, mPathBounds.top,
|
|
||||||
mPathBounds.right, mPathBounds.bottom, Region.Op.INTERSECT.nativeInt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean clipPath(Path path, Region.Op op) {
|
public boolean clipPath(Path path, Region.Op op) {
|
||||||
// TODO: Implement
|
return nClipPath(mRenderer, path.mNativePath, op.nativeInt);
|
||||||
path.computeBounds(mPathBounds, true);
|
|
||||||
return nClipRect(mRenderer, mPathBounds.left, mPathBounds.top,
|
|
||||||
mPathBounds.right, mPathBounds.bottom, op.nativeInt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static native boolean nClipPath(int renderer, int path, int op);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean clipRect(float left, float top, float right, float bottom) {
|
public boolean clipRect(float left, float top, float right, float bottom) {
|
||||||
return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
|
return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
|
||||||
@@ -465,8 +461,8 @@ class GLES20Canvas extends HardwareCanvas {
|
|||||||
return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
|
return nClipRect(mRenderer, left, top, right, bottom, Region.Op.INTERSECT.nativeInt);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static native boolean nClipRect(int renderer, int left, int top, int right, int bottom,
|
private static native boolean nClipRect(int renderer, int left, int top,
|
||||||
int op);
|
int right, int bottom, int op);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean clipRect(Rect rect) {
|
public boolean clipRect(Rect rect) {
|
||||||
@@ -492,20 +488,16 @@ class GLES20Canvas extends HardwareCanvas {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean clipRegion(Region region) {
|
public boolean clipRegion(Region region) {
|
||||||
// TODO: Implement
|
return nClipRegion(mRenderer, region.mNativeRegion, Region.Op.INTERSECT.nativeInt);
|
||||||
region.getBounds(mClipBounds);
|
|
||||||
return nClipRect(mRenderer, mClipBounds.left, mClipBounds.top,
|
|
||||||
mClipBounds.right, mClipBounds.bottom, Region.Op.INTERSECT.nativeInt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean clipRegion(Region region, Region.Op op) {
|
public boolean clipRegion(Region region, Region.Op op) {
|
||||||
// TODO: Implement
|
return nClipRegion(mRenderer, region.mNativeRegion, op.nativeInt);
|
||||||
region.getBounds(mClipBounds);
|
|
||||||
return nClipRect(mRenderer, mClipBounds.left, mClipBounds.top,
|
|
||||||
mClipBounds.right, mClipBounds.bottom, op.nativeInt);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static native boolean nClipRegion(int renderer, int region, int op);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean getClipBounds(Rect bounds) {
|
public boolean getClipBounds(Rect bounds) {
|
||||||
return nGetClipBounds(mRenderer, bounds);
|
return nGetClipBounds(mRenderer, bounds);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2010 The Android Open Source Project
|
* Copyright (C) 2013 The Android Open Source Project
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -14,7 +14,6 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package android.view;
|
package android.view;
|
||||||
|
|
||||||
import android.content.ComponentCallbacks2;
|
import android.content.ComponentCallbacks2;
|
||||||
@@ -173,6 +172,17 @@ public abstract class HardwareRenderer {
|
|||||||
*/
|
*/
|
||||||
public static final String DEBUG_SHOW_OVERDRAW_PROPERTY = "debug.hwui.show_overdraw";
|
public static final String DEBUG_SHOW_OVERDRAW_PROPERTY = "debug.hwui.show_overdraw";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Turn on to allow region clipping (see
|
||||||
|
* {@link android.graphics.Canvas#clipPath(android.graphics.Path)} and
|
||||||
|
* {@link android.graphics.Canvas#clipRegion(android.graphics.Region)}.
|
||||||
|
*
|
||||||
|
* When this option is turned on a stencil buffer is always required.
|
||||||
|
* If this option is off a stencil buffer is only created when the overdraw
|
||||||
|
* debugging mode is turned on.
|
||||||
|
*/
|
||||||
|
private static final boolean REGION_CLIPPING_ENABLED = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A process can set this flag to false to prevent the use of hardware
|
* A process can set this flag to false to prevent the use of hardware
|
||||||
* rendering.
|
* rendering.
|
||||||
@@ -876,10 +886,12 @@ public abstract class HardwareRenderer {
|
|||||||
changed = true;
|
changed = true;
|
||||||
mShowOverdraw = value;
|
mShowOverdraw = value;
|
||||||
|
|
||||||
if (surface != null && isEnabled()) {
|
if (!REGION_CLIPPING_ENABLED) {
|
||||||
if (validate()) {
|
if (surface != null && isEnabled()) {
|
||||||
sEglConfig = loadEglConfig();
|
if (validate()) {
|
||||||
invalidate(surface);
|
sEglConfig = loadEglConfig();
|
||||||
|
invalidate(surface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1752,6 +1764,11 @@ public abstract class HardwareRenderer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
int[] getConfig(boolean dirtyRegions) {
|
int[] getConfig(boolean dirtyRegions) {
|
||||||
|
//noinspection PointlessBooleanExpression
|
||||||
|
final int stencilSize = mShowOverdraw || REGION_CLIPPING_ENABLED ?
|
||||||
|
GLES20Canvas.getStencilSize() : 0;
|
||||||
|
final int swapBehavior = dirtyRegions ? EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0;
|
||||||
|
|
||||||
return new int[] {
|
return new int[] {
|
||||||
EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
|
EGL_RENDERABLE_TYPE, EGL14.EGL_OPENGL_ES2_BIT,
|
||||||
EGL_RED_SIZE, 8,
|
EGL_RED_SIZE, 8,
|
||||||
@@ -1760,14 +1777,12 @@ public abstract class HardwareRenderer {
|
|||||||
EGL_ALPHA_SIZE, 8,
|
EGL_ALPHA_SIZE, 8,
|
||||||
EGL_DEPTH_SIZE, 0,
|
EGL_DEPTH_SIZE, 0,
|
||||||
EGL_CONFIG_CAVEAT, EGL_NONE,
|
EGL_CONFIG_CAVEAT, EGL_NONE,
|
||||||
// TODO: Find a better way to choose the stencil size
|
EGL_STENCIL_SIZE, stencilSize,
|
||||||
EGL_STENCIL_SIZE, mShowOverdraw ? GLES20Canvas.getStencilSize() : 0,
|
EGL_SURFACE_TYPE, EGL_WINDOW_BIT | swapBehavior,
|
||||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT |
|
|
||||||
(dirtyRegions ? EGL14.EGL_SWAP_BEHAVIOR_PRESERVED_BIT : 0),
|
|
||||||
EGL_NONE
|
EGL_NONE
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
void initCaches() {
|
void initCaches() {
|
||||||
GLES20Canvas.initCaches();
|
GLES20Canvas.initCaches();
|
||||||
|
|||||||
@@ -275,6 +275,16 @@ static bool android_view_GLES20Canvas_clipRect(JNIEnv* env, jobject clazz,
|
|||||||
return renderer->clipRect(float(left), float(top), float(right), float(bottom), op);
|
return renderer->clipRect(float(left), float(top), float(right), float(bottom), op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool android_view_GLES20Canvas_clipPath(JNIEnv* env, jobject clazz,
|
||||||
|
OpenGLRenderer* renderer, SkPath* path, SkRegion::Op op) {
|
||||||
|
return renderer->clipPath(path, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool android_view_GLES20Canvas_clipRegion(JNIEnv* env, jobject clazz,
|
||||||
|
OpenGLRenderer* renderer, SkRegion* region, SkRegion::Op op) {
|
||||||
|
return renderer->clipRegion(region, op);
|
||||||
|
}
|
||||||
|
|
||||||
static bool android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
|
static bool android_view_GLES20Canvas_getClipBounds(JNIEnv* env, jobject clazz,
|
||||||
OpenGLRenderer* renderer, jobject rect) {
|
OpenGLRenderer* renderer, jobject rect) {
|
||||||
const android::uirenderer::Rect& bounds(renderer->getClipBounds());
|
const android::uirenderer::Rect& bounds(renderer->getClipBounds());
|
||||||
@@ -961,6 +971,8 @@ static JNINativeMethod gMethods[] = {
|
|||||||
{ "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_quickReject },
|
{ "nQuickReject", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_quickReject },
|
||||||
{ "nClipRect", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_clipRectF },
|
{ "nClipRect", "(IFFFFI)Z", (void*) android_view_GLES20Canvas_clipRectF },
|
||||||
{ "nClipRect", "(IIIIII)Z", (void*) android_view_GLES20Canvas_clipRect },
|
{ "nClipRect", "(IIIIII)Z", (void*) android_view_GLES20Canvas_clipRect },
|
||||||
|
{ "nClipPath", "(III)Z", (void*) android_view_GLES20Canvas_clipPath },
|
||||||
|
{ "nClipRegion", "(III)Z", (void*) android_view_GLES20Canvas_clipRegion },
|
||||||
|
|
||||||
{ "nTranslate", "(IFF)V", (void*) android_view_GLES20Canvas_translate },
|
{ "nTranslate", "(IFF)V", (void*) android_view_GLES20Canvas_translate },
|
||||||
{ "nRotate", "(IF)V", (void*) android_view_GLES20Canvas_rotate },
|
{ "nRotate", "(IF)V", (void*) android_view_GLES20Canvas_rotate },
|
||||||
|
|||||||
@@ -35,6 +35,9 @@
|
|||||||
// Turn on to enable layers debugging when rendered as regions
|
// Turn on to enable layers debugging when rendered as regions
|
||||||
#define DEBUG_LAYERS_AS_REGIONS 0
|
#define DEBUG_LAYERS_AS_REGIONS 0
|
||||||
|
|
||||||
|
// Turn on to enable debugging when the clip is not a rect
|
||||||
|
#define DEBUG_CLIP_REGIONS 0
|
||||||
|
|
||||||
// Turn on to display debug info about vertex/fragment shaders
|
// Turn on to display debug info about vertex/fragment shaders
|
||||||
#define DEBUG_PROGRAMS 0
|
#define DEBUG_PROGRAMS 0
|
||||||
|
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ const char* DisplayList::OP_NAMES[] = {
|
|||||||
"SetMatrix",
|
"SetMatrix",
|
||||||
"ConcatMatrix",
|
"ConcatMatrix",
|
||||||
"ClipRect",
|
"ClipRect",
|
||||||
|
"ClipPath",
|
||||||
|
"ClipRegion",
|
||||||
"DrawDisplayList",
|
"DrawDisplayList",
|
||||||
"DrawLayer",
|
"DrawLayer",
|
||||||
"DrawBitmap",
|
"DrawBitmap",
|
||||||
@@ -166,6 +168,10 @@ void DisplayList::clearResources() {
|
|||||||
delete mPaints.itemAt(i);
|
delete mPaints.itemAt(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mRegions.size(); i++) {
|
||||||
|
delete mRegions.itemAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < mPaths.size(); i++) {
|
for (size_t i = 0; i < mPaths.size(); i++) {
|
||||||
SkPath* path = mPaths.itemAt(i);
|
SkPath* path = mPaths.itemAt(i);
|
||||||
caches.pathCache.remove(path);
|
caches.pathCache.remove(path);
|
||||||
@@ -182,6 +188,7 @@ void DisplayList::clearResources() {
|
|||||||
mShaders.clear();
|
mShaders.clear();
|
||||||
mSourcePaths.clear();
|
mSourcePaths.clear();
|
||||||
mPaints.clear();
|
mPaints.clear();
|
||||||
|
mRegions.clear();
|
||||||
mPaths.clear();
|
mPaths.clear();
|
||||||
mMatrices.clear();
|
mMatrices.clear();
|
||||||
mLayers.clear();
|
mLayers.clear();
|
||||||
@@ -259,20 +266,10 @@ void DisplayList::initFromDisplayListRenderer(const DisplayListRenderer& recorde
|
|||||||
|
|
||||||
caches.resourceCache.unlock();
|
caches.resourceCache.unlock();
|
||||||
|
|
||||||
const Vector<SkPaint*>& paints = recorder.getPaints();
|
mPaints.appendVector(recorder.getPaints());
|
||||||
for (size_t i = 0; i < paints.size(); i++) {
|
mRegions.appendVector(recorder.getRegions());
|
||||||
mPaints.add(paints.itemAt(i));
|
mPaths.appendVector(recorder.getPaths());
|
||||||
}
|
mMatrices.appendVector(recorder.getMatrices());
|
||||||
|
|
||||||
const Vector<SkPath*>& paths = recorder.getPaths();
|
|
||||||
for (size_t i = 0; i < paths.size(); i++) {
|
|
||||||
mPaths.add(paths.itemAt(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
const Vector<SkMatrix*>& matrices = recorder.getMatrices();
|
|
||||||
for (size_t i = 0; i < matrices.size(); i++) {
|
|
||||||
mMatrices.add(matrices.itemAt(i));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisplayList::init() {
|
void DisplayList::init() {
|
||||||
@@ -429,6 +426,18 @@ void DisplayList::output(OpenGLRenderer& renderer, uint32_t level) {
|
|||||||
f1, f2, f3, f4, regionOp);
|
f1, f2, f3, f4, regionOp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ClipPath: {
|
||||||
|
SkPath* path = getPath();
|
||||||
|
int regionOp = getInt();
|
||||||
|
ALOGD("%s%s %d", (char*) indent, OP_NAMES[op], regionOp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ClipRegion: {
|
||||||
|
SkRegion* region = getRegion();
|
||||||
|
int regionOp = getInt();
|
||||||
|
ALOGD("%s%s %d", (char*) indent, OP_NAMES[op], regionOp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case DrawDisplayList: {
|
case DrawDisplayList: {
|
||||||
DisplayList* displayList = getDisplayList();
|
DisplayList* displayList = getDisplayList();
|
||||||
int32_t flags = getInt();
|
int32_t flags = getInt();
|
||||||
@@ -1031,6 +1040,20 @@ status_t DisplayList::replay(OpenGLRenderer& renderer, Rect& dirty, int32_t flag
|
|||||||
renderer.clipRect(f1, f2, f3, f4, (SkRegion::Op) regionOp);
|
renderer.clipRect(f1, f2, f3, f4, (SkRegion::Op) regionOp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ClipPath: {
|
||||||
|
SkPath* path = getPath();
|
||||||
|
int32_t regionOp = getInt();
|
||||||
|
DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], regionOp);
|
||||||
|
renderer.clipPath(path, (SkRegion::Op) regionOp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ClipRegion: {
|
||||||
|
SkRegion* region = getRegion();
|
||||||
|
int32_t regionOp = getInt();
|
||||||
|
DISPLAY_LIST_LOGD("%s%s %d", (char*) indent, OP_NAMES[op], regionOp);
|
||||||
|
renderer.clipRegion(region, (SkRegion::Op) regionOp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case DrawDisplayList: {
|
case DrawDisplayList: {
|
||||||
DisplayList* displayList = getDisplayList();
|
DisplayList* displayList = getDisplayList();
|
||||||
int32_t flags = getInt();
|
int32_t flags = getInt();
|
||||||
@@ -1415,6 +1438,9 @@ void DisplayListRenderer::reset() {
|
|||||||
mPaints.clear();
|
mPaints.clear();
|
||||||
mPaintMap.clear();
|
mPaintMap.clear();
|
||||||
|
|
||||||
|
mRegions.clear();
|
||||||
|
mRegionMap.clear();
|
||||||
|
|
||||||
mPaths.clear();
|
mPaths.clear();
|
||||||
mPathMap.clear();
|
mPathMap.clear();
|
||||||
|
|
||||||
@@ -1571,6 +1597,20 @@ bool DisplayListRenderer::clipRect(float left, float top, float right, float bot
|
|||||||
return OpenGLRenderer::clipRect(left, top, right, bottom, op);
|
return OpenGLRenderer::clipRect(left, top, right, bottom, op);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DisplayListRenderer::clipPath(SkPath* path, SkRegion::Op op) {
|
||||||
|
addOp(DisplayList::ClipPath);
|
||||||
|
addPath(path);
|
||||||
|
addInt(op);
|
||||||
|
return OpenGLRenderer::clipPath(path, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DisplayListRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
|
||||||
|
addOp(DisplayList::ClipRegion);
|
||||||
|
addRegion(region);
|
||||||
|
addInt(op);
|
||||||
|
return OpenGLRenderer::clipRegion(region, op);
|
||||||
|
}
|
||||||
|
|
||||||
status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
|
status_t DisplayListRenderer::drawDisplayList(DisplayList* displayList,
|
||||||
Rect& dirty, int32_t flags, uint32_t level) {
|
Rect& dirty, int32_t flags, uint32_t level) {
|
||||||
// dirty is an out parameter and should not be recorded,
|
// dirty is an out parameter and should not be recorded,
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ public:
|
|||||||
SetMatrix,
|
SetMatrix,
|
||||||
ConcatMatrix,
|
ConcatMatrix,
|
||||||
ClipRect,
|
ClipRect,
|
||||||
|
ClipPath,
|
||||||
|
ClipRegion,
|
||||||
// Drawing operations
|
// Drawing operations
|
||||||
DrawDisplayList,
|
DrawDisplayList,
|
||||||
DrawLayer,
|
DrawLayer,
|
||||||
@@ -457,6 +459,10 @@ private:
|
|||||||
return (SkPath*) getInt();
|
return (SkPath*) getInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SkRegion* getRegion() {
|
||||||
|
return (SkRegion*) getInt();
|
||||||
|
}
|
||||||
|
|
||||||
SkPaint* getPaint(OpenGLRenderer& renderer) {
|
SkPaint* getPaint(OpenGLRenderer& renderer) {
|
||||||
return renderer.filterPaint((SkPaint*) getInt());
|
return renderer.filterPaint((SkPaint*) getInt());
|
||||||
}
|
}
|
||||||
@@ -496,6 +502,7 @@ private:
|
|||||||
Vector<SkPaint*> mPaints;
|
Vector<SkPaint*> mPaints;
|
||||||
Vector<SkPath*> mPaths;
|
Vector<SkPath*> mPaths;
|
||||||
SortedVector<SkPath*> mSourcePaths;
|
SortedVector<SkPath*> mSourcePaths;
|
||||||
|
Vector<SkRegion*> mRegions;
|
||||||
Vector<SkMatrix*> mMatrices;
|
Vector<SkMatrix*> mMatrices;
|
||||||
Vector<SkiaShader*> mShaders;
|
Vector<SkiaShader*> mShaders;
|
||||||
Vector<Layer*> mLayers;
|
Vector<Layer*> mLayers;
|
||||||
@@ -577,6 +584,8 @@ public:
|
|||||||
virtual void concatMatrix(SkMatrix* matrix);
|
virtual void concatMatrix(SkMatrix* matrix);
|
||||||
|
|
||||||
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
|
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
|
||||||
|
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,
|
virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags,
|
||||||
uint32_t level = 0);
|
uint32_t level = 0);
|
||||||
@@ -657,6 +666,10 @@ public:
|
|||||||
return mSourcePaths;
|
return mSourcePaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Vector<SkRegion*>& getRegions() const {
|
||||||
|
return mRegions;
|
||||||
|
}
|
||||||
|
|
||||||
const Vector<Layer*>& getLayers() const {
|
const Vector<Layer*>& getLayers() const {
|
||||||
return mLayers;
|
return mLayers;
|
||||||
}
|
}
|
||||||
@@ -802,6 +815,26 @@ private:
|
|||||||
return paintCopy;
|
return paintCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline SkRegion* addRegion(SkRegion* region) {
|
||||||
|
if (!region) {
|
||||||
|
addInt((int) NULL);
|
||||||
|
return region;
|
||||||
|
}
|
||||||
|
|
||||||
|
SkRegion* regionCopy = mRegionMap.valueFor(region);
|
||||||
|
// TODO: Add generation ID to SkRegion
|
||||||
|
if (regionCopy == NULL) {
|
||||||
|
regionCopy = new SkRegion(*region);
|
||||||
|
// replaceValueFor() performs an add if the entry doesn't exist
|
||||||
|
mRegionMap.replaceValueFor(region, regionCopy);
|
||||||
|
mRegions.add(regionCopy);
|
||||||
|
}
|
||||||
|
|
||||||
|
addInt((int) regionCopy);
|
||||||
|
|
||||||
|
return regionCopy;
|
||||||
|
}
|
||||||
|
|
||||||
inline void addDisplayList(DisplayList* displayList) {
|
inline void addDisplayList(DisplayList* displayList) {
|
||||||
// TODO: To be safe, the display list should be ref-counted in the
|
// TODO: To be safe, the display list should be ref-counted in the
|
||||||
// resources cache, but we rely on the caller (UI toolkit) to
|
// resources cache, but we rely on the caller (UI toolkit) to
|
||||||
@@ -876,6 +909,9 @@ private:
|
|||||||
|
|
||||||
SortedVector<SkPath*> mSourcePaths;
|
SortedVector<SkPath*> mSourcePaths;
|
||||||
|
|
||||||
|
Vector<SkRegion*> mRegions;
|
||||||
|
DefaultKeyedVector<SkRegion*, SkRegion*> mRegionMap;
|
||||||
|
|
||||||
Vector<SkiaShader*> mShaders;
|
Vector<SkiaShader*> mShaders;
|
||||||
DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
|
DefaultKeyedVector<SkiaShader*, SkiaShader*> mShaderMap;
|
||||||
|
|
||||||
|
|||||||
@@ -1288,10 +1288,38 @@ bool OpenGLRenderer::clipRect(float left, float top, float right, float bottom,
|
|||||||
bool clipped = mSnapshot->clip(left, top, right, bottom, op);
|
bool clipped = mSnapshot->clip(left, top, right, bottom, op);
|
||||||
if (clipped) {
|
if (clipped) {
|
||||||
dirtyClip();
|
dirtyClip();
|
||||||
|
#if DEBUG_CLIP_REGIONS
|
||||||
|
if (!isDeferred() && mSnapshot->clipRegion && !mSnapshot->clipRegion->isRect()) {
|
||||||
|
int count = 0;
|
||||||
|
Vector<float> rects;
|
||||||
|
SkRegion::Iterator it(*mSnapshot->clipRegion);
|
||||||
|
while (!it.done()) {
|
||||||
|
const SkIRect& r = it.rect();
|
||||||
|
rects.push(r.fLeft);
|
||||||
|
rects.push(r.fTop);
|
||||||
|
rects.push(r.fRight);
|
||||||
|
rects.push(r.fBottom);
|
||||||
|
count++;
|
||||||
|
it.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
drawColorRects(rects.array(), count, 0x7f00ff00, SkXfermode::kSrcOver_Mode, true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return !mSnapshot->clipRect->isEmpty();
|
return !mSnapshot->clipRect->isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OpenGLRenderer::clipPath(SkPath* path, SkRegion::Op op) {
|
||||||
|
const SkRect& bounds = path->getBounds();
|
||||||
|
return clipRect(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OpenGLRenderer::clipRegion(SkRegion* region, SkRegion::Op op) {
|
||||||
|
const SkIRect& bounds = region->getBounds();
|
||||||
|
return clipRect(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom, op);
|
||||||
|
}
|
||||||
|
|
||||||
Rect* OpenGLRenderer::getClipRect() {
|
Rect* OpenGLRenderer::getClipRect() {
|
||||||
return mSnapshot->clipRect;
|
return mSnapshot->clipRect;
|
||||||
}
|
}
|
||||||
@@ -3046,6 +3074,19 @@ status_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint
|
|||||||
return DrawGlInfo::kStatusDone;
|
return DrawGlInfo::kStatusDone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int color = paint->getColor();
|
||||||
|
// If a shader is set, preserve only the alpha
|
||||||
|
if (mShader) {
|
||||||
|
color |= 0x00ffffff;
|
||||||
|
}
|
||||||
|
SkXfermode::Mode mode = getXfermode(paint->getXfermode());
|
||||||
|
|
||||||
|
return drawColorRects(rects, count, color, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
status_t OpenGLRenderer::drawColorRects(const float* rects, int count, int color,
|
||||||
|
SkXfermode::Mode mode, bool ignoreTransform) {
|
||||||
|
|
||||||
float left = FLT_MAX;
|
float left = FLT_MAX;
|
||||||
float top = FLT_MAX;
|
float top = FLT_MAX;
|
||||||
float right = FLT_MIN;
|
float right = FLT_MIN;
|
||||||
@@ -3081,13 +3122,6 @@ status_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint
|
|||||||
|
|
||||||
if (count == 0) return DrawGlInfo::kStatusDone;
|
if (count == 0) return DrawGlInfo::kStatusDone;
|
||||||
|
|
||||||
int color = paint->getColor();
|
|
||||||
// If a shader is set, preserve only the alpha
|
|
||||||
if (mShader) {
|
|
||||||
color |= 0x00ffffff;
|
|
||||||
}
|
|
||||||
SkXfermode::Mode mode = getXfermode(paint->getXfermode());
|
|
||||||
|
|
||||||
setupDraw();
|
setupDraw();
|
||||||
setupDrawNoTexture();
|
setupDrawNoTexture();
|
||||||
setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
|
setupDrawColor(color, ((color >> 24) & 0xFF) * mSnapshot->alpha);
|
||||||
@@ -3096,7 +3130,7 @@ status_t OpenGLRenderer::drawRects(const float* rects, int count, SkPaint* paint
|
|||||||
setupDrawBlending(mode);
|
setupDrawBlending(mode);
|
||||||
setupDrawProgram();
|
setupDrawProgram();
|
||||||
setupDrawDirtyRegionsDisabled();
|
setupDrawDirtyRegionsDisabled();
|
||||||
setupDrawModelView(0.0f, 0.0f, 1.0f, 1.0f);
|
setupDrawModelView(0.0f, 0.0f, 1.0f, 1.0f, ignoreTransform, true);
|
||||||
setupDrawColorUniforms();
|
setupDrawColorUniforms();
|
||||||
setupDrawShaderUniforms();
|
setupDrawShaderUniforms();
|
||||||
setupDrawColorFilterUniforms();
|
setupDrawColorFilterUniforms();
|
||||||
|
|||||||
@@ -164,6 +164,8 @@ public:
|
|||||||
ANDROID_API bool quickReject(float left, float top, float right, float bottom);
|
ANDROID_API bool quickReject(float left, float top, float right, float bottom);
|
||||||
bool quickRejectNoScissor(float left, float top, float right, float bottom);
|
bool quickRejectNoScissor(float left, float top, float right, float bottom);
|
||||||
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
|
virtual bool clipRect(float left, float top, float right, float bottom, SkRegion::Op op);
|
||||||
|
virtual bool clipPath(SkPath* path, SkRegion::Op op);
|
||||||
|
virtual bool clipRegion(SkRegion* region, SkRegion::Op op);
|
||||||
virtual Rect* getClipRect();
|
virtual Rect* getClipRect();
|
||||||
|
|
||||||
virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags,
|
virtual status_t drawDisplayList(DisplayList* displayList, Rect& dirty, int32_t flags,
|
||||||
@@ -498,7 +500,8 @@ private:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a colored rectangle with the specified color. The specified coordinates
|
* Draws a colored rectangle with the specified color. The specified coordinates
|
||||||
* are transformed by the current snapshot's transform matrix.
|
* are transformed by the current snapshot's transform matrix unless specified
|
||||||
|
* otherwise.
|
||||||
*
|
*
|
||||||
* @param left The left coordinate of the rectangle
|
* @param left The left coordinate of the rectangle
|
||||||
* @param top The top coordinate of the rectangle
|
* @param top The top coordinate of the rectangle
|
||||||
@@ -511,6 +514,20 @@ private:
|
|||||||
void drawColorRect(float left, float top, float right, float bottom,
|
void drawColorRect(float left, float top, float right, float bottom,
|
||||||
int color, SkXfermode::Mode mode, bool ignoreTransform = false);
|
int color, SkXfermode::Mode mode, bool ignoreTransform = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Draws a series of colored rectangles with the specified color. The specified
|
||||||
|
* coordinates are transformed by the current snapshot's transform matrix unless
|
||||||
|
* specified otherwise.
|
||||||
|
*
|
||||||
|
* @param rects A list of rectangles, 4 floats (left, top, right, bottom)
|
||||||
|
* per rectangle
|
||||||
|
* @param color The rectangles' ARGB color, defined as a packed 32 bits word
|
||||||
|
* @param mode The Skia xfermode to use
|
||||||
|
* @param ignoreTransform True if the current transform should be ignored
|
||||||
|
*/
|
||||||
|
status_t drawColorRects(const float* rects, int count, int color,
|
||||||
|
SkXfermode::Mode mode, bool ignoreTransform = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the shape represented by the specified path texture.
|
* Draws the shape represented by the specified path texture.
|
||||||
* This method invokes drawPathTexture() but takes into account
|
* This method invokes drawPathTexture() but takes into account
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
|
|||||||
switch (op) {
|
switch (op) {
|
||||||
case SkRegion::kIntersect_Op: {
|
case SkRegion::kIntersect_Op: {
|
||||||
if (CC_UNLIKELY(clipRegion)) {
|
if (CC_UNLIKELY(clipRegion)) {
|
||||||
|
ensureClipRegion();
|
||||||
clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op);
|
clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op);
|
||||||
} else {
|
} else {
|
||||||
clipped = clipRect->intersect(r);
|
clipped = clipRect->intersect(r);
|
||||||
@@ -142,6 +143,7 @@ bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
|
|||||||
}
|
}
|
||||||
case SkRegion::kUnion_Op: {
|
case SkRegion::kUnion_Op: {
|
||||||
if (CC_UNLIKELY(clipRegion)) {
|
if (CC_UNLIKELY(clipRegion)) {
|
||||||
|
ensureClipRegion();
|
||||||
clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kUnion_Op);
|
clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kUnion_Op);
|
||||||
} else {
|
} else {
|
||||||
clipped = clipRect->unionWith(r);
|
clipped = clipRect->unionWith(r);
|
||||||
|
|||||||
@@ -18,13 +18,7 @@ package com.android.test.hwui;
|
|||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.graphics.BitmapFactory;
|
|
||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Paint;
|
|
||||||
import android.graphics.Path;
|
|
||||||
import android.graphics.PorterDuff;
|
|
||||||
import android.graphics.PorterDuffXfermode;
|
|
||||||
import android.graphics.Region;
|
import android.graphics.Region;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -50,8 +44,10 @@ public class ClipRegionActivity extends Activity {
|
|||||||
canvas.save();
|
canvas.save();
|
||||||
canvas.clipRect(100.0f, 100.0f, getWidth() - 100.0f, getHeight() - 100.0f,
|
canvas.clipRect(100.0f, 100.0f, getWidth() - 100.0f, getHeight() - 100.0f,
|
||||||
Region.Op.DIFFERENCE);
|
Region.Op.DIFFERENCE);
|
||||||
canvas.drawARGB(255, 255, 0, 0);
|
canvas.drawARGB(128, 255, 0, 0);
|
||||||
canvas.restore();
|
canvas.restore();
|
||||||
|
|
||||||
|
invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user