Creating framework for drawShadowedPicture
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2146073003

Committed: https://skia.googlesource.com/skia/+/0ae097d116f4332be02a135ffc99c162473dee6a
Review-Url: https://codereview.chromium.org/2146073003
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 050253f..2cfe8ae 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -663,6 +663,9 @@
     fDeviceCMDirty = true;
     fSaveCount = 1;
     fMetaData = nullptr;
+#ifdef SK_EXPERIMENTAL_SHADOWING
+    fLights = nullptr;
+#endif
 
     fClipStack.reset(new SkClipStack);
 
@@ -1519,6 +1522,7 @@
     this->setMatrix(SkMatrix::I());
 }
 
+#ifdef SK_EXPERIMENTAL_SHADOWING
 void SkCanvas::translateZ(SkScalar z) {
     this->checkForDeferredSave();
     this->fMCRec->fCurDrawDepth += z;
@@ -1529,6 +1533,15 @@
     return this->fMCRec->fCurDrawDepth;
 }
 
+void SkCanvas::setLights(sk_sp<SkLights> lights) {
+    this->fLights = lights;
+}
+
+sk_sp<SkLights> SkCanvas::getLights() const {
+    return this->fLights;
+}
+#endif
+
 //////////////////////////////////////////////////////////////////////////////
 
 void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
@@ -3000,6 +3013,24 @@
     picture->playback(this);
 }
 
+#ifdef SK_EXPERIMENTAL_SHADOWING
+void SkCanvas::drawShadowedPicture(const SkPicture* picture,
+                                   const SkMatrix* matrix,
+                                   const SkPaint* paint) {
+    RETURN_ON_NULL(picture);
+
+    TRACE_EVENT0("disabled-by-default-skia", "SkCanvas::drawShadowedPicture()");
+
+    this->onDrawShadowedPicture(picture, matrix, paint);
+}
+
+void SkCanvas::onDrawShadowedPicture(const SkPicture* picture,
+                                     const SkMatrix* matrix,
+                                     const SkPaint* paint) {
+    this->onDrawPicture(picture, matrix, paint);
+}
+#endif
+
 ///////////////////////////////////////////////////////////////////////////////
 ///////////////////////////////////////////////////////////////////////////////
 
diff --git a/src/core/SkLightingShader.cpp b/src/core/SkLightingShader.cpp
index 92f41ad..b6b5496 100644
--- a/src/core/SkLightingShader.cpp
+++ b/src/core/SkLightingShader.cpp
@@ -45,7 +45,7 @@
     */
     SkLightingShaderImpl(sk_sp<SkShader> diffuseShader,
                          sk_sp<SkNormalSource> normalSource,
-                         const sk_sp<SkLights> lights)
+                         sk_sp<SkLights> lights)
         : fDiffuseShader(std::move(diffuseShader))
         , fNormalSource(std::move(normalSource))
         , fLights(std::move(lights)) {}
@@ -134,6 +134,7 @@
                 // TODO: handle more than one of these
                 fLightColor = lights->light(i).color();
                 fLightDir = lights->light(i).dir();
+                // TODO get the handle to the shadow map if there is one
             }
         }
 
@@ -176,6 +177,9 @@
             this->emitChild(0, nullptr, &dstNormalName, args);
 
             fragBuilder->codeAppendf("vec3 normal = %s.xyz;", dstNormalName.c_str());
+
+            // TODO: make this a loop and modulate the contribution from each light
+            // based on the shadow map
             fragBuilder->codeAppendf("float NdotL = clamp(dot(normal, %s), 0.0, 1.0);",
                                      lightDirUniName);
             // diffuse light
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index 125d4e9..17b7681 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -17,6 +17,13 @@
 #include "SkPtrRecorder.h"
 #include "SkTDynamicHash.h"
 
