From: robertphillips Date: Fri, 24 Jul 2015 17:20:45 +0000 (-0700) Subject: Fix Ganesh drawAtlas bug with quad colors X-Git-Tag: accepted/tizen/5.0/unified/20181102.025319~1589 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=29ccdf86ab0a1649fd775c9431891bacb1391e99;p=platform%2Fupstream%2FlibSkiaSharp.git 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 --- diff --git a/gm/drawatlascolor.cpp b/gm/drawatlascolor.cpp new file mode 100644 index 0000000..ad0ec50 --- /dev/null +++ b/gm/drawatlascolor.cpp @@ -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 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 fAtlas; + + typedef GM INHERITED; +}; +DEF_GM( return new DrawAtlasColorsGM; ) + diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index a439458..e66d28f 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -1714,10 +1714,23 @@ void SkGpuDevice::drawAtlas(const SkDraw& d, const SkImage* atlas, const SkRSXfo indices += 6; } + SkAutoTMalloc 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); }