blob: 9f34ee59f448636b7c7756d3d7768bcd80f61a0a [file] [log] [blame]
Chris Dalton2b598902020-03-25 10:50:35 -06001/*
2 * Copyright 2020 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include <emscripten.h>
9#include <emscripten/bind.h>
Chris Dalton8ce842d2020-04-01 14:46:16 -060010#include "include/core/SkCanvas.h"
Chris Daltone6778f32020-05-27 14:59:16 -060011#include "include/core/SkSurface.h"
12#include "include/gpu/GrContext.h"
Chris Daltonf3242c42020-05-27 17:31:12 -060013#include "tools/viewer/SKPSlide.h"
Chris Dalton2b598902020-03-25 10:50:35 -060014#include "tools/viewer/SampleSlide.h"
Chris Daltone6778f32020-05-27 14:59:16 -060015#include <GLES3/gl3.h>
Chris Dalton2b598902020-03-25 10:50:35 -060016#include <string>
17
18using namespace emscripten;
19
Chris Daltone6778f32020-05-27 14:59:16 -060020sk_sp<Slide> MakeSlide(std::string name) {
21 if (name == "WavyPathText") {
22 extern Sample* MakeWavyPathTextSample();
23 return sk_make_sp<SampleSlide>(MakeWavyPathTextSample);
24 }
25 return nullptr;
26}
27
Chris Daltonf3242c42020-05-27 17:31:12 -060028sk_sp<Slide> MakeSkpSlide(std::string name, std::string skpData) {
29 auto stream = std::make_unique<SkMemoryStream>(skpData.data(), skpData.size(),
30 /*copyData=*/true);
31 return sk_make_sp<SKPSlide>(SkString(name.c_str()), std::move(stream));
32}
33
Chris Daltone6778f32020-05-27 14:59:16 -060034static void delete_wrapped_framebuffer(SkSurface::ReleaseContext context) {
35 GLuint framebuffer = (GLuint)context;
36 glDeleteFramebuffers(1, &framebuffer);
37}
38
39sk_sp<SkSurface> MakeOffscreenFramebuffer(sk_sp<GrContext> grContext, int width, int height,
40 int sampleCnt) {
41 GLuint colorBuffer;
42 glGenRenderbuffers(1, &colorBuffer);
43 glBindRenderbuffer(GL_RENDERBUFFER, colorBuffer);
44 glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCnt, GL_RGBA8, width, height);
45
46 GLuint stencilBuffer;
47 glGenRenderbuffers(1, &stencilBuffer);
48 glBindRenderbuffer(GL_RENDERBUFFER, stencilBuffer);
49 glRenderbufferStorageMultisample(GL_RENDERBUFFER, sampleCnt, GL_STENCIL_INDEX8, width, height);
50
51 GLuint framebuffer;
52 glGenFramebuffers(1, &framebuffer);
53 glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
54 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
55 colorBuffer);
56 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
57 stencilBuffer);
58
59 // Unbind "framebuffer" before orphaning its renderbuffers. (Otherwise they are spec'd to be
60 // detached from the currently bound framebuffer.)
61 glBindFramebuffer(GL_FRAMEBUFFER, 0);
62 glDeleteRenderbuffers(1, &colorBuffer);
63 glDeleteRenderbuffers(1, &stencilBuffer);
64
65 grContext->resetContext(kRenderTarget_GrGLBackendState);
66
67 GrGLFramebufferInfo glInfo;
68 glInfo.fFBOID = framebuffer;
69 glInfo.fFormat = GL_RGBA8;
70 GrBackendRenderTarget backendRenderTarget(width, height, sampleCnt, 8, glInfo);
71 return SkSurface::MakeFromBackendRenderTarget(grContext.get(), backendRenderTarget,
72 kBottomLeft_GrSurfaceOrigin,
73 SkColorType::kRGBA_8888_SkColorType, nullptr,
74 nullptr, &delete_wrapped_framebuffer,
75 (SkSurface::ReleaseContext)framebuffer);
76}
77
78enum class GLFilter {
79 kNearest = GL_NEAREST,
80 kLinear = GL_LINEAR
81};
82
83void BlitOffscreenFramebuffer(sk_sp<SkSurface> surface, int srcX0, int srcY0, int srcX1, int srcY1,
84 int dstX0, int dstY0, int dstX1, int dstY1, GLFilter filter) {
85 surface->flush(SkSurface::BackendSurfaceAccess::kPresent, GrFlushInfo());
86 GrGLFramebufferInfo glInfo;
87 auto backendRT = surface->getBackendRenderTarget(SkSurface::kFlushRead_BackendHandleAccess);
88 backendRT.getGLFramebufferInfo(&glInfo);
89 glBindFramebuffer(GL_READ_FRAMEBUFFER, glInfo.fFBOID);
90 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
91 glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, GL_COLOR_BUFFER_BIT,
92 (GLenum)filter);
93 surface->getContext()->resetContext(kRenderTarget_GrGLBackendState);
94}
95
Chris Dalton2b598902020-03-25 10:50:35 -060096EMSCRIPTEN_BINDINGS(Viewer) {
Chris Daltone6778f32020-05-27 14:59:16 -060097 function("MakeSlide", &MakeSlide);
Chris Daltonf3242c42020-05-27 17:31:12 -060098 function("MakeSkpSlide", &MakeSkpSlide);
Chris Daltone6778f32020-05-27 14:59:16 -060099 function("MakeOffscreenFramebuffer", &MakeOffscreenFramebuffer);
100 function("BlitOffscreenFramebuffer", &BlitOffscreenFramebuffer);
Chris Dalton2b598902020-03-25 10:50:35 -0600101 class_<Slide>("Slide")
102 .smart_ptr<sk_sp<Slide>>("sk_sp<Slide>")
103 .function("load", &Slide::load)
104 .function("animate", &Slide::animate)
105 .function("draw", optional_override([](Slide& self, SkCanvas& canvas) {
106 self.draw(&canvas);
107 }));
Chris Daltone6778f32020-05-27 14:59:16 -0600108 enum_<GLFilter>("GLFilter")
109 .value("Nearest", GLFilter::kNearest)
110 .value("Linear", GLFilter::kLinear);
Chris Dalton2b598902020-03-25 10:50:35 -0600111}