Allow clients to cache sample count and stencil params

Bug: https://github.com/flutter/flutter/issues/117934
Change-Id: I3e5460e4f323e1909a03bd82c5be021db0cb6b06
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/628842
Reviewed-by: Kevin Lubick <kjlubick@google.com>
diff --git a/modules/canvaskit/CHANGELOG.md b/modules/canvaskit/CHANGELOG.md
index 7ed98bc..4a1772f 100644
--- a/modules/canvaskit/CHANGELOG.md
+++ b/modules/canvaskit/CHANGELOG.md
@@ -10,6 +10,8 @@
  - `Paragraph.getRectsForRange` and `Paragraph.getRectsForPlaceholders` had been returning a list
    of Float32Arrays upon which a property 'direction' had been monkey-patched (this was
    undocumented). They now return an object `RectWithDirection`.
+- `CanvasKit.MakeOnScreenGLSurface` allows providing a cached sample count and stencil
+  value to avoid repeated lookups on Surface creation.
 
 ## [0.37.2] - 2022-11-15
 
@@ -257,7 +259,7 @@
 
 ### Added
  - `Font.getGlyphIntercepts()`
- 
+
 ### Fixed
  - Bug with images using certain exif metadata. (skbug.com/11968)
 
@@ -423,7 +425,7 @@
    `CanvasKit.Shader`.
  - `MakeRasterDirectSurface` for giving the user direct access to drawn pixels.
  - `getLineMetrics` to Paragraph.
- - `Canvas.saveLayerPaint` as an experimental, undocumented "fast path" if one only needs to pass 
+ - `Canvas.saveLayerPaint` as an experimental, undocumented "fast path" if one only needs to pass
    the paint.
  - Support for .woff and .woff2 fonts. Disable .woff2 for reduced code size by supplying
    no_woff2 to compile.sh. (This removes the code to do brotli decompression).
diff --git a/modules/canvaskit/canvaskit_bindings.cpp b/modules/canvaskit/canvaskit_bindings.cpp
index a3fb4d8..2e1a3f4 100644
--- a/modules/canvaskit/canvaskit_bindings.cpp
+++ b/modules/canvaskit/canvaskit_bindings.cpp
@@ -187,7 +187,7 @@
 }
 
 sk_sp<SkSurface> MakeOnScreenGLSurface(sk_sp<GrDirectContext> dContext, int width, int height,
-                                       sk_sp<SkColorSpace> colorSpace) {
+                                       sk_sp<SkColorSpace> colorSpace, int sampleCnt, int stencil) {
     // WebGL should already be clearing the color and stencil buffers, but do it again here to
     // ensure Skia receives them in the expected state.
     emscripten_glBindFramebuffer(GL_FRAMEBUFFER, 0);
@@ -200,12 +200,6 @@
     GrGLFramebufferInfo info;
     info.fFBOID = 0;
 
-    GrGLint sampleCnt;
-    emscripten_glGetIntegerv(GL_SAMPLES, &sampleCnt);
-
-    GrGLint stencil;
-    emscripten_glGetIntegerv(GL_STENCIL_BITS, &stencil);
-
     if (!colorSpace) {
         colorSpace = SkColorSpace::MakeSRGB();
     }
@@ -218,6 +212,17 @@
     return surface;
 }
 
+sk_sp<SkSurface> MakeOnScreenGLSurface(sk_sp<GrDirectContext> dContext, int width, int height,
+                                       sk_sp<SkColorSpace> colorSpace) {
+    GrGLint sampleCnt;
+    emscripten_glGetIntegerv(GL_SAMPLES, &sampleCnt);
+
+    GrGLint stencil;
+    emscripten_glGetIntegerv(GL_STENCIL_BITS, &stencil);
+
+    return MakeOnScreenGLSurface(dContext, width, height, colorSpace, sampleCnt, stencil);
+}
+
 sk_sp<SkSurface> MakeRenderTarget(sk_sp<GrDirectContext> dContext, int width, int height) {
     SkImageInfo info = SkImageInfo::MakeN32(
             width, height, SkAlphaType::kPremul_SkAlphaType, SkColorSpace::MakeSRGB());
@@ -919,7 +924,8 @@
 
 #ifdef CK_ENABLE_WEBGL
     constant("webgl", true);
-    function("_MakeOnScreenGLSurface", &MakeOnScreenGLSurface);
+    function("_MakeOnScreenGLSurface", select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, int, int, sk_sp<SkColorSpace>)>(&MakeOnScreenGLSurface));
+    function("_MakeOnScreenGLSurface", select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, int, int, sk_sp<SkColorSpace>, int, int)>(&MakeOnScreenGLSurface));
     function("_MakeRenderTargetWH", select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, int, int)>(&MakeRenderTarget));
     function("_MakeRenderTargetII", select_overload<sk_sp<SkSurface>(sk_sp<GrDirectContext>, SimpleImageInfo)>(&MakeRenderTarget));
 #endif // CK_ENABLE_WEBGL
diff --git a/modules/canvaskit/npm_build/types/canvaskit-wasm-tests.ts b/modules/canvaskit/npm_build/types/canvaskit-wasm-tests.ts
index c97f67a..374a52b 100644
--- a/modules/canvaskit/npm_build/types/canvaskit-wasm-tests.ts
+++ b/modules/canvaskit/npm_build/types/canvaskit-wasm-tests.ts
@@ -952,6 +952,11 @@
     const surfaceNine = CK.MakeOnScreenGLSurface(grCtx!, 100, 400, // $ExpectType Surface
         CK.ColorSpace.ADOBE_RGB)!;
 
+    var sample = gl.getParameter(gl.SAMPLES);
+    var stencil = gl.getParameter(gl.STENCIL_BITS);
+    const surfaceTen = CK.MakeOnScreenGLSurface(grCtx!, 100, 400, // $ExpectType Surface
+        CK.ColorSpace.ADOBE_RGB, sample, stencil)!;
+
     const rt = CK.MakeRenderTarget(grCtx!, 100, 200); // $ExpectType Surface | null
     const rt2 = CK.MakeRenderTarget(grCtx!, { // $ExpectType Surface | null
         width: 79,
diff --git a/modules/canvaskit/npm_build/types/index.d.ts b/modules/canvaskit/npm_build/types/index.d.ts
index 3872f78..29149c7 100644
--- a/modules/canvaskit/npm_build/types/index.d.ts
+++ b/modules/canvaskit/npm_build/types/index.d.ts
@@ -256,9 +256,13 @@
      * @param width - number of pixels of the width of the visible area.
      * @param height - number of pixels of the height of the visible area.
      * @param colorSpace
+     * @param sampleCount - sample count value from GL_SAMPLES. If not provided this will be looked up from
+     *                      the canvas.
+     * @param stencil - stencil count value from GL_STENCIL_BITS. If not provided this will be looked up
+     *                  from the WebGL Context.
      */
     MakeOnScreenGLSurface(ctx: GrDirectContext, width: number, height: number,
-                          colorSpace: ColorSpace): Surface | null;
+                          colorSpace: ColorSpace, sampleCount?: number, stencil?: number): Surface | null;
 
     /**
      * Creates a context that operates over the given WebGPU Device.
diff --git a/modules/canvaskit/tests/core_test.js b/modules/canvaskit/tests/core_test.js
index 1d6ab29..b60d152 100644
--- a/modules/canvaskit/tests/core_test.js
+++ b/modules/canvaskit/tests/core_test.js
@@ -2001,4 +2001,22 @@
         grContext.delete();
         expect(grContext.isDeleted()).toBeTrue();
     });
+
+    it('can provide sample count and stencil parameters to onscreen surface', () => {
+        if (!CanvasKit.webgl) {
+            return SHOULD_SKIP;
+        }
+        const paramCanvas = document.createElement('canvas');
+        const gl = paramCanvas.getContext('webgl');
+        var sample = gl.getParameter(gl.SAMPLES);
+        var stencil = gl.getParameter(gl.STENCIL_BITS);
+
+        const newCanvas = document.createElement('canvas');
+        const ctx = CanvasKit.GetWebGLContext(newCanvas);
+        const grContext = CanvasKit.MakeWebGLContext(ctx);
+        expect(grContext).toBeTruthy();
+
+        var surface =  CanvasKit.MakeOnScreenGLSurface(grContext, 100, 100, CanvasKit.ColorSpace.SRGB, sample, stencil);
+        expect(surface).toBeTruthy();
+    });
 });
diff --git a/modules/canvaskit/webgl.js b/modules/canvaskit/webgl.js
index 47a8f90..4685f2a 100644
--- a/modules/canvaskit/webgl.js
+++ b/modules/canvaskit/webgl.js
@@ -112,11 +112,17 @@
           this._setResourceCacheLimitBytes(maxResourceBytes);
       };
 
-      CanvasKit.MakeOnScreenGLSurface = function(grCtx, w, h, colorspace) {
+      CanvasKit.MakeOnScreenGLSurface = function(grCtx, w, h, colorspace, sc, st) {
         if (!this.setCurrentContext(grCtx._context)) {
           return null;
         }
-        var surface = this._MakeOnScreenGLSurface(grCtx, w, h, colorspace);
+        var surface;
+        // zero is a valid value for sample count or stencil bits.
+        if (sc === undefined || st === undefined) {
+          surface = this._MakeOnScreenGLSurface(grCtx, w, h, colorspace);
+        } else {
+          surface = this._MakeOnScreenGLSurface(grCtx, w, h, colorspace, sc, st);
+        }
         if (!surface) {
           return null;
         }