Fix Ganesh drawAtlas bug with quad colors
authorrobertphillips <robertphillips@google.com>
Fri, 24 Jul 2015 17:20:45 +0000 (10:20 -0700)
committerCommit bot <commit-bot@chromium.org>
Fri, 24 Jul 2015 17:20:45 +0000 (10:20 -0700)
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

gm/drawatlascolor.cpp [new file with mode: 0644]
src/gpu/SkGpuDevice.cpp

diff --git a/gm/drawatlascolor.cpp b/gm/drawatlascolor.cpp
new file mode 100644 (file)
index 0000000..ad0ec50
--- /dev/null
@@ -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; )
+
index a439458..e66d28f 100644 (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);
 }