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:
robertphillips 2015-07-24 10:20:45 -07:00 committed by Commit bot
parent 965b36cb16
commit 29ccdf86ab
2 changed files with 191 additions and 1 deletions

177
gm/drawatlascolor.cpp Normal file
View 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; )

View File

@ -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);
}