Merge "Add more support for transformed clip rects and paths" into jb-mr1-dev

This commit is contained in:
Romain Guy
2012-08-31 17:18:03 -07:00
committed by Android (Google) Code Review
10 changed files with 190 additions and 78 deletions

View File

@@ -46,6 +46,7 @@
#include <OpenGLRenderer.h>
#include <SkiaShader.h>
#include <SkiaColorFilter.h>
#include <Stencil.h>
#include <Rect.h>
#include <TextLayout.h>
@@ -150,7 +151,7 @@ static void android_view_GLES20Canvas_finish(JNIEnv* env, jobject clazz,
}
static jint android_view_GLES20Canvas_getStencilSize(JNIEnv* env, jobject clazz) {
return OpenGLRenderer::getStencilSize();
return Stencil::getStencilSize();
}
// ----------------------------------------------------------------------------

View File

@@ -28,6 +28,7 @@ ifeq ($(USE_OPENGL_RENDERER),true)
SkiaColorFilter.cpp \
SkiaShader.cpp \
Snapshot.cpp \
Stencil.cpp \
TextureCache.cpp \
TextDropShadowCache.cpp

View File

@@ -38,6 +38,7 @@
#include "TextDropShadowCache.h"
#include "FboCache.h"
#include "ResourceCache.h"
#include "Stencil.h"
#include "Dither.h"
namespace android {
@@ -252,10 +253,14 @@ public:
TextDropShadowCache dropShadowCache;
FboCache fboCache;
ResourceCache resourceCache;
Dither dither;
GammaFontRenderer* fontRenderer;
Dither dither;
#if STENCIL_BUFFER_SIZE
Stencil stencil;
#endif
// Debug methods
PFNGLINSERTEVENTMARKEREXTPROC eventMark;
PFNGLPUSHGROUPMARKEREXTPROC startMark;

View File

@@ -57,7 +57,7 @@ GradientCache::GradientCache():
INIT_LOGD(" Using default gradient cache size of %.2fMB", DEFAULT_GRADIENT_CACHE_SIZE);
}
glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
mMaxTextureSize = Caches::getInstance().maxTextureSize;
mCache.setOnEntryRemovedListener(this);
}

View File

@@ -139,10 +139,6 @@ void OpenGLRenderer::endMark() const {
// Setup
///////////////////////////////////////////////////////////////////////////////
uint32_t OpenGLRenderer::getStencilSize() {
return STENCIL_BUFFER_SIZE;
}
bool OpenGLRenderer::isDeferred() {
return false;
}

View File

@@ -207,12 +207,6 @@ public:
SkPaint* filterPaint(SkPaint* paint);
/**
* Returns the desired size for the stencil buffer. If the returned value
* is 0, then no stencil buffer is required.
*/
ANDROID_API static uint32_t getStencilSize();
/**
* Sets the alpha on the current snapshot. This alpha value will be modulated
* with other alpha values when drawing primitives.

View File

@@ -57,7 +57,7 @@ Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags):
clipRect = &mClipRectRoot;
#if STENCIL_BUFFER_SIZE
if (s->clipRegion) {
mClipRegionRoot.merge(*s->clipRegion);
mClipRegionRoot.op(*s->clipRegion, SkRegion::kUnion_Op);
clipRegion = &mClipRegionRoot;
}
#endif
@@ -84,8 +84,7 @@ void Snapshot::ensureClipRegion() {
#if STENCIL_BUFFER_SIZE
if (!clipRegion) {
clipRegion = &mClipRegionRoot;
android::Rect tmp(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
clipRegion->set(tmp);
clipRegion->setRect(clipRect->left, clipRect->top, clipRect->right, clipRect->bottom);
}
#endif
}
@@ -93,11 +92,11 @@ void Snapshot::ensureClipRegion() {
void Snapshot::copyClipRectFromRegion() {
#if STENCIL_BUFFER_SIZE
if (!clipRegion->isEmpty()) {
android::Rect bounds(clipRegion->bounds());
clipRect->set(bounds.left, bounds.top, bounds.right, bounds.bottom);
const SkIRect& bounds = clipRegion->getBounds();
clipRect->set(bounds.fLeft, bounds.fTop, bounds.fRight, bounds.fBottom);
if (clipRegion->isRect()) {
clipRegion->clear();
clipRegion->setEmpty();
clipRegion = NULL;
}
} else {
@@ -107,43 +106,11 @@ void Snapshot::copyClipRectFromRegion() {
#endif
}
bool Snapshot::clipRegionOr(float left, float top, float right, float bottom) {
bool Snapshot::clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op) {
#if STENCIL_BUFFER_SIZE
android::Rect tmp(left, top, right, bottom);
clipRegion->orSelf(tmp);
copyClipRectFromRegion();
return true;
#else
return false;
#endif
}
bool Snapshot::clipRegionXor(float left, float top, float right, float bottom) {
#if STENCIL_BUFFER_SIZE
android::Rect tmp(left, top, right, bottom);
clipRegion->xorSelf(tmp);
copyClipRectFromRegion();
return true;
#else
return false;
#endif
}
bool Snapshot::clipRegionAnd(float left, float top, float right, float bottom) {
#if STENCIL_BUFFER_SIZE
android::Rect tmp(left, top, right, bottom);
clipRegion->andSelf(tmp);
copyClipRectFromRegion();
return true;
#else
return false;
#endif
}
bool Snapshot::clipRegionNand(float left, float top, float right, float bottom) {
#if STENCIL_BUFFER_SIZE
android::Rect tmp(left, top, right, bottom);
clipRegion->subtractSelf(tmp);
SkIRect tmp;
tmp.set(left, top, right, bottom);
clipRegion->op(tmp, op);
copyClipRectFromRegion();
return true;
#else
@@ -161,14 +128,9 @@ bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
bool clipped = false;
switch (op) {
case SkRegion::kDifference_Op: {
ensureClipRegion();
clipped = clipRegionNand(r.left, r.top, r.right, r.bottom);
break;
}
case SkRegion::kIntersect_Op: {
if (CC_UNLIKELY(clipRegion)) {
clipped = clipRegionOr(r.left, r.top, r.right, r.bottom);
clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kIntersect_Op);
} else {
clipped = clipRect->intersect(r);
if (!clipped) {
@@ -180,26 +142,22 @@ bool Snapshot::clipTransformed(const Rect& r, SkRegion::Op op) {
}
case SkRegion::kUnion_Op: {
if (CC_UNLIKELY(clipRegion)) {
clipped = clipRegionAnd(r.left, r.top, r.right, r.bottom);
clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, SkRegion::kUnion_Op);
} else {
clipped = clipRect->unionWith(r);
}
break;
}
case SkRegion::kXOR_Op: {
ensureClipRegion();
clipped = clipRegionXor(r.left, r.top, r.right, r.bottom);
break;
}
case SkRegion::kReverseDifference_Op: {
// TODO!!!!!!!
break;
}
case SkRegion::kReplace_Op: {
setClip(r.left, r.top, r.right, r.bottom);
clipped = true;
break;
}
default: {
ensureClipRegion();
clipped = clipRegionOp(r.left, r.top, r.right, r.bottom, op);
break;
}
}
if (clipped) {
@@ -213,7 +171,7 @@ void Snapshot::setClip(float left, float top, float right, float bottom) {
clipRect->set(left, top, right, bottom);
#if STENCIL_BUFFER_SIZE
if (clipRegion) {
clipRegion->clear();
clipRegion->setEmpty();
clipRegion = NULL;
}
#endif

View File

@@ -198,7 +198,7 @@ public:
*
* This field is used only if STENCIL_BUFFER_SIZE is > 0.
*/
Region* clipRegion;
SkRegion* clipRegion;
/**
* The ancestor layer's dirty region.
@@ -223,17 +223,14 @@ private:
void ensureClipRegion();
void copyClipRectFromRegion();
bool clipRegionOr(float left, float top, float right, float bottom);
bool clipRegionXor(float left, float top, float right, float bottom);
bool clipRegionAnd(float left, float top, float right, float bottom);
bool clipRegionNand(float left, float top, float right, float bottom);
bool clipRegionOp(float left, float top, float right, float bottom, SkRegion::Op op);
mat4 mTransformRoot;
Rect mClipRectRoot;
Rect mLocalClip;
#if STENCIL_BUFFER_SIZE
Region mClipRegionRoot;
SkRegion mClipRegionRoot;
#endif
}; // class Snapshot

71
libs/hwui/Stencil.cpp Normal file
View File

@@ -0,0 +1,71 @@
/*
* Copyright (C) 2012 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.
*/
#include <GLES2/gl2.h>
#include "Properties.h"
#include "Stencil.h"
namespace android {
namespace uirenderer {
Stencil::Stencil(): mState(kDisabled) {
}
uint32_t Stencil::getStencilSize() {
return STENCIL_BUFFER_SIZE;
}
void Stencil::clear() {
glClearStencil(0);
glClear(GL_STENCIL_BUFFER_BIT);
}
void Stencil::enableTest() {
if (mState != kTest) {
enable();
glStencilFunc(GL_LESS, 0x0, 0x1);
// We only want to test, let's keep everything
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
mState = kTest;
}
}
void Stencil::enableWrite() {
if (mState != kWrite) {
enable();
glStencilFunc(GL_ALWAYS, 0x1, 0x1);
// The test always passes so the first two values are meaningless
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
mState = kWrite;
}
}
void Stencil::enable() {
if (!mState == kDisabled) {
glEnable(GL_STENCIL_TEST);
}
}
void Stencil::disable() {
if (mState != kDisabled) {
glDisable(GL_STENCIL_TEST);
mState = kDisabled;
}
}
}; // namespace uirenderer
}; // namespace android

89
libs/hwui/Stencil.h Normal file
View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2012 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_STENCIL_H
#define ANDROID_HWUI_STENCIL_H
#ifndef LOG_TAG
#define LOG_TAG "OpenGLRenderer"
#endif
#include <cutils/compiler.h>
namespace android {
namespace uirenderer {
///////////////////////////////////////////////////////////////////////////////
// Stencil buffer management
///////////////////////////////////////////////////////////////////////////////
class ANDROID_API Stencil {
public:
Stencil();
/**
* Returns the desired size for the stencil buffer. If the returned value
* is 0, then no stencil buffer is required.
*/
ANDROID_API static uint32_t getStencilSize();
/**
* Clears the stencil buffer.
*/
void clear();
/**
* Enables stencil test. When the stencil test is enabled the stencil
* buffer is not written into.
*/
void enableTest();
/**
* Enables stencil write. When stencil write is enabled, the stencil
* test always succeeds and the value 0x1 is written in the stencil
* buffer for each fragment.
*/
void enableWrite();
/**
* Disables stencil test and write.
*/
void disable();
/**
* Indicates whether either test or write is enabled.
*/
bool isEnabled() {
return mState != kDisabled;
}
private:
void enable();
enum StencilState {
kDisabled,
kTest,
kWrite
};
StencilState mState;
}; // class Stencil
}; // namespace uirenderer
}; // namespace android
#endif // ANDROID_HWUI_STENCIL_H