+/*
+ * Note: While adding new DrawTypes, it is necessary to add to the end of this list
+ *       and update LAST_DRAWTYPE_ENUM to avoid having the code read older skps wrong.
+ *       (which can cause segfaults)
+ *
+ *       Reordering can be done during version updates.
+ */
 enum DrawType {
     UNUSED,
     CLIP_PATH,
@@ -83,7 +90,9 @@
 
     TRANSLATE_Z,
 
-    LAST_DRAWTYPE_ENUM = TRANSLATE_Z
+    DRAW_SHADOWED_PICTURE_LIGHTS,
+
+    LAST_DRAWTYPE_ENUM = DRAW_SHADOWED_PICTURE_LIGHTS
 };
 
 // In the 'match' method, this constant will match any flavor of DRAW_BITMAP*
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 60c4fe8..0bce09c 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -617,9 +617,11 @@
             canvas->translate(dx, dy);
         } break;
         case TRANSLATE_Z: {
+#ifdef SK_EXPERIMENTAL_SHADOWING
             SkScalar dz = reader->readScalar();
             canvas->translateZ(dz);
-        }
+#endif
+        } break;
         default:
             SkASSERTF(false, "Unknown draw type: %d", op);
     }
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index f2a0fd8..562f056 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -219,6 +219,7 @@
 }
 
 void SkPictureRecord::didTranslateZ(SkScalar z) {
+#ifdef SK_EXPERIMENTAL_SHADOWING
     this->validate(fWriter.bytesWritten(), 0);
     // op + scalar
     size_t size = 1 * kUInt32Size + 1 * sizeof(SkScalar);
@@ -226,6 +227,7 @@
     this->addScalar(z);
     this->validate(initialOffset, size);
     this->INHERITED::didTranslateZ(z);
+#endif
 }
 
 static bool regionOpExpands(SkRegion::Op op) {
@@ -672,6 +674,27 @@
     this->validate(initialOffset, size);
 }
 
+void SkPictureRecord::onDrawShadowedPicture(const SkPicture* picture,
+                                            const SkMatrix* matrix,
+                                            const SkPaint* paint) {
+    // op + picture index
+    size_t size = 2 * kUInt32Size;
+    size_t initialOffset;
+
+    if (nullptr == matrix && nullptr == paint) {
+        initialOffset = this->addDraw(DRAW_PICTURE, &size);
+        this->addPicture(picture);
+    } else {
+        const SkMatrix& m = matrix ? *matrix : SkMatrix::I();
+        size += m.writeToMemory(nullptr) + kUInt32Size;    // matrix + paint
+        initialOffset = this->addDraw(DRAW_PICTURE_MATRIX_PAINT, &size);
+        this->addPaintPtr(paint);
+        this->addMatrix(m);
+        this->addPicture(picture);
+    }
+    this->validate(initialOffset, size);
+}
+
 void SkPictureRecord::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
     // op + drawable index
     size_t size = 2 * kUInt32Size;
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 276dd3e..5f51a0e 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -159,7 +159,11 @@
     void didConcat(const SkMatrix&) override;
     void didSetMatrix(const SkMatrix&) override;
 
+#ifdef SK_EXPERIMENTAL_SHADOWING
     void didTranslateZ(SkScalar) override;
+#endif
+    void didTranslateZ(SkScalar);
+#endif
 
     void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
 
@@ -208,6 +212,17 @@
     void onClipRegion(const SkRegion&, SkRegion::Op) override;
 
     void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
+
+#ifdef SK_EXPERIMENTAL_SHADOWING
+    void onDrawShadowedPicture(const SkPicture*,
+                               const SkMatrix*,
+                               const SkPaint*) override;
+#else
+    void onDrawShadowedPicture(const SkPicture*,
+                               const SkMatrix*,
+                               const SkPaint*);
+#endif
+
     void onDrawDrawable(SkDrawable*, const SkMatrix*) override;
     void onDrawAnnotation(const SkRect&, const char[], SkData*) override;
 
@@ -253,5 +268,3 @@
 
     typedef SkCanvas INHERITED;
 };
-
-#endif
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index 02d07d5..cdfce66 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -86,7 +86,11 @@
 DRAW(ClipRect, clipRect(r.rect, r.opAA.op, r.opAA.aa));
 DRAW(ClipRegion, clipRegion(r.region, r.op));
 
+#ifdef SK_EXPERIMENTAL_SHADOWING
 DRAW(TranslateZ, SkCanvas::translateZ(r.z));
