Fix Ganesh drawAtlas bug with quad colors
Ganesh was not expanding the quad colors to vertex colors before calling drawVertices. The new GM would've caught this bug and reveals Ganesh's limitations re the various xfer modes used with drawAtlas (i.e., w/o AA Ganesh only supports kModulate, w/ AA Ganesh only supports the coefficient-based xfer modes). Review URL: https://codereview.chromium.org/1254943002
This commit is contained in:
parent
965b36cb16
commit
29ccdf86ab
177
gm/drawatlascolor.cpp
Normal file
177
gm/drawatlascolor.cpp
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2015 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 "SkCanvas.h"
|
||||
#include "SkRSXform.h"
|
||||
#include "SkSurface.h"
|
||||
|
||||
// Create a square atlas of:
|
||||
// opaque white | opaque red
|
||||
// ------------------------------------
|
||||
// opaque green | transparent black
|
||||
//
|
||||
static SkImage* make_atlas(SkCanvas* caller, int atlasSize) {
|
||||
const int kBlockSize = atlasSize/2;
|
||||
|
||||
SkImageInfo info = SkImageInfo::MakeN32Premul(atlasSize, atlasSize);
|
||||
SkAutoTUnref<SkSurface> surface(caller->newSurface(info));
|
||||
if (NULL == surface) {
|
||||
surface.reset(SkSurface::NewRaster(info));
|
||||
}
|
||||
SkCanvas* canvas = surface->getCanvas();
|
||||
|
||||
SkPaint paint;
|
||||
paint.setXfermode(SkXfermode::Create(SkXfermode::kSrc_Mode));
|
||||
|
||||
paint.setColor(SK_ColorWHITE);
|
||||
SkRect r = SkRect::MakeXYWH(0, 0,
|
||||
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
|
||||
canvas->drawRect(r, paint);
|
||||
|
||||
paint.setColor(SK_ColorRED);
|
||||
r = SkRect::MakeXYWH(SkIntToScalar(kBlockSize), 0,
|
||||
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
|
||||
canvas->drawRect(r, paint);
|
||||
|
||||
paint.setColor(SK_ColorGREEN);
|
||||
r = SkRect::MakeXYWH(0, SkIntToScalar(kBlockSize),
|
||||
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
|
||||
canvas->drawRect(r, paint);
|
||||
|
||||
paint.setColor(SK_ColorTRANSPARENT);
|
||||
r = SkRect::MakeXYWH(SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize),
|
||||
SkIntToScalar(kBlockSize), SkIntToScalar(kBlockSize));
|
||||
canvas->drawRect(r, paint);
|
||||
|
||||
return surface->newImageSnapshot();
|
||||
}
|
||||
|
||||
// This GM tests the drawAtlas API with colors, different xfer modes
|
||||
// and transparency in the atlas image
|
||||
class DrawAtlasColorsGM : public skiagm::GM {
|
||||
public:
|
||||
DrawAtlasColorsGM() {
|
||||
this->setBGColor(sk_tool_utils::color_to_565(0xFFCCCCCC));
|
||||
}
|
||||
|
||||
protected:
|
||||
SkString onShortName() override {
|
||||
return SkString("draw-atlas-colors");
|
||||
}
|
||||
|
||||
SkISize onISize() override {
|
||||
return SkISize::Make(kNumXferModes * (kAtlasSize + kPad) + kPad,
|
||||
2 * kNumColors * (kAtlasSize + kPad) + kTextPad + kPad);
|
||||
}
|
||||
|
||||
void onDraw(SkCanvas* canvas) override {
|
||||
const SkRect target = SkRect::MakeWH(SkIntToScalar(kAtlasSize), SkIntToScalar(kAtlasSize));
|
||||
|
||||
if (NULL == fAtlas) {
|
||||
fAtlas.reset(make_atlas(canvas, kAtlasSize));
|
||||
}
|
||||
|
||||
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, "Mod" },
|
||||
{ SkXfermode::kScreen_Mode, "Screen" },
|
||||
{ SkXfermode::kOverlay_Mode, "Overlay" },
|
||||
{ SkXfermode::kDarken_Mode, "Darken" },
|
||||
{ SkXfermode::kLighten_Mode, "Lighten" },
|
||||
{ SkXfermode::kColorDodge_Mode, "Dodge" },
|
||||
{ SkXfermode::kColorBurn_Mode, "Burn" },
|
||||
{ SkXfermode::kHardLight_Mode, "Hard" },
|
||||
{ SkXfermode::kSoftLight_Mode, "Soft" },
|
||||
{ SkXfermode::kDifference_Mode, "Diff" },
|
||||
{ SkXfermode::kExclusion_Mode, "Exclusion" },
|
||||
{ SkXfermode::kMultiply_Mode, "Multiply" },
|
||||
{ SkXfermode::kHue_Mode, "Hue" },
|
||||
{ SkXfermode::kSaturation_Mode, "Sat" },
|
||||
{ SkXfermode::kColor_Mode, "Color" },
|
||||
{ SkXfermode::kLuminosity_Mode, "Luminosity"},
|
||||
};
|
||||
|
||||
SkColor gColors[] = {
|
||||
SK_ColorWHITE,
|
||||
SK_ColorRED,
|
||||
0x88888888, // transparent grey
|
||||
0x88000088 // transparent blue
|
||||
};
|
||||
|
||||
const int numModes = SK_ARRAY_COUNT(gModes);
|
||||
SkASSERT(numModes == kNumXferModes);
|
||||
const int numColors = SK_ARRAY_COUNT(gColors);
|
||||
SkASSERT(numColors == kNumColors);
|
||||
SkRSXform xforms[numColors];
|
||||
SkRect rects[numColors];
|
||||
SkColor quadColors[numColors];
|
||||
|
||||
SkPaint paint;
|
||||
paint.setAntiAlias(true);
|
||||
|
||||
for (int i = 0; i < numColors; ++i) {
|
||||
xforms[i].set(1.0f, 0.0f, SkIntToScalar(kPad), i*(target.width()+kPad));
|
||||
rects[i] = target;
|
||||
quadColors[i] = gColors[i];
|
||||
}
|
||||
|
||||
SkPaint textP;
|
||||
textP.setTextSize(SkIntToScalar(kTextPad));
|
||||
textP.setAntiAlias(true);
|
||||
sk_tool_utils::set_portable_typeface_always(&textP, NULL);
|
||||
|
||||
for (int i = 0; i < numModes; ++i) {
|
||||
canvas->drawText(gModes[i].fLabel, strlen(gModes[i].fLabel),
|
||||
i*(target.width()+kPad)+kPad, SkIntToScalar(kTextPad),
|
||||
textP);
|
||||
}
|
||||
|
||||
for (int i = 0; i < numModes; ++i) {
|
||||
canvas->save();
|
||||
canvas->translate(SkIntToScalar(i*(target.height()+kPad)),
|
||||
SkIntToScalar(kTextPad+kPad));
|
||||
// w/o a paint
|
||||
canvas->drawAtlas(fAtlas, xforms, rects, quadColors, numColors,
|
||||
gModes[i].fMode, NULL, NULL);
|
||||
canvas->translate(0.0f, numColors*(target.height()+kPad));
|
||||
// w a paint
|
||||
canvas->drawAtlas(fAtlas, xforms, rects, quadColors, numColors,
|
||||
gModes[i].fMode, NULL, &paint);
|
||||
canvas->restore();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static const int kNumXferModes = 29;
|
||||
static const int kNumColors = 4;
|
||||
static const int kAtlasSize = 30;
|
||||
static const int kPad = 2;
|
||||
static const int kTextPad = 8;
|
||||
|
||||
|
||||
SkAutoTUnref<SkImage> fAtlas;
|
||||
|
||||
typedef GM INHERITED;
|
||||
};
|
||||
DEF_GM( return new DrawAtlasColorsGM; )
|
||||
|
@ -1714,10 +1714,23 @@ void SkGpuDevice::drawAtlas(const SkDraw& d, const SkImage* atlas, const SkRSXfo
|
||||
indices += 6;
|
||||
}
|
||||
|
||||
SkAutoTMalloc<SkColor> colorStorage;
|
||||
SkColor* vertCols = NULL;
|
||||
if (colors) {
|
||||
colorStorage.reset(vertCount);
|
||||
vertCols = colorStorage.get();
|
||||
|
||||
for (int i = 0; i < count; ++i) {
|
||||
vertCols[0] = vertCols[1] = vertCols[2] = vertCols[3] = colors[i];
|
||||
vertCols += 4;
|
||||
}
|
||||
}
|
||||
|
||||
verts = vertStorage.get();
|
||||
texs = verts + vertCount;
|
||||
vertCols = colorStorage.get();
|
||||
indices = indexStorage.get();
|
||||
this->drawVertices(d, SkCanvas::kTriangles_VertexMode, vertCount, verts, texs, colors, xfer,
|
||||
this->drawVertices(d, SkCanvas::kTriangles_VertexMode, vertCount, verts, texs, vertCols, xfer,
|
||||
indices, indexCount, p);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user