Glop based composeLayerRegion/Rect

Change-Id: I69440cabca84948e8aaead9479d616ebc2496517
This commit is contained in:
Chris Craik
2015-03-09 14:17:29 -07:00
parent be331a3809
commit 182952f5ee
9 changed files with 112 additions and 48 deletions

View File

@@ -208,7 +208,8 @@ GlopBuilder& GlopBuilder::setMeshPatchQuads(const Patch& patch) {
// Fill
////////////////////////////////////////////////////////////////////////////////
void GlopBuilder::setFill(int color, float alphaScale, SkXfermode::Mode mode,
void GlopBuilder::setFill(int color, float alphaScale,
SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage,
const SkShader* shader, const SkColorFilter* colorFilter) {
if (mode != SkXfermode::kClear_Mode) {
float alpha = (SkColorGetA(color) / 255.0f) * alphaScale;
@@ -226,7 +227,6 @@ void GlopBuilder::setFill(int color, float alphaScale, SkXfermode::Mode mode,
} else {
mOutGlop->fill.color = { 0, 0, 0, 1 };
}
const bool SWAP_SRC_DST = false;
mOutGlop->blend = { GL_ZERO, GL_ZERO };
if (mOutGlop->fill.color.a < 1.0f
@@ -237,7 +237,7 @@ void GlopBuilder::setFill(int color, float alphaScale, SkXfermode::Mode mode,
|| PaintUtils::isBlendedColorFilter(colorFilter)
|| mode != SkXfermode::kSrcOver_Mode) {
if (CC_LIKELY(mode <= SkXfermode::kScreen_Mode)) {
Blend::getFactors(mode, SWAP_SRC_DST,
Blend::getFactors(mode, modeUsage,
&mOutGlop->blend.src, &mOutGlop->blend.dst);
} else {
// These blend modes are not supported by OpenGL directly and have
@@ -247,11 +247,11 @@ void GlopBuilder::setFill(int color, float alphaScale, SkXfermode::Mode mode,
// back to the default SrcOver blend mode instead
if (CC_UNLIKELY(mCaches.extensions().hasFramebufferFetch())) {
mDescription.framebufferMode = mode;
mDescription.swapSrcDst = SWAP_SRC_DST;
mDescription.swapSrcDst = (modeUsage == Blend::ModeOrderSwap::Swap);
// blending in shader, don't enable
} else {
// unsupported
Blend::getFactors(SkXfermode::kSrcOver_Mode, SWAP_SRC_DST,
Blend::getFactors(SkXfermode::kSrcOver_Mode, modeUsage,
&mOutGlop->blend.src, &mOutGlop->blend.dst);
}
}
@@ -317,17 +317,17 @@ GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture, int textureFillF
color |= 0x00FFFFFF;
shader = nullptr;
}
setFill(color, alphaScale, PaintUtils::getXfermode(paint->getXfermode()),
setFill(color, alphaScale,
PaintUtils::getXfermode(paint->getXfermode()), Blend::ModeOrderSwap::NoSwap,
shader, paint->getColorFilter());
} else {
mOutGlop->fill.color = { alphaScale, alphaScale, alphaScale, alphaScale };
const bool SWAP_SRC_DST = false;
if (alphaScale < 1.0f
|| (mOutGlop->mesh.vertices.flags & VertexAttribFlags::kAlpha)
|| texture.blend
|| mOutGlop->roundRectClipState) {
Blend::getFactors(SkXfermode::kSrcOver_Mode, SWAP_SRC_DST,
Blend::getFactors(SkXfermode::kSrcOver_Mode, Blend::ModeOrderSwap::NoSwap,
&mOutGlop->blend.src, &mOutGlop->blend.dst);
} else {
mOutGlop->blend = { GL_ZERO, GL_ZERO };
@@ -349,7 +349,8 @@ GlopBuilder& GlopBuilder::setFillPaint(const SkPaint& paint, float alphaScale) {
mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
setFill(paint.getColor(), alphaScale, PaintUtils::getXfermode(paint.getXfermode()),
setFill(paint.getColor(), alphaScale,
PaintUtils::getXfermode(paint.getXfermode()), Blend::ModeOrderSwap::NoSwap,
paint.getShader(), paint.getColorFilter());
mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
return *this;
@@ -363,7 +364,8 @@ GlopBuilder& GlopBuilder::setFillPathTexturePaint(PathTexture& texture,
//specify invalid filter/clamp, since these are always static for PathTextures
mOutGlop->fill.texture = { &texture, GL_TEXTURE_2D, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
setFill(paint.getColor(), alphaScale, PaintUtils::getXfermode(paint.getXfermode()),
setFill(paint.getColor(), alphaScale,
PaintUtils::getXfermode(paint.getXfermode()), Blend::ModeOrderSwap::NoSwap,
paint.getShader(), paint.getColorFilter());
mDescription.hasAlpha8Texture = true;
@@ -386,7 +388,8 @@ GlopBuilder& GlopBuilder::setFillShadowTexturePaint(ShadowTexture& texture, int
shadowColor &= paint.getColor() | COLOR_BITMASK;
}
setFill(shadowColor, alphaScale, PaintUtils::getXfermode(paint.getXfermode()),
setFill(shadowColor, alphaScale,
PaintUtils::getXfermode(paint.getXfermode()), Blend::ModeOrderSwap::NoSwap,
paint.getShader(), paint.getColorFilter());
mDescription.hasAlpha8Texture = true;
@@ -399,7 +402,8 @@ GlopBuilder& GlopBuilder::setFillBlack() {
REQUIRE_STAGES(kMeshStage);
mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
setFill(SK_ColorBLACK, 1.0f, SkXfermode::kSrcOver_Mode, nullptr, nullptr);
setFill(SK_ColorBLACK, 1.0f, SkXfermode::kSrcOver_Mode, Blend::ModeOrderSwap::NoSwap,
nullptr, nullptr);
return *this;
}
@@ -408,12 +412,13 @@ GlopBuilder& GlopBuilder::setFillClear() {
REQUIRE_STAGES(kMeshStage);
mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
setFill(SK_ColorBLACK, 1.0f, SkXfermode::kClear_Mode, nullptr, nullptr);
setFill(SK_ColorBLACK, 1.0f, SkXfermode::kClear_Mode, Blend::ModeOrderSwap::NoSwap,
nullptr, nullptr);
return *this;
}
GlopBuilder& GlopBuilder::setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
float alpha, SkXfermode::Mode mode) {
float alpha, SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage) {
TRIGGER_STAGE(kFillStage);
REQUIRE_STAGES(kMeshStage);
@@ -421,7 +426,7 @@ GlopBuilder& GlopBuilder::setFillLayer(Texture& texture, const SkColorFilter* co
GL_TEXTURE_2D, GL_LINEAR, GL_CLAMP_TO_EDGE, nullptr };
mOutGlop->fill.color = { alpha, alpha, alpha, alpha };
setFill(SK_ColorWHITE, alpha, mode, nullptr, colorFilter);
setFill(SK_ColorWHITE, alpha, mode, modeUsage, nullptr, colorFilter);
mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
return *this;
@@ -435,7 +440,8 @@ GlopBuilder& GlopBuilder::setFillTextureLayer(Layer& layer, float alpha) {
layer.getRenderTarget(), GL_LINEAR, GL_CLAMP_TO_EDGE, &layer.getTexTransform() };
mOutGlop->fill.color = { alpha, alpha, alpha, alpha };
setFill(SK_ColorWHITE, alpha, layer.getMode(), nullptr, layer.getColorFilter());
setFill(SK_ColorWHITE, alpha, layer.getMode(), Blend::ModeOrderSwap::NoSwap,
nullptr, layer.getColorFilter());
mDescription.modulate = mOutGlop->fill.color.a < 1.0f;
mDescription.hasTextureTransform = true;

View File

@@ -18,6 +18,7 @@
#include "OpenGLRenderer.h"
#include "Program.h"
#include "renderstate/Blend.h"
#include "utils/Macros.h"
class SkPaint;
@@ -65,7 +66,7 @@ public:
GlopBuilder& setFillBlack();
GlopBuilder& setFillClear();
GlopBuilder& setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
float alpha, SkXfermode::Mode mode);
float alpha, SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage);
GlopBuilder& setFillTextureLayer(Layer& layer, float alpha);
GlopBuilder& setTransform(const Matrix4& ortho, const Matrix4& transform, bool fudgingOffset);
@@ -94,7 +95,8 @@ public:
void build();
private:
void setFill(int color, float alphaScale, SkXfermode::Mode mode,
void setFill(int color, float alphaScale,
SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage,
const SkShader* shader, const SkColorFilter* colorFilter);
enum StageFlags {

View File

@@ -908,15 +908,35 @@ void OpenGLRenderer::composeLayerRect(Layer* layer, const Rect& rect, bool swap)
resetDrawTextureTexCoords(0.0f, 0.0f, 1.0f, 1.0f);
} else {
EVENT_LOGD("composeHardwareLayerRect");
if (USE_GLOPS) {
Blend::ModeOrderSwap modeUsage = swap ?
Blend::ModeOrderSwap::Swap : Blend::ModeOrderSwap::NoSwap;
const Matrix4& transform = swap ? Matrix4::identity() : *currentTransform();
bool snap = !swap
&& layer->getWidth() == static_cast<uint32_t>(rect.getWidth())
&& layer->getHeight() == static_cast<uint32_t>(rect.getHeight());
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshTexturedUvQuad(nullptr, layer->texCoords)
.setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), modeUsage)
.setTransform(currentSnapshot()->getOrthoMatrix(), transform, false)
.setModelViewMapUnitToRectOptionalSnap(snap, rect)
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
renderGlop(glop);
return;
}
const Rect& texCoords = layer->texCoords;
resetDrawTextureTexCoords(texCoords.left, texCoords.top,
texCoords.right, texCoords.bottom);
float x = rect.left;
float y = rect.top;
bool simpleTransform = currentTransform()->isPureTranslate() &&
layer->getWidth() == (uint32_t) rect.getWidth() &&
layer->getHeight() == (uint32_t) rect.getHeight();
bool simpleTransform = currentTransform()->isPureTranslate()
&& layer->getWidth() == (uint32_t) rect.getWidth()
&& layer->getHeight() == (uint32_t) rect.getHeight();
if (simpleTransform) {
// When we're swapping, the layer is already in screen coordinates
@@ -1053,11 +1073,42 @@ void OpenGLRenderer::composeLayerRegion(Layer* layer, const Rect& rect) {
rects = safeRegion.getArray(&count);
}
const float alpha = getLayerAlpha(layer);
const float texX = 1.0f / float(layer->getWidth());
const float texY = 1.0f / float(layer->getHeight());
const float height = rect.getHeight();
if (USE_GLOPS) {
TextureVertex quadVertices[count * 4];
//std::unique_ptr<TextureVertex[]> quadVertices(new TextureVertex[count * 4]);
TextureVertex* mesh = &quadVertices[0];
for (size_t i = 0; i < count; i++) {
const android::Rect* r = &rects[i];
const float u1 = r->left * texX;
const float v1 = (height - r->top) * texY;
const float u2 = r->right * texX;
const float v2 = (height - r->bottom) * texY;
// TODO: Reject quads outside of the clip
TextureVertex::set(mesh++, r->left, r->top, u1, v1);
TextureVertex::set(mesh++, r->right, r->top, u2, v1);
TextureVertex::set(mesh++, r->left, r->bottom, u1, v2);
TextureVertex::set(mesh++, r->right, r->bottom, u2, v2);
}
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshTexturedIndexedQuads(&quadVertices[0], count * 6)
.setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
.setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
.setModelViewOffsetRectSnap(0, 0, rect)
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
.build();
DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
return;
}
const float alpha = getLayerAlpha(layer);
setupDraw();
// We must get (and therefore bind) the region mesh buffer
@@ -3114,7 +3165,7 @@ void OpenGLRenderer::drawLayer(Layer* layer, float x, float y) {
Glop glop;
GlopBuilder(mRenderState, mCaches, &glop)
.setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount)
.setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode())
.setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
.setTransform(currentSnapshot()->getOrthoMatrix(), *currentTransform(), false)
.setModelViewOffsetRectSnap(x, y, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight()))
.setRoundRectClipState(currentSnapshot()->roundRectClipState)
@@ -3600,7 +3651,8 @@ void OpenGLRenderer::chooseBlending(bool blend, SkXfermode::Mode mode,
mode = SkXfermode::kSrcOver_Mode;
}
}
mRenderState.blend().enable(mode, swapSrcDst);
mRenderState.blend().enable(mode,
swapSrcDst ? Blend::ModeOrderSwap::Swap : Blend::ModeOrderSwap::NoSwap);
} else {
mRenderState.blend().disable();
}

View File

@@ -139,7 +139,7 @@ void RenderNode::damageSelf(TreeInfo& info) {
void RenderNode::prepareLayer(TreeInfo& info, uint32_t dirtyMask) {
LayerType layerType = properties().layerProperties().type();
if (CC_UNLIKELY(layerType == kLayerTypeRenderLayer)) {
if (CC_UNLIKELY(layerType == LayerType::RenderLayer)) {
// Damage applied so far needs to affect our parent, but does not require
// the layer to be updated. So we pop/push here to clear out the current
// damage and get a clean state for display list or children updates to
@@ -156,7 +156,7 @@ void RenderNode::pushLayerUpdate(TreeInfo& info) {
LayerType layerType = properties().layerProperties().type();
// If we are not a layer OR we cannot be rendered (eg, view was detached)
// we need to destroy any Layers we may have had previously
if (CC_LIKELY(layerType != kLayerTypeRenderLayer) || CC_UNLIKELY(!isRenderable())) {
if (CC_LIKELY(layerType != LayerType::RenderLayer) || CC_UNLIKELY(!isRenderable())) {
if (CC_UNLIKELY(mLayer)) {
LayerRenderer::destroyLayer(mLayer);
mLayer = nullptr;
@@ -384,7 +384,7 @@ void RenderNode::setViewProperties(OpenGLRenderer& renderer, T& handler) {
renderer.concatMatrix(*properties().getTransformMatrix());
}
}
const bool isLayer = properties().layerProperties().type() != kLayerTypeNone;
const bool isLayer = properties().layerProperties().type() != LayerType::None;
int clipFlags = properties().getClippingFlags();
if (properties().getAlpha() < 1) {
if (isLayer) {

View File

@@ -33,14 +33,12 @@
namespace android {
namespace uirenderer {
LayerProperties::LayerProperties()
: mType(kLayerTypeNone)
, mColorFilter(nullptr) {
LayerProperties::LayerProperties() {
reset();
}
LayerProperties::~LayerProperties() {
setType(kLayerTypeNone);
setType(LayerType::None);
}
void LayerProperties::reset() {
@@ -146,7 +144,7 @@ void RenderProperties::debugOutputProperties(const int level) const {
}
}
const bool isLayer = layerProperties().type() != kLayerTypeNone;
const bool isLayer = layerProperties().type() != LayerType::None;
int clipFlags = getClippingFlags();
if (mPrimitiveFields.mAlpha < 1) {
if (isLayer) {

View File

@@ -49,12 +49,12 @@ class RenderProperties;
#define RP_SET_AND_DIRTY(a, b) RP_SET(a, b, mPrimitiveFields.mMatrixOrPivotDirty = true)
// Keep in sync with View.java:LAYER_TYPE_*
enum LayerType {
kLayerTypeNone = 0,
enum class LayerType {
None = 0,
// Although we cannot build the software layer directly (must be done at
// record time), this information is used when applying alpha.
kLayerTypeSoftware = 1,
kLayerTypeRenderLayer = 2,
Software = 1,
RenderLayer = 2,
// TODO: LayerTypeSurfaceTexture? Maybe?
};
@@ -124,12 +124,12 @@ private:
friend class RenderProperties;
LayerType mType;
LayerType mType = LayerType::None;
// Whether or not that Layer's content is opaque, doesn't include alpha
bool mOpaque;
uint8_t mAlpha;
SkXfermode::Mode mMode;
SkColorFilter* mColorFilter;
SkColorFilter* mColorFilter = nullptr;
};
/*

View File

@@ -78,10 +78,10 @@ Blend::Blend()
// gl blending off by default
}
void Blend::enable(SkXfermode::Mode mode, bool swapSrcDst) {
void Blend::enable(SkXfermode::Mode mode, ModeOrderSwap modeUsage) {
GLenum srcMode;
GLenum dstMode;
getFactors(mode, swapSrcDst, &srcMode, &dstMode);
getFactors(mode, modeUsage, &srcMode, &dstMode);
setFactors(srcMode, dstMode);
}
@@ -105,9 +105,9 @@ void Blend::syncEnabled() {
}
}
void Blend::getFactors(SkXfermode::Mode mode, bool swapSrcDst, GLenum* outSrc, GLenum* outDst) {
*outSrc = swapSrcDst ? kBlendsSwap[mode].src : kBlends[mode].src;
*outDst = swapSrcDst ? kBlendsSwap[mode].dst : kBlends[mode].dst;
void Blend::getFactors(SkXfermode::Mode mode, ModeOrderSwap modeUsage, GLenum* outSrc, GLenum* outDst) {
*outSrc = (modeUsage == ModeOrderSwap::Swap) ? kBlendsSwap[mode].src : kBlends[mode].src;
*outDst = (modeUsage == ModeOrderSwap::Swap) ? kBlendsSwap[mode].dst : kBlends[mode].dst;
}
void Blend::setFactors(GLenum srcMode, GLenum dstMode) {

View File

@@ -29,11 +29,18 @@ namespace uirenderer {
class Blend {
friend class RenderState;
public:
void enable(SkXfermode::Mode mode, bool swapSrcDst);
// dictates whether to swap src/dst
enum class ModeOrderSwap {
NoSwap,
Swap,
};
void enable(SkXfermode::Mode mode, ModeOrderSwap modeUsage);
void disable();
void syncEnabled();
static void getFactors(SkXfermode::Mode mode, bool swapSrcDst, GLenum* outSrc, GLenum* outDst);
static void getFactors(SkXfermode::Mode mode, ModeOrderSwap modeUsage,
GLenum* outSrc, GLenum* outDst);
void setFactors(GLenum src, GLenum dst);
void dump();

View File

@@ -37,7 +37,7 @@ MeshState::MeshState()
mCurrentBuffer = mUnitQuadBuffer;
std::unique_ptr<uint16_t[]> regionIndices(new uint16_t[kMaxNumberOfQuads * 6]);
uint16_t regionIndices[kMaxNumberOfQuads * 6];
for (uint32_t i = 0; i < kMaxNumberOfQuads; i++) {
uint16_t quad = i * 4;
int index = i * 6;
@@ -50,8 +50,7 @@ MeshState::MeshState()
}
glGenBuffers(1, &mQuadListIndices);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, mQuadListIndices);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, kMaxNumberOfQuads * 6 * sizeof(uint16_t),
regionIndices.get(), GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(regionIndices), regionIndices, GL_STATIC_DRAW);
mCurrentIndicesBuffer = mQuadListIndices;
// position attribute always enabled