+#else
+template <> void Draw::draw(const TranslateZ& r) { }
+#endif
 
 DRAW(DrawBitmap, drawBitmap(r.bitmap.shallowCopy(), r.left, r.top, r.paint));
 DRAW(DrawBitmapNine, drawBitmapNine(r.bitmap.shallowCopy(), r.center, r.dst, r.paint));
@@ -107,6 +111,13 @@
 DRAW(DrawPath, drawPath(r.path, r.paint));
 DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode, r.paint));
 DRAW(DrawPicture, drawPicture(r.picture, &r.matrix, r.paint));
+
+#ifdef SK_EXPERIMENTAL_SHADOWING
+DRAW(DrawShadowedPicture, drawShadowedPicture(r.picture, &r.matrix, r.paint));
+#else
+template <> void Draw::draw(const DrawShadowedPicture& r) { }
+#endif
+
 DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint));
 DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint));
 DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint));
@@ -472,6 +483,12 @@
         return this->adjustAndMap(dst, op.paint);
     }
 
+    Bounds bounds(const DrawShadowedPicture& op) const {
+        SkRect dst = op.picture->cullRect();
+        op.matrix.mapRect(&dst);
+        return this->adjustAndMap(dst, op.paint);
+    }
+
     Bounds bounds(const DrawPosText& op) const {
         const int N = op.paint.countText(op.text, op.byteLength);
         if (N == 0) {
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index c7869bb..76fd3b8 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -305,6 +305,20 @@
     }
 }
 
+void SkRecorder::onDrawShadowedPicture(const SkPicture* pic,
+                                       const SkMatrix* matrix,
+                                       const SkPaint* paint) {
+    if (fDrawPictureMode == Record_DrawPictureMode) {
+        fApproxBytesUsedBySubPictures += SkPictureUtils::ApproximateBytesUsed(pic);
+        APPEND(DrawShadowedPicture, this->copy(paint), pic, matrix ? *matrix : SkMatrix::I());
+    } else {
+        SkASSERT(fDrawPictureMode == Playback_DrawPictureMode);
+        SkAutoCanvasMatrixPaint acmp(this,  matrix, paint, pic->cullRect());
+        pic->playback(this);
+    }
+}
+
+
 void SkRecorder::onDrawVertices(VertexMode vmode,
                                 int vertexCount, const SkPoint vertices[],
                                 const SkPoint texs[], const SkColor colors[],
@@ -369,8 +383,10 @@
     APPEND(SetMatrix, matrix);
 }
 
-void SkRecorder::didTranslateZ(SkScalar z)  {
+void SkRecorder::didTranslateZ(SkScalar z) {
+#ifdef SK_EXPERIMENTAL_SHADOWING
     APPEND(TranslateZ, z);
+#endif
 }
 
 void SkRecorder::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edgeStyle) {
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index 66a0067..5282740 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -60,7 +60,12 @@
 
     void didConcat(const SkMatrix&) override;
     void didSetMatrix(const SkMatrix&) override;
+
+#ifdef SK_EXPERIMENTAL_SHADOWING
     void didTranslateZ(SkScalar) override;
+#else
+    void didTranslateZ(SkScalar);
+#endif
 
     void onDrawDRRect(const SkRRect&, const SkRRect&, const SkPaint&) override;
     void onDrawDrawable(SkDrawable*, const SkMatrix*) override;
@@ -126,6 +131,17 @@
     void onClipRegion(const SkRegion& deviceRgn, SkRegion::Op op) override;
 
     void onDrawPicture(const SkPicture*, const SkMatrix*, const SkPaint*) override;
+
+#ifdef SK_EXPERIMENTAL_SHADOWING
+    void onDrawShadowedPicture(const SkPicture*,
+                               const SkMatrix*,
+                               const SkPaint*) override;
+#else
+    void onDrawShadowedPicture(const SkPicture*,
+                               const SkMatrix*,
+                               const SkPaint*);
+#endif
+
     void onDrawAnnotation(const SkRect&, const char[], SkData*) override;
 
     sk_sp<SkSurface> onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override;