Make shadow_utils GM use its own SkResourceCache
authorBrian Salomon <bsalomon@google.com>
Thu, 23 Feb 2017 14:34:03 +0000 (09:34 -0500)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Thu, 23 Feb 2017 16:22:56 +0000 (16:22 +0000)
This should stabilize the replay testing on the bots.

Change-Id: I89e3e308000743da6e1a765751103cffabc7e4ba
Reviewed-on: https://skia-review.googlesource.com/8902
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>

gm/shadowutils.cpp
include/utils/SkShadowUtils.h
src/utils/SkShadowUtils.cpp

index fd02d92133c057ea72e0280022337599493fe780..350a546f0a18b17624bc452e9aaac4e492c41fef 100644 (file)
@@ -8,15 +8,15 @@
 #include "gm.h"
 #include "SkCanvas.h"
 #include "SkPath.h"
-#include "SkMutex.h"
+#include "SkResourceCache.h"
 #include "SkShadowUtils.h"
 
 void draw_shadow(SkCanvas* canvas, const SkPath& path, int height, SkColor color, SkPoint3 lightPos,
-                 SkScalar lightR, bool isAmbient, uint32_t flags) {
+                 SkScalar lightR, bool isAmbient, uint32_t flags, SkResourceCache* cache) {
     SkScalar ambientAlpha = isAmbient ? .5f : 0.f;
     SkScalar spotAlpha = isAmbient ? 0.f : .5f;
     SkShadowUtils::DrawShadow(canvas, path, height, lightPos, lightR, ambientAlpha, spotAlpha,
-                              color, flags);
+                              color, flags, cache);
 }
 
 static constexpr int kW = 700;
@@ -25,11 +25,10 @@ static constexpr int kH = 800;
 DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
     // SkShadowUtils uses a cache of SkVertices meshes. The vertices are created in a local
     // coordinate system and then translated when reused. The coordinate system depends on
-    // parameters to the generating draw. To avoid slight rendering differences due to this property
-    // we only allow one thread into this GM at a time and we reset the cache before each run.
-    static SkMutex gMutex;
-    SkAutoMutexAcquire mutexLock(&gMutex);
-    SkShadowUtils::ClearCache();
+    // parameters to the generating draw. If other threads are hitting the cache while this GM is
+    // running then we may have different cache behavior leading to slight rendering differences.
+    // To avoid that we use our own isolated cache rather than the global cache.
+    SkResourceCache cache(1 << 20);
 
     SkTArray<SkPath> paths;
     paths.push_back().addRoundRect(SkRect::MakeWH(50, 50), 10, 10);
@@ -70,8 +69,10 @@ DEF_SIMPLE_GM(shadow_utils, canvas, kW, kH) {
 
                 canvas->save();
                 canvas->concat(m);
-                draw_shadow(canvas, path, kHeight, SK_ColorRED, kLightPos, kLightR, true, flags);
-                draw_shadow(canvas, path, kHeight, SK_ColorBLUE, kLightPos, kLightR, false, flags);
+                draw_shadow(canvas, path, kHeight, SK_ColorRED, kLightPos, kLightR, true, flags,
+                            &cache);
+                draw_shadow(canvas, path, kHeight, SK_ColorBLUE, kLightPos, kLightR, false, flags,
+                            &cache);
 
                 // Draw the path outline in green on top of the ambient and spot shadows.
                 SkPaint paint;
index 60ce6ffe301fc87b54244eef455b1d47d93531b9..3339812c345268a67626bf61f3c16fa77559accf 100644 (file)
 
 class SkCanvas;
 class SkPath;
+class SkResourceCache;
 
 class SkShadowUtils {
 public:
-    // Draw an offset spot shadow and outlining ambient shadow for the given path.
-    static void DrawShadow(SkCanvas*, const SkPath& path, SkScalar occluderHeight,
-                           const SkPoint3& lightPos, SkScalar lightRadius,
-                           SkScalar ambientAlpha, SkScalar spotAlpha, SkColor color,
-                           uint32_t flags = SkShadowFlags::kNone_ShadowFlag);
-    static void ClearCache();
+    /**
+     * Draw an offset spot shadow and outlining ambient shadow for the given path using a disc
+     * light.
+     *
+     * @param canvas  The canvas on which to draw the shadows.
+     * @param path  The occluder used to generate the shadows.
+     * @param occluderHeight  The vertical offset of the occluder from the canvas. This is
+     *  indepdendent of the canvas's current matrix.
+     * @param lightPos  The 3D position of the light relative to the canvas plane. This is
+     *  independent of the canvas's current matrix.
+     * @param lightRadius  The radius of the disc light.
+     * @param ambientAlpha  The maximum alpha of the ambient shadow.
+     * @param spotAlpha  The maxium alpha of the spot shadow.
+     * @param color  The shadow color.
+     * @param flags  Options controlling opaque occluder optimizations and shadow appearance. See
+     *               SkShadowFlags.
+     * @param cache  Used for testing purposes. Clients should pass nullptr (default).
+     */
+    static void DrawShadow(SkCanvas* canvas, const SkPath& path, SkScalar occluderHeight,
+                           const SkPoint3& lightPos, SkScalar lightRadius, SkScalar ambientAlpha,
+                           SkScalar spotAlpha, SkColor color,
+                           uint32_t flags = SkShadowFlags::kNone_ShadowFlag,
+                           SkResourceCache* cache = nullptr);
 };
 
 #endif
index 86aba797d6e27f0c06f44db73652864dc31d74d9..88ebaf5c8f5516caad938013e0ebd40ecc8e7757 100644 (file)
@@ -375,7 +375,8 @@ static void* kNamespace;
  * they are first found in SkResourceCache.
  */
 template <typename FACTORY>
-void draw_shadow(const FACTORY& factory, SkCanvas* canvas, ShadowedPath& path, SkColor color) {
+void draw_shadow(const FACTORY& factory, SkCanvas* canvas, ShadowedPath& path, SkColor color,
+                 SkResourceCache* cache) {
     FindContext<FACTORY> context(&path.viewMatrix(), &factory);
 
     SkResourceCache::Key* key = nullptr;
@@ -386,7 +387,11 @@ void draw_shadow(const FACTORY& factory, SkCanvas* canvas, ShadowedPath& path, S
         key = new (keyStorage.begin()) SkResourceCache::Key();
         path.writeKey((uint32_t*)(keyStorage.begin() + sizeof(*key)));
         key->init(&kNamespace, resource_cache_shared_id(), keyDataBytes);
-        SkResourceCache::Find(*key, FindVisitor<FACTORY>, &context);
+        if (cache) {
+            cache->find(*key, FindVisitor<FACTORY>, &context);
+        } else {
+            SkResourceCache::Find(*key, FindVisitor<FACTORY>, &context);
+        }
     }
 
     sk_sp<SkVertices> vertices;
@@ -410,7 +415,12 @@ void draw_shadow(const FACTORY& factory, SkCanvas* canvas, ShadowedPath& path, S
             if (!vertices) {
                 return;
             }
-            SkResourceCache::Add(new CachedTessellationsRec(*key, std::move(tessellations)));
+            auto rec = new CachedTessellationsRec(*key, std::move(tessellations));
+            if (cache) {
+                cache->add(rec);
+            } else {
+                SkResourceCache::Add(rec);
+            }
         } else {
             vertices = factory.makeVertices(path.path(), path.viewMatrix());
             if (!vertices) {
@@ -444,7 +454,7 @@ static const float kGeomFactor = 64.0f;
 void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, SkScalar occluderHeight,
                                const SkPoint3& devLightPos, SkScalar lightRadius,
                                SkScalar ambientAlpha, SkScalar spotAlpha, SkColor color,
-                               uint32_t flags) {
+                               uint32_t flags, SkResourceCache* cache) {
     SkAutoCanvasRestore acr(canvas, true);
     SkMatrix viewMatrix = canvas->getTotalMatrix();
     canvas->resetMatrix();
@@ -467,7 +477,7 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, SkScalar oc
         factory.fPenumbraColor = SkColorSetARGB(255, 0, ambientAlpha * 255.9999f, 0);
         factory.fTransparent = transparent;
 
-        draw_shadow(factory, canvas, shadowedPath, color);
+        draw_shadow(factory, canvas, shadowedPath, color, cache);
     }
 
     if (spotAlpha > 0) {
@@ -523,8 +533,6 @@ void SkShadowUtils::DrawShadow(SkCanvas* canvas, const SkPath& path, SkScalar oc
         if (factory.fOccluderType == SpotVerticesFactory::OccluderType::kOpaque) {
             factory.fOccluderType = SpotVerticesFactory::OccluderType::kTransparent;
         }
-        draw_shadow(factory, canvas, shadowedPath, color);
+        draw_shadow(factory, canvas, shadowedPath, color, cache);
     }
 }
-
-void SkShadowUtils::ClearCache() { SkResourceCache::PostPurgeSharedID(resource_cache_shared_id()); }