| // Copyright 2013 The Flutter Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "export.h" | |
| #include "skwasm_support.h" | |
| #include "surface.h" | |
| #include "wrappers.h" | |
| #include "third_party/skia/include/core/SkColorSpace.h" | |
| #include "third_party/skia/include/core/SkData.h" | |
| #include "third_party/skia/include/core/SkImage.h" | |
| #include "third_party/skia/include/core/SkImageInfo.h" | |
| #include "third_party/skia/include/core/SkPicture.h" | |
| #include "third_party/skia/include/gpu/GpuTypes.h" | |
| #include "third_party/skia/include/gpu/GrBackendSurface.h" | |
| #include "third_party/skia/include/gpu/GrDirectContext.h" | |
| #include "third_party/skia/include/gpu/ganesh/GrExternalTextureGenerator.h" | |
| #include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h" | |
| #include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h" | |
| #include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h" | |
| #include "third_party/skia/include/gpu/gl/GrGLInterface.h" | |
| #include "third_party/skia/include/gpu/gl/GrGLTypes.h" | |
| #include <GLES2/gl2.h> | |
| #include <GLES2/gl2ext.h> | |
| #include <emscripten/html5_webgl.h> | |
| using namespace SkImages; | |
| namespace { | |
| enum class PixelFormat { | |
| rgba8888, | |
| bgra8888, | |
| rgbaFloat32, | |
| }; | |
| SkColorType colorTypeForPixelFormat(PixelFormat format) { | |
| switch (format) { | |
| case PixelFormat::rgba8888: | |
| return SkColorType::kRGBA_8888_SkColorType; | |
| case PixelFormat::bgra8888: | |
| return SkColorType::kBGRA_8888_SkColorType; | |
| case PixelFormat::rgbaFloat32: | |
| return SkColorType::kRGBA_F32_SkColorType; | |
| } | |
| } | |
| SkAlphaType alphaTypeForPixelFormat(PixelFormat format) { | |
| switch (format) { | |
| case PixelFormat::rgba8888: | |
| case PixelFormat::bgra8888: | |
| return SkAlphaType::kPremul_SkAlphaType; | |
| case PixelFormat::rgbaFloat32: | |
| return SkAlphaType::kUnpremul_SkAlphaType; | |
| } | |
| } | |
| class ExternalWebGLTexture : public GrExternalTexture { | |
| public: | |
| ExternalWebGLTexture(GrBackendTexture backendTexture, | |
| GLuint textureId, | |
| EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context) | |
| : _backendTexture(backendTexture), | |
| _textureId(textureId), | |
| _webGLContext(context) {} | |
| GrBackendTexture getBackendTexture() override { return _backendTexture; } | |
| void dispose() override { | |
| Skwasm::makeCurrent(_webGLContext); | |
| glDeleteTextures(1, &_textureId); | |
| } | |
| private: | |
| GrBackendTexture _backendTexture; | |
| GLuint _textureId; | |
| EMSCRIPTEN_WEBGL_CONTEXT_HANDLE _webGLContext; | |
| }; | |
| } // namespace | |
| class TextureSourceImageGenerator : public GrExternalTextureGenerator { | |
| public: | |
| TextureSourceImageGenerator(SkImageInfo ii, | |
| SkwasmObject textureSource, | |
| Skwasm::Surface* surface) | |
| : GrExternalTextureGenerator(ii), | |
| _textureSourceWrapper( | |
| surface->createTextureSourceWrapper(textureSource)) {} | |
| std::unique_ptr<GrExternalTexture> generateExternalTexture( | |
| GrRecordingContext* context, | |
| skgpu::Mipmapped mipmapped) override { | |
| GrGLTextureInfo glInfo; | |
| glInfo.fID = skwasm_createGlTextureFromTextureSource( | |
| _textureSourceWrapper->getTextureSource(), fInfo.width(), | |
| fInfo.height()); | |
| glInfo.fFormat = GL_RGBA8_OES; | |
| glInfo.fTarget = GL_TEXTURE_2D; | |
| auto backendTexture = GrBackendTextures::MakeGL( | |
| fInfo.width(), fInfo.height(), mipmapped, glInfo); | |
| // In order to bind the image source to the texture, makeTexture has changed | |
| // which texture is "in focus" for the WebGL context. | |
| GrAsDirectContext(context)->resetContext(kTextureBinding_GrGLBackendState); | |
| return std::make_unique<ExternalWebGLTexture>( | |
| backendTexture, glInfo.fID, emscripten_webgl_get_current_context()); | |
| } | |
| private: | |
| std::unique_ptr<Skwasm::TextureSourceWrapper> _textureSourceWrapper; | |
| }; | |
| SKWASM_EXPORT SkImage* image_createFromPicture(SkPicture* picture, | |
| int32_t width, | |
| int32_t height) { | |
| return DeferredFromPicture(sk_ref_sp<SkPicture>(picture), {width, height}, | |
| nullptr, nullptr, BitDepth::kU8, | |
| SkColorSpace::MakeSRGB()) | |
| .release(); | |
| } | |
| SKWASM_EXPORT SkImage* image_createFromPixels(SkData* data, | |
| int width, | |
| int height, | |
| PixelFormat pixelFormat, | |
| size_t rowByteCount) { | |
| return SkImages::RasterFromData( | |
| SkImageInfo::Make(width, height, | |
| colorTypeForPixelFormat(pixelFormat), | |
| alphaTypeForPixelFormat(pixelFormat), | |
| SkColorSpace::MakeSRGB()), | |
| sk_ref_sp(data), rowByteCount) | |
| .release(); | |
| } | |
| SKWASM_EXPORT SkImage* image_createFromTextureSource(SkwasmObject textureSource, | |
| int width, | |
| int height, | |
| Skwasm::Surface* surface) { | |
| return SkImages::DeferredFromTextureGenerator( | |
| std::unique_ptr<TextureSourceImageGenerator>( | |
| new TextureSourceImageGenerator( | |
| SkImageInfo::Make(width, height, | |
| SkColorType::kRGBA_8888_SkColorType, | |
| SkAlphaType::kPremul_SkAlphaType), | |
| textureSource, surface))) | |
| .release(); | |
| } | |
| SKWASM_EXPORT void image_ref(SkImage* image) { | |
| image->ref(); | |
| } | |
| SKWASM_EXPORT void image_dispose(SkImage* image) { | |
| image->unref(); | |
| } | |
| SKWASM_EXPORT int image_getWidth(SkImage* image) { | |
| return image->width(); | |
| } | |
| SKWASM_EXPORT int image_getHeight(SkImage* image) { | |
| return image->height(); | |
| } |