Use Color Processor for color bitmap text draws on gpu.
This change is here since previously color bitmap text was rendered using a geometry processor in the coverage stage. The problem with this is that we cannot correctly do xfer modes with this method. So I now make color bitmap text draw using a color stage in the same was as a draw bitmap call. One issue that arrises from this fix is that we end up adding this final color processor after any previous color processors. Thus if we have a custom blend implemented as a color processor it will be before this text one and we won't blend correctly. This issue will get fixed once an xfer processor is fully implemented. I have hacked a test locally to show that if we can add the text color processor to the begining of the color stages we do blend correctly in all cases (so the xfer processor will be a fix). BUG=skia: Review URL: https://codereview.chromium.org/689923004
This commit is contained in:
parent
bd1605905b
commit
ed3af6648f
174
gm/colortypexfermode.cpp
Normal file
174
gm/colortypexfermode.cpp
Normal file
@ -0,0 +1,174 @@
|
||||
/*
|
||||
* Copyright 2014 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
#include "gm.h"
|
||||
#include "SkBitmap.h"
|
||||
#include "SkGradientShader.h"
|
||||
#include "SkShader.h"
|
||||
#include "SkXfermode.h"
|
||||
#include "../src/fonts/SkGScalerContext.h"
|
||||
|
||||
namespace skiagm {
|
||||
|
||||
static uint16_t gData[] = { 0xFFFF, 0xCCCF, 0xCCCF, 0xFFFF };
|
||||
|
||||
class ColorTypeXfermodeGM : public GM {
|
||||
SkBitmap fBG;
|
||||
|
||||
virtual void onOnceBeforeDraw() SK_OVERRIDE {
|
||||
fBG.installPixels(SkImageInfo::Make(2, 2, kARGB_4444_SkColorType,
|
||||
kOpaque_SkAlphaType), gData, 4);
|
||||
}
|
||||
|
||||
public:
|
||||
const static int W = 64;
|
||||
const static int H = 64;
|
||||
ColorTypeXfermodeGM() {
|
||||
const SkColor colors[] = {
|
||||
SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
|
||||
SK_ColorMAGENTA, SK_ColorCYAN, SK_ColorYELLOW
|
||||
};
|
||||
SkMatrix local;
|
||||
local.setRotate(180);
|
||||
SkShader* s = SkGradientShader::CreateSweep(0,0, colors, NULL,
|
||||
SK_ARRAY_COUNT(colors), 0, &local);
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
paint.setShader(s)->unref();
|
||||
|
||||
SkTypeface* orig = sk_tool_utils::create_portable_typeface("Times",
|
||||
SkTypeface::kBold);
|
||||
if (NULL == orig) {
|
||||
orig = SkTypeface::RefDefault();
|
||||
}
|
||||
fColorType = SkNEW_ARGS(SkGTypeface, (orig, paint));
|
||||
orig->unref();
|
||||
}
|
||||
|
||||
virtual ~ColorTypeXfermodeGM() {
|
||||
fColorType->unref();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual SkString onShortName() {
|
||||
return SkString("colortype_xfermodes");
|
||||
}
|
||||
|
||||
virtual SkISize onISize() {
|
||||
return SkISize::Make(400, 640);
|
||||
}
|
||||
|
||||
virtual void onDraw(SkCanvas* canvas) {
|
||||
canvas->translate(SkIntToScalar(10), SkIntToScalar(20));
|
||||
|
||||
const struct {
|
||||
SkXfermode::Mode fMode;
|
||||
const char* fLabel;
|
||||
} gModes[] = {
|
||||
{ SkXfermode::kClear_Mode, "Clear" },
|
||||
{ SkXfermode::kSrc_Mode, "Src" },
|
||||
{ SkXfermode::kDst_Mode, "Dst" },
|
||||
{ SkXfermode::kSrcOver_Mode, "SrcOver" },
|
||||
{ SkXfermode::kDstOver_Mode, "DstOver" },
|
||||
{ SkXfermode::kSrcIn_Mode, "SrcIn" },
|
||||
{ SkXfermode::kDstIn_Mode, "DstIn" },
|
||||
{ SkXfermode::kSrcOut_Mode, "SrcOut" },
|
||||
{ SkXfermode::kDstOut_Mode, "DstOut" },
|
||||
{ SkXfermode::kSrcATop_Mode, "SrcATop" },
|
||||
{ SkXfermode::kDstATop_Mode, "DstATop" },
|
||||
|
||||
{ SkXfermode::kXor_Mode, "Xor" },
|
||||
{ SkXfermode::kPlus_Mode, "Plus" },
|
||||
{ SkXfermode::kModulate_Mode, "Modulate" },
|
||||
{ SkXfermode::kScreen_Mode, "Screen" },
|
||||
{ SkXfermode::kOverlay_Mode, "Overlay" },
|
||||
{ SkXfermode::kDarken_Mode, "Darken" },
|
||||
{ SkXfermode::kLighten_Mode, "Lighten" },
|
||||
{ SkXfermode::kColorDodge_Mode, "ColorDodge" },
|
||||
{ SkXfermode::kColorBurn_Mode, "ColorBurn" },
|
||||
{ SkXfermode::kHardLight_Mode, "HardLight" },
|
||||
{ SkXfermode::kSoftLight_Mode, "SoftLight" },
|
||||
{ SkXfermode::kDifference_Mode, "Difference" },
|
||||
{ SkXfermode::kExclusion_Mode, "Exclusion" },
|
||||
{ SkXfermode::kMultiply_Mode, "Multiply" },
|
||||
{ SkXfermode::kHue_Mode, "Hue" },
|
||||
{ SkXfermode::kSaturation_Mode, "Saturation" },
|
||||
{ SkXfermode::kColor_Mode, "Color" },
|
||||
{ SkXfermode::kLuminosity_Mode, "Luminosity" },
|
||||
};
|
||||
|
||||
const SkScalar w = SkIntToScalar(W);
|
||||
const SkScalar h = SkIntToScalar(H);
|
||||
SkMatrix m;
|
||||
m.setScale(SkIntToScalar(6), SkIntToScalar(6));
|
||||
SkShader* s = SkShader::CreateBitmapShader(fBG,
|
||||
SkShader::kRepeat_TileMode,
|
||||
SkShader::kRepeat_TileMode,
|
||||
&m);
|
||||
|
||||
SkPaint labelP;
|
||||
labelP.setAntiAlias(true);
|
||||
sk_tool_utils::set_portable_typeface(&labelP);
|
||||
labelP.setTextAlign(SkPaint::kCenter_Align);
|
||||
|
||||
SkPaint textP;
|
||||
textP.setAntiAlias(true);
|
||||
textP.setTypeface(fColorType);
|
||||
textP.setTextSize(SkIntToScalar(70));
|
||||
|
||||
const int W = 5;
|
||||
|
||||
SkScalar x0 = 0;
|
||||
SkScalar y0 = 0;
|
||||
SkScalar x = x0, y = y0;
|
||||
for (size_t i = 0; i < SK_ARRAY_COUNT(gModes); i++) {
|
||||
SkXfermode* mode = SkXfermode::Create(gModes[i].fMode);
|
||||
SkAutoUnref aur(mode);
|
||||
SkRect r;
|
||||
r.set(x, y, x+w, y+h);
|
||||
|
||||
SkPaint p;
|
||||
p.setStyle(SkPaint::kFill_Style);
|
||||
p.setShader(s);
|
||||
canvas->drawRect(r, p);
|
||||
|
||||
r.inset(-SK_ScalarHalf, -SK_ScalarHalf);
|
||||
p.setStyle(SkPaint::kStroke_Style);
|
||||
p.setShader(NULL);
|
||||
canvas->drawRect(r, p);
|
||||
|
||||
textP.setXfermode(mode);
|
||||
canvas->drawText("H", 1, x+ w/10.f, y + 7.f*h/8.f, textP);
|
||||
#if 1
|
||||
canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
|
||||
x + w/2, y - labelP.getTextSize()/2, labelP);
|
||||
#endif
|
||||
x += w + SkIntToScalar(10);
|
||||
if ((i % W) == W - 1) {
|
||||
x = x0;
|
||||
y += h + SkIntToScalar(30);
|
||||
}
|
||||
}
|
||||
s->unref();
|
||||
}
|
||||
|
||||
virtual uint32_t onGetFlags() const {
|
||||
return kSkipPipe_Flag | kSkipPicture_Flag;
|
||||
}
|
||||
|
||||
private:
|
||||
SkTypeface* fColorType;
|
||||
|
||||
typedef GM INHERITED;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static GM* MyFactory(void*) { return new ColorTypeXfermodeGM; }
|
||||
static GMRegistry reg(MyFactory);
|
||||
|
||||
}
|
@ -49,6 +49,7 @@
|
||||
'../gm/colorfilters.cpp',
|
||||
'../gm/colormatrix.cpp',
|
||||
'../gm/colortype.cpp',
|
||||
'../gm/colortypexfermode.cpp',
|
||||
'../gm/colorwheel.cpp',
|
||||
'../gm/complexclip.cpp',
|
||||
'../gm/complexclip2.cpp',
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "GrTextStrike.h"
|
||||
#include "GrTextStrike_impl.h"
|
||||
#include "effects/GrCustomCoordsTextureEffect.h"
|
||||
#include "effects/GrSimpleTextureEffect.h"
|
||||
|
||||
#include "SkAutoKern.h"
|
||||
#include "SkColorPriv.h"
|
||||
@ -33,21 +34,29 @@ SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false,
|
||||
|
||||
namespace {
|
||||
// position + texture coord
|
||||
extern const GrVertexAttrib gTextVertexAttribs[] = {
|
||||
extern const GrVertexAttrib gLCDVertexAttribs[] = {
|
||||
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
|
||||
{kVec2f_GrVertexAttribType, sizeof(SkPoint), kGeometryProcessor_GrVertexAttribBinding}
|
||||
};
|
||||
|
||||
static const size_t kTextVASize = 2 * sizeof(SkPoint);
|
||||
static const size_t kLCDTextVASize = 2 * sizeof(SkPoint);
|
||||
|
||||
// position + local coord
|
||||
extern const GrVertexAttrib gColorVertexAttribs[] = {
|
||||
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
|
||||
{kVec2f_GrVertexAttribType, sizeof(SkPoint), kLocalCoord_GrVertexAttribBinding}
|
||||
};
|
||||
|
||||
static const size_t kColorTextVASize = 2 * sizeof(SkPoint);
|
||||
|
||||
// position + color + texture coord
|
||||
extern const GrVertexAttrib gTextVertexWithColorAttribs[] = {
|
||||
extern const GrVertexAttrib gGrayVertexAttribs[] = {
|
||||
{kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding},
|
||||
{kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVertexAttribBinding},
|
||||
{kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kGeometryProcessor_GrVertexAttribBinding}
|
||||
};
|
||||
|
||||
static const size_t kTextVAColorSize = 2 * sizeof(SkPoint) + sizeof(GrColor);
|
||||
static const size_t kGrayTextVASize = 2 * sizeof(SkPoint) + sizeof(GrColor);
|
||||
|
||||
static const int kVerticesPerGlyph = 4;
|
||||
static const int kIndicesPerGlyph = 6;
|
||||
@ -345,18 +354,21 @@ void GrBitmapTextContext::onDrawPosText(const GrPaint& paint, const SkPaint& skP
|
||||
this->finish();
|
||||
}
|
||||
|
||||
static void* alloc_vertices(GrDrawTarget* drawTarget, int numVertices, bool useColorVerts) {
|
||||
static void* alloc_vertices(GrDrawTarget* drawTarget, int numVertices, GrMaskFormat maskFormat) {
|
||||
if (numVertices <= 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// set up attributes
|
||||
if (useColorVerts) {
|
||||
drawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
|
||||
SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
|
||||
if (kA8_GrMaskFormat == maskFormat) {
|
||||
drawTarget->drawState()->setVertexAttribs<gGrayVertexAttribs>(
|
||||
SK_ARRAY_COUNT(gGrayVertexAttribs), kGrayTextVASize);
|
||||
} else if (kARGB_GrMaskFormat == maskFormat) {
|
||||
drawTarget->drawState()->setVertexAttribs<gColorVertexAttribs>(
|
||||
SK_ARRAY_COUNT(gColorVertexAttribs), kColorTextVASize);
|
||||
} else {
|
||||
drawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
|
||||
SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
|
||||
drawTarget->drawState()->setVertexAttribs<gLCDVertexAttribs>(
|
||||
SK_ARRAY_COUNT(gLCDVertexAttribs), kLCDTextVASize);
|
||||
}
|
||||
void* vertices = NULL;
|
||||
bool success = drawTarget->reserveVertexAndIndexSpace(numVertices,
|
||||
@ -476,12 +488,10 @@ HAS_ATLAS:
|
||||
fCurrMaskFormat = glyph->fMaskFormat;
|
||||
}
|
||||
|
||||
bool useColorVerts = kA8_GrMaskFormat == fCurrMaskFormat;
|
||||
|
||||
if (NULL == fVertices) {
|
||||
int maxQuadVertices = kVerticesPerGlyph * fContext->getQuadIndexBuffer()->maxQuads();
|
||||
fAllocVertexCount = SkMin32(fTotalVertexCount, maxQuadVertices);
|
||||
fVertices = alloc_vertices(fDrawTarget, fAllocVertexCount, useColorVerts);
|
||||
fVertices = alloc_vertices(fDrawTarget, fAllocVertexCount, fCurrMaskFormat);
|
||||
}
|
||||
|
||||
SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
|
||||
@ -495,8 +505,16 @@ HAS_ATLAS:
|
||||
|
||||
fVertexBounds.joinNonEmptyArg(r);
|
||||
|
||||
size_t vertSize = useColorVerts ? (2 * sizeof(SkPoint) + sizeof(GrColor)) :
|
||||
(2 * sizeof(SkPoint));
|
||||
size_t vertSize;
|
||||
switch (fCurrMaskFormat) {
|
||||
case kA8_GrMaskFormat:
|
||||
vertSize = kGrayTextVASize;
|
||||
break;
|
||||
case kARGB_GrMaskFormat:
|
||||
vertSize = kColorTextVASize;
|
||||
default:
|
||||
vertSize = kLCDTextVASize;
|
||||
}
|
||||
|
||||
SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexStride());
|
||||
|
||||
@ -512,7 +530,7 @@ HAS_ATLAS:
|
||||
SkFixedToFloat(texture->texturePriv().normalizeFixedX(tx + width)),
|
||||
SkFixedToFloat(texture->texturePriv().normalizeFixedY(ty + height)),
|
||||
vertSize);
|
||||
if (useColorVerts) {
|
||||
if (kA8_GrMaskFormat == fCurrMaskFormat) {
|
||||
if (0xFF == GrColorUnpackA(fPaint.getColor())) {
|
||||
fDrawTarget->drawState()->setHint(GrDrawState::kVertexColorsAreOpaque_Hint, true);
|
||||
}
|
||||
@ -548,16 +566,23 @@ void GrBitmapTextContext::flush() {
|
||||
SkASSERT(fCurrTexture);
|
||||
GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode);
|
||||
|
||||
uint32_t textureUniqueID = fCurrTexture->getUniqueID();
|
||||
// This effect could be stored with one of the cache objects (atlas?)
|
||||
if (kARGB_GrMaskFormat == fCurrMaskFormat) {
|
||||
GrFragmentProcessor* fragProcessor = GrSimpleTextureEffect::Create(fCurrTexture,
|
||||
SkMatrix::I(),
|
||||
params);
|
||||
drawState->addColorProcessor(fragProcessor)->unref();
|
||||
} else {
|
||||
uint32_t textureUniqueID = fCurrTexture->getUniqueID();
|
||||
if (textureUniqueID != fEffectTextureUniqueID) {
|
||||
fCachedGeometryProcessor.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture,
|
||||
params));
|
||||
fEffectTextureUniqueID = textureUniqueID;
|
||||
}
|
||||
|
||||
if (textureUniqueID != fEffectTextureUniqueID) {
|
||||
fCachedGeometryProcessor.reset(GrCustomCoordsTextureEffect::Create(fCurrTexture,
|
||||
params));
|
||||
fEffectTextureUniqueID = textureUniqueID;
|
||||
drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
|
||||
}
|
||||
|
||||
// This effect could be stored with one of the cache objects (atlas?)
|
||||
drawState->setGeometryProcessor(fCachedGeometryProcessor.get());
|
||||
SkASSERT(fStrike);
|
||||
switch (fCurrMaskFormat) {
|
||||
// Color bitmap text
|
||||
|
Loading…
Reference in New Issue
Block a user