@shopify/react-native-skia 1.5.4 → 1.5.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -54,7 +54,7 @@ if(SK_GRAPHITE)
54
54
  else()
55
55
  add_definitions(-DSK_GL -DSK_GANESH)
56
56
  set(BACKEND_SOURCES
57
- "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.cpp"
57
+ "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/OpenGLWindowContext.cpp"
58
58
  "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/GrAHardwareBufferUtils.cpp"
59
59
  )
60
60
  endif()
@@ -74,6 +74,7 @@ add_library(
74
74
  "${PROJECT_SOURCE_DIR}/cpp/jni/JniSkiaManager.cpp"
75
75
 
76
76
  "${PROJECT_SOURCE_DIR}/cpp/jni/JniPlatformContext.cpp"
77
+ "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/opengl/Error.cpp"
77
78
  "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp"
78
79
  "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/AHardwareBufferUtils.cpp"
79
80
  "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkAndroidVideo.cpp"
@@ -1,9 +1,18 @@
1
1
  #pragma once
2
2
 
3
- #include "SkiaOpenGLSurfaceFactory.h"
4
- #include "WindowContext.h"
3
+ #include "GrAHardwareBufferUtils.h"
4
+ #include "OpenGLWindowContext.h"
5
+ #include "opengl/Display.h"
5
6
 
7
+ #include "include/core/SkCanvas.h"
8
+ #include "include/core/SkColorSpace.h"
6
9
  #include "include/core/SkSurface.h"
10
+ #include "include/gpu/ganesh/GrDirectContext.h"
11
+ #include "include/gpu/ganesh/SkImageGanesh.h"
12
+ #include "include/gpu/ganesh/gl/GrGLBackendSurface.h"
13
+ #include "include/gpu/ganesh/gl/GrGLDirectContext.h"
14
+ #include "include/gpu/ganesh/gl/GrGLInterface.h"
15
+ #include "src/gpu/ganesh/gl/GrGLDefines.h"
7
16
 
8
17
  class OpenGLContext {
9
18
  public:
@@ -16,25 +25,127 @@ public:
16
25
  }
17
26
 
18
27
  sk_sp<SkSurface> MakeOffscreen(int width, int height) {
19
- return RNSkia::SkiaOpenGLSurfaceFactory::makeOffscreenSurface(
20
- &_context, width, height);
28
+ auto colorType = kRGBA_8888_SkColorType;
29
+
30
+ SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
31
+
32
+ auto result = _ctx->makeCurrent(*_surface);
33
+ if (!result) {
34
+ return nullptr;
35
+ }
36
+
37
+ // Create texture
38
+ auto texture = _directContext->createBackendTexture(
39
+ width, height, colorType, skgpu::Mipmapped::kNo, GrRenderable::kYes);
40
+
41
+ if (!texture.isValid()) {
42
+ RNSkia::RNSkLogger::logToConsole(
43
+ "couldn't create offscreen texture %dx%d", width, height);
44
+ }
45
+
46
+ struct ReleaseContext {
47
+ GrDirectContext *directContext;
48
+ GrBackendTexture texture;
49
+ };
50
+
51
+ auto releaseCtx = new ReleaseContext{.directContext = _directContext.get(),
52
+ .texture = texture};
53
+
54
+ // Create a SkSurface from the GrBackendTexture
55
+ return SkSurfaces::WrapBackendTexture(
56
+ _directContext.get(), texture, kTopLeft_GrSurfaceOrigin, 0, colorType,
57
+ nullptr, &props,
58
+ [](void *addr) {
59
+ auto releaseCtx = reinterpret_cast<ReleaseContext *>(addr);
60
+ releaseCtx->directContext->deleteBackendTexture(releaseCtx->texture);
61
+ delete releaseCtx;
62
+ },
63
+ releaseCtx);
21
64
  }
22
65
 
23
- sk_sp<SkImage> MakeImageFromBuffer(void *buffer) {
24
- return RNSkia::SkiaOpenGLSurfaceFactory::makeImageFromHardwareBuffer(
25
- &_context, buffer);
66
+ sk_sp<SkImage> MakeImageFromBuffer(void *buffer,
67
+ bool requireKnownFormat = false) {
68
+ #if __ANDROID_API__ >= 26
69
+ const AHardwareBuffer *hardwareBuffer =
70
+ static_cast<AHardwareBuffer *>(buffer);
71
+ RNSkia::DeleteImageProc deleteImageProc = nullptr;
72
+ RNSkia::UpdateImageProc updateImageProc = nullptr;
73
+ RNSkia::TexImageCtx deleteImageCtx = nullptr;
74
+
75
+ AHardwareBuffer_Desc description;
76
+ AHardwareBuffer_describe(hardwareBuffer, &description);
77
+ GrBackendFormat format;
78
+ switch (description.format) {
79
+ // TODO: find out if we can detect, which graphic buffers support
80
+ // GR_GL_TEXTURE_2D
81
+ case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
82
+ format = GrBackendFormats::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
83
+ case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
84
+ format = GrBackendFormats::MakeGL(GR_GL_RGBA16F, GR_GL_TEXTURE_EXTERNAL);
85
+ case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
86
+ format = GrBackendFormats::MakeGL(GR_GL_RGB565, GR_GL_TEXTURE_EXTERNAL);
87
+ case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
88
+ format = GrBackendFormats::MakeGL(GR_GL_RGB10_A2, GR_GL_TEXTURE_EXTERNAL);
89
+ case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
90
+ format = GrBackendFormats::MakeGL(GR_GL_RGB8, GR_GL_TEXTURE_EXTERNAL);
91
+ #if __ANDROID_API__ >= 33
92
+ case AHARDWAREBUFFER_FORMAT_R8_UNORM:
93
+ format = GrBackendFormats::MakeGL(GR_GL_R8, GR_GL_TEXTURE_EXTERNAL);
94
+ #endif
95
+ default:
96
+ if (requireKnownFormat) {
97
+ format = GrBackendFormat();
98
+ } else {
99
+ format = GrBackendFormats::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
100
+ }
101
+ }
102
+
103
+ auto backendTex = RNSkia::MakeGLBackendTexture(
104
+ _directContext.get(), const_cast<AHardwareBuffer *>(hardwareBuffer),
105
+ description.width, description.height, &deleteImageProc,
106
+ &updateImageProc, &deleteImageCtx, false, format, false);
107
+ if (!backendTex.isValid()) {
108
+ RNSkia::RNSkLogger::logToConsole(
109
+ "Failed to convert HardwareBuffer to OpenGL Texture!");
110
+ return nullptr;
111
+ }
112
+ sk_sp<SkImage> image = SkImages::BorrowTextureFrom(
113
+ _directContext.get(), backendTex, kTopLeft_GrSurfaceOrigin,
114
+ kRGBA_8888_SkColorType, kOpaque_SkAlphaType, nullptr, deleteImageProc,
115
+ deleteImageCtx);
116
+ return image;
117
+ #else
118
+ throw std::runtime_error(
119
+ "HardwareBuffers are only supported on Android API 26 or higher! Set "
120
+ "your minSdk to 26 (or higher) and try again.");
121
+ #endif
26
122
  }
27
123
 
28
124
  std::unique_ptr<RNSkia::WindowContext> MakeWindow(ANativeWindow *window,
29
125
  int width, int height) {
30
- return RNSkia::SkiaOpenGLSurfaceFactory::makeContext(&_context, window,
31
- width, height);
126
+ return std::make_unique<RNSkia::OpenGLWindowContext>(
127
+ _config, _display.get(), _ctx.get(), _directContext.get(), window,
128
+ width, height);
32
129
  }
33
130
 
34
131
  private:
35
- RNSkia::SkiaOpenGLContext _context;
132
+ EGLConfig _config;
133
+ std::unique_ptr<RNSkia::Display> _display;
134
+ std::unique_ptr<RNSkia::Context> _ctx;
135
+ std::unique_ptr<RNSkia::Surface> _surface;
136
+ sk_sp<GrDirectContext> _directContext;
36
137
 
37
138
  OpenGLContext() {
38
- RNSkia::SkiaOpenGLHelper::createSkiaDirectContextIfNecessary(&_context);
139
+ _display = std::make_unique<RNSkia::Display>();
140
+ _config = _display->chooseConfig();
141
+ _ctx = _display->makeContext(_config, nullptr);
142
+ _surface = _display->makePixelBufferSurface(_config, 1, 1);
143
+ _ctx->makeCurrent(*_surface);
144
+ auto backendInterface = GrGLMakeNativeInterface();
145
+ _directContext = GrDirectContexts::MakeGL(backendInterface);
146
+
147
+ if (_directContext == nullptr) {
148
+ throw std::runtime_error("GrDirectContexts::MakeGL failed");
149
+ }
39
150
  }
40
151
  };
@@ -0,0 +1,73 @@
1
+ #include "OpenGLWindowContext.h"
2
+ #include "GrAHardwareBufferUtils.h"
3
+
4
+ #pragma clang diagnostic push
5
+ #pragma clang diagnostic ignored "-Wdocumentation"
6
+
7
+ #include "include/gpu/ganesh/SkImageGanesh.h"
8
+ #include "include/gpu/ganesh/gl/GrGLBackendSurface.h"
9
+ #include "src/gpu/ganesh/gl/GrGLDefines.h"
10
+
11
+ #pragma clang diagnostic pop
12
+
13
+ namespace RNSkia {
14
+
15
+ sk_sp<SkSurface> OpenGLWindowContext::getSurface() {
16
+ if (_skSurface == nullptr) {
17
+
18
+ struct ReleaseContext {
19
+ std::unique_ptr<Surface> surface = nullptr;
20
+ };
21
+
22
+ auto releaseCtx = new ReleaseContext();
23
+ releaseCtx->surface = _display->makeWindowSurface(_config, _window);
24
+ _surface = releaseCtx->surface.get();
25
+
26
+ // Now make this one current
27
+ _context->makeCurrent(*releaseCtx->surface);
28
+
29
+ // Set up parameters for the render target so that it
30
+ // matches the underlying OpenGL context.
31
+ GrGLFramebufferInfo fboInfo;
32
+
33
+ // We pass 0 as the framebuffer id, since the
34
+ // underlying Skia GrGlGpu will read this when wrapping the context in the
35
+ // render target and the GrGlGpu object.
36
+ fboInfo.fFBOID = 0;
37
+ fboInfo.fFormat = 0x8058; // GL_RGBA8
38
+
39
+ GLint stencil;
40
+ glGetIntegerv(GL_STENCIL_BITS, &stencil);
41
+
42
+ GLint samples;
43
+ glGetIntegerv(GL_SAMPLES, &samples);
44
+
45
+ auto colorType = kN32_SkColorType;
46
+
47
+ auto maxSamples =
48
+ _directContext->maxSurfaceSampleCountForColorType(colorType);
49
+
50
+ if (samples > maxSamples) {
51
+ samples = maxSamples;
52
+ }
53
+
54
+ auto renderTarget = GrBackendRenderTargets::MakeGL(_width, _height, samples,
55
+ stencil, fboInfo);
56
+
57
+ SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
58
+
59
+
60
+ // Create surface object
61
+ _skSurface = SkSurfaces::WrapBackendRenderTarget(
62
+ _directContext, renderTarget, kBottomLeft_GrSurfaceOrigin, colorType,
63
+ nullptr, &props,
64
+ [](void *addr) {
65
+ auto releaseCtx = reinterpret_cast<ReleaseContext *>(addr);
66
+ delete releaseCtx;
67
+ },
68
+ reinterpret_cast<void *>(releaseCtx));
69
+ }
70
+ return _skSurface;
71
+ }
72
+
73
+ } // namespace RNSkia
@@ -0,0 +1,74 @@
1
+ #pragma once
2
+
3
+ #include "RNSkLog.h"
4
+
5
+ #include <fbjni/fbjni.h>
6
+ #include <jni.h>
7
+
8
+ #include <android/native_window_jni.h>
9
+ #include <android/surface_texture.h>
10
+ #include <android/surface_texture_jni.h>
11
+ #include <condition_variable>
12
+ #include <memory>
13
+ #include <thread>
14
+ #include <unordered_map>
15
+
16
+ #include "WindowContext.h"
17
+ #include "opengl/Display.h"
18
+
19
+ #pragma clang diagnostic push
20
+ #pragma clang diagnostic ignored "-Wdocumentation"
21
+
22
+ #include "include/core/SkCanvas.h"
23
+ #include "include/core/SkColorSpace.h"
24
+ #include "include/core/SkSurface.h"
25
+ #include "include/gpu/ganesh/GrBackendSurface.h"
26
+ #include "include/gpu/ganesh/GrDirectContext.h"
27
+ #include "include/gpu/ganesh/SkSurfaceGanesh.h"
28
+ #include "include/gpu/ganesh/gl/GrGLInterface.h"
29
+
30
+ #pragma clang diagnostic pop
31
+
32
+ namespace RNSkia {
33
+
34
+ class OpenGLWindowContext : public WindowContext {
35
+ public:
36
+ OpenGLWindowContext(EGLConfig &config, Display *display, Context *context,
37
+ GrDirectContext *directContext, ANativeWindow *window,
38
+ int width, int height)
39
+ : _config(config), _display(display), _directContext(directContext),
40
+ _context(context), _window(window), _width(width), _height(height) {}
41
+
42
+ ~OpenGLWindowContext() { ANativeWindow_release(_window); }
43
+
44
+ sk_sp<SkSurface> getSurface() override;
45
+
46
+ void present() override {
47
+ _context->makeCurrent(*_surface);
48
+ _directContext->flushAndSubmit();
49
+ _surface->Present();
50
+ }
51
+
52
+ void resize(int width, int height) override {
53
+ _skSurface = nullptr;
54
+ _width = width;
55
+ _height = height;
56
+ }
57
+
58
+ int getWidth() override { return _width; };
59
+
60
+ int getHeight() override { return _height; };
61
+
62
+ private:
63
+ ANativeWindow *_window;
64
+ sk_sp<SkSurface> _skSurface = nullptr;
65
+ EGLConfig _config;
66
+ Context *_context;
67
+ Surface* _surface;
68
+ Display *_display;
69
+ GrDirectContext *_directContext;
70
+ int _width = 0;
71
+ int _height = 0;
72
+ };
73
+
74
+ } // namespace RNSkia
@@ -71,7 +71,6 @@ bool RNSkOpenGLCanvasProvider::renderToCanvas(
71
71
  return false;
72
72
  }
73
73
  }
74
-
75
74
  return false;
76
75
  }
77
76
 
@@ -0,0 +1,77 @@
1
+ #pragma once
2
+
3
+ #include "opengl/Error.h"
4
+ #include "opengl/Surface.h"
5
+
6
+ namespace RNSkia {
7
+
8
+ class Surface;
9
+ class Display;
10
+
11
+ class Context {
12
+ public:
13
+ ~Context() {
14
+ if (_context != EGL_NO_CONTEXT) {
15
+ if (eglDestroyContext(_display, _context) != EGL_TRUE) {
16
+ LOG_EGL_ERROR;
17
+ }
18
+ }
19
+ }
20
+
21
+ bool isValid() const { return _context != EGL_NO_CONTEXT; }
22
+
23
+ const EGLContext &getHandle() const { return _context; }
24
+
25
+ bool makeCurrent(const Surface &surface) const {
26
+ if (_context == EGL_NO_CONTEXT) {
27
+ return false;
28
+ }
29
+ const auto result =
30
+ eglMakeCurrentIfNecessary(_display, surface.getHandle(),
31
+ surface.getHandle(), _context) == EGL_TRUE;
32
+ if (!result) {
33
+ LOG_EGL_ERROR;
34
+ }
35
+ return result;
36
+ }
37
+
38
+ bool clearCurrent() const {
39
+ const auto result =
40
+ eglMakeCurrentIfNecessary(_display, EGL_NO_SURFACE, EGL_NO_SURFACE,
41
+ EGL_NO_CONTEXT) == EGL_TRUE;
42
+ if (!result) {
43
+ LOG_EGL_ERROR;
44
+ }
45
+ return result;
46
+ }
47
+
48
+ bool isCurrent() const { return eglGetCurrentContext() == _context; }
49
+
50
+ private:
51
+ friend class Display;
52
+
53
+ EGLDisplay _display = EGL_NO_DISPLAY;
54
+ EGLContext _context = EGL_NO_CONTEXT;
55
+
56
+ static EGLBoolean eglMakeCurrentIfNecessary(EGLDisplay display,
57
+ EGLSurface draw, EGLSurface read,
58
+ EGLContext context) {
59
+ if (display != eglGetCurrentDisplay() ||
60
+ draw != eglGetCurrentSurface(EGL_DRAW) ||
61
+ read != eglGetCurrentSurface(EGL_READ) ||
62
+ context != eglGetCurrentContext()) {
63
+ return eglMakeCurrent(display, draw, read, context);
64
+ }
65
+
66
+ return EGL_TRUE;
67
+ }
68
+
69
+ Context(EGLDisplay display, EGLContext context)
70
+ : _display(display), _context(context) {}
71
+
72
+ Context(const Context &) = delete;
73
+
74
+ Context &operator=(const Context &) = delete;
75
+ };
76
+
77
+ } // namespace RNSkia
@@ -0,0 +1,117 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+
5
+ #include "EGL/egl.h"
6
+ #include "GLES2/gl2.h"
7
+
8
+ #include "opengl/Context.h"
9
+ #include "opengl/Error.h"
10
+
11
+ namespace RNSkia {
12
+
13
+ class Context;
14
+ class Surface;
15
+
16
+ class Display {
17
+ public:
18
+ Display() {
19
+ EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
20
+
21
+ if (eglInitialize(display, nullptr, nullptr) != EGL_TRUE) {
22
+ LOG_EGL_ERROR;
23
+ return;
24
+ }
25
+ _display = display;
26
+ }
27
+
28
+ ~Display() {
29
+ if (_display != EGL_NO_DISPLAY) {
30
+ if (eglTerminate(_display) != EGL_TRUE) {
31
+ LOG_EGL_ERROR;
32
+ }
33
+ }
34
+ }
35
+
36
+ bool isValid() const { return _display != EGL_NO_DISPLAY; }
37
+
38
+ EGLConfig chooseConfig() const {
39
+
40
+ EGLint att[] = {EGL_RENDERABLE_TYPE,
41
+ EGL_OPENGL_ES2_BIT,
42
+ EGL_ALPHA_SIZE,
43
+ 8,
44
+ EGL_BLUE_SIZE,
45
+ 8,
46
+ EGL_GREEN_SIZE,
47
+ 8,
48
+ EGL_RED_SIZE,
49
+ 8,
50
+ EGL_DEPTH_SIZE,
51
+ 0,
52
+ EGL_STENCIL_SIZE,
53
+ 0,
54
+ EGL_SAMPLE_BUFFERS,
55
+ 0,
56
+ EGL_NONE};
57
+
58
+ EGLint numConfigs;
59
+ EGLConfig glConfig = 0;
60
+ if (eglChooseConfig(_display, att, &glConfig, 1, &numConfigs) != EGL_TRUE ||
61
+ numConfigs == 0) {
62
+ LOG_EGL_ERROR;
63
+ return 0;
64
+ }
65
+
66
+ return glConfig;
67
+ }
68
+
69
+ std::unique_ptr<Context> makeContext(const EGLConfig &config,
70
+ const Context *share_context) {
71
+ EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
72
+ auto context = eglCreateContext(
73
+ _display, config,
74
+ share_context != nullptr ? share_context->getHandle() : nullptr,
75
+ contextAttribs);
76
+
77
+ if (context == EGL_NO_CONTEXT) {
78
+ LOG_EGL_ERROR;
79
+ return nullptr;
80
+ }
81
+ return std::unique_ptr<Context>(new Context(_display, context));
82
+ }
83
+
84
+ std::unique_ptr<Surface> makeWindowSurface(const EGLConfig &config,
85
+ EGLNativeWindowType window) {
86
+ const EGLint attribs[] = {EGL_NONE};
87
+ auto surface = eglCreateWindowSurface(_display, config, window, attribs);
88
+ if (surface == EGL_NO_SURFACE) {
89
+ LOG_EGL_ERROR;
90
+ return nullptr;
91
+ }
92
+ return std::unique_ptr<Surface>(new Surface(_display, surface));
93
+ }
94
+
95
+ std::unique_ptr<Surface> makePixelBufferSurface(const EGLConfig &config,
96
+ size_t width, size_t height) {
97
+ const EGLint attribs[] = {EGL_WIDTH, static_cast<EGLint>(width), EGL_HEIGHT,
98
+ static_cast<EGLint>(height), EGL_NONE};
99
+ auto surface = eglCreatePbufferSurface(_display, config, attribs);
100
+ if (surface == EGL_NO_SURFACE) {
101
+ LOG_EGL_ERROR;
102
+ return nullptr;
103
+ }
104
+ return std::unique_ptr<Surface>(new Surface(_display, surface));
105
+ }
106
+
107
+ const EGLDisplay &getHandle() const { return _display; }
108
+
109
+ private:
110
+ EGLDisplay _display = EGL_NO_DISPLAY;
111
+
112
+ Display(const Display &) = delete;
113
+
114
+ Display &operator=(const Display &) = delete;
115
+ };
116
+
117
+ } // namespace RNSkia
@@ -0,0 +1,9 @@
1
+ #include "opengl/Error.h"
2
+
3
+ #include "RNSkLog.h"
4
+
5
+ void LogEGLError(const char *file, int line) {
6
+ const auto error = eglGetError();
7
+ RNSkia::RNSkLogger::logToConsole("EGL Error: %s (%d) in %s:%d",
8
+ EGLErrorToString(error), error, file, line);
9
+ }
@@ -0,0 +1,44 @@
1
+ #pragma once
2
+
3
+ #include "EGL/egl.h"
4
+ #include "GLES2/gl2.h"
5
+
6
+ #define LOG_EGL_ERROR LogEGLError(__FILE__, __LINE__);
7
+
8
+ static const char *EGLErrorToString(EGLint error) {
9
+ switch (error) {
10
+ case EGL_SUCCESS:
11
+ return "Success";
12
+ case EGL_NOT_INITIALIZED:
13
+ return "Not Initialized";
14
+ case EGL_BAD_ACCESS:
15
+ return "Bad Access";
16
+ case EGL_BAD_ALLOC:
17
+ return "Bad Alloc";
18
+ case EGL_BAD_ATTRIBUTE:
19
+ return "Bad Attribute";
20
+ case EGL_BAD_CONTEXT:
21
+ return "Bad Context";
22
+ case EGL_BAD_CONFIG:
23
+ return "Bad Config";
24
+ case EGL_BAD_CURRENT_SURFACE:
25
+ return "Bad Current Surface";
26
+ case EGL_BAD_DISPLAY:
27
+ return "Bad Display";
28
+ case EGL_BAD_SURFACE:
29
+ return "Bad Surface";
30
+ case EGL_BAD_MATCH:
31
+ return "Bad Match";
32
+ case EGL_BAD_PARAMETER:
33
+ return "Bad Parameter";
34
+ case EGL_BAD_NATIVE_PIXMAP:
35
+ return "Bad Native Pixmap";
36
+ case EGL_BAD_NATIVE_WINDOW:
37
+ return "Bad Native Window";
38
+ case EGL_CONTEXT_LOST:
39
+ return "Context Lost";
40
+ }
41
+ return "Unknown";
42
+ }
43
+
44
+ void LogEGLError(const char *file, int line);
@@ -0,0 +1,43 @@
1
+ #pragma once
2
+
3
+ #include "opengl/Error.h"
4
+
5
+ namespace RNSkia {
6
+
7
+ class Surface {
8
+ public:
9
+ ~Surface() {
10
+ if (_surface != EGL_NO_SURFACE) {
11
+ if (eglDestroySurface(_display, _surface) != EGL_TRUE) {
12
+ LOG_EGL_ERROR;
13
+ }
14
+ }
15
+ }
16
+
17
+ bool isValid() { return _surface != EGL_NO_SURFACE; }
18
+
19
+ const EGLSurface &getHandle() const { return _surface; }
20
+
21
+ bool Present() const {
22
+ const auto result = eglSwapBuffers(_display, _surface) == EGL_TRUE;
23
+ if (!result) {
24
+ LOG_EGL_ERROR;
25
+ }
26
+ return result;
27
+ }
28
+
29
+ private:
30
+ friend class Display;
31
+
32
+ EGLDisplay _display = EGL_NO_DISPLAY;
33
+ EGLSurface _surface = EGL_NO_SURFACE;
34
+
35
+ Surface(EGLDisplay display, EGLSurface surface)
36
+ : _display(display), _surface(surface) {}
37
+
38
+ Surface(const Surface &) = delete;
39
+
40
+ Surface &operator=(const Surface &) = delete;
41
+ };
42
+
43
+ } // Namespace RNSkia
@@ -23,16 +23,12 @@
23
23
  #include <TargetConditionals.h>
24
24
  #if TARGET_RT_BIG_ENDIAN
25
25
  #define FourCC2Str(fourcc) \
26
- (const char[]) { \
27
- *((char *)&fourcc), *(((char *)&fourcc) + 1), *(((char *)&fourcc) + 2), \
28
- *(((char *)&fourcc) + 3), 0 \
29
- }
26
+ (const char[]){*((char *)&fourcc), *(((char *)&fourcc) + 1), \
27
+ *(((char *)&fourcc) + 2), *(((char *)&fourcc) + 3), 0}
30
28
  #else
31
29
  #define FourCC2Str(fourcc) \
32
- (const char[]) { \
33
- *(((char *)&fourcc) + 3), *(((char *)&fourcc) + 2), \
34
- *(((char *)&fourcc) + 1), *(((char *)&fourcc) + 0), 0 \
35
- }
30
+ (const char[]){*(((char *)&fourcc) + 3), *(((char *)&fourcc) + 2), \
31
+ *(((char *)&fourcc) + 1), *(((char *)&fourcc) + 0), 0}
36
32
  #endif
37
33
 
38
34
  // pragma MARK: TextureHolder
@@ -109,9 +109,13 @@ public:
109
109
 
110
110
  void resize(int width, int height) override { _skSurface = nullptr; }
111
111
 
112
- int getWidth() override { return _layer.frame.size.width * _layer.contentsScale; };
112
+ int getWidth() override {
113
+ return _layer.frame.size.width * _layer.contentsScale;
114
+ };
113
115
 
114
- int getHeight() override { return _layer.frame.size.height * _layer.contentsScale; };
116
+ int getHeight() override {
117
+ return _layer.frame.size.height * _layer.contentsScale;
118
+ };
115
119
 
116
120
  private:
117
121
  SkiaMetalContext *_context;
package/package.json CHANGED
@@ -7,7 +7,7 @@
7
7
  "setup-skia-web": "./scripts/setup-canvaskit.js"
8
8
  },
9
9
  "title": "React Native Skia",
10
- "version": "1.5.4",
10
+ "version": "1.5.5",
11
11
  "description": "High-performance React Native Graphics using Skia",
12
12
  "main": "lib/module/index.js",
13
13
  "react-native": "src/index.ts",
@@ -1,310 +0,0 @@
1
- #pragma once
2
-
3
- #include "EGL/egl.h"
4
- #include "GLES2/gl2.h"
5
- #include <fbjni/fbjni.h>
6
- #include <jni.h>
7
-
8
- #include <atomic>
9
-
10
- #include "RNSkLog.h"
11
-
12
- #pragma clang diagnostic push
13
- #pragma clang diagnostic ignored "-Wdocumentation"
14
-
15
- #include "include/core/SkCanvas.h"
16
- #include "include/core/SkColorSpace.h"
17
- #include "include/core/SkSurface.h"
18
- #include "include/gpu/ganesh/GrDirectContext.h"
19
- #include "include/gpu/ganesh/gl/GrGLDirectContext.h"
20
- #include "include/gpu/ganesh/gl/GrGLInterface.h"
21
-
22
- #pragma clang diagnostic pop
23
-
24
- namespace RNSkia {
25
-
26
- /**
27
- * Singleton holding the default display and shared eglContext that will be the
28
- * first context we create so that we can share data between contexts.
29
- */
30
- class OpenGLResourceHolder {
31
- private:
32
- OpenGLResourceHolder() {
33
- // Initialize OpenGL
34
- glDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
35
- if (glDisplay == EGL_NO_DISPLAY) {
36
- RNSkLogger::logToConsole("eglGetDisplay failed : %i", glGetError());
37
- return;
38
- }
39
-
40
- EGLint major;
41
- EGLint minor;
42
- if (eglInitialize(glDisplay, &major, &minor) != EGL_TRUE) {
43
- RNSkLogger::logToConsole("eglInitialize failed : %i", glGetError());
44
- return;
45
- }
46
-
47
- // Create a default shared context
48
- glConfig = getConfig(glDisplay);
49
-
50
- // Create OpenGL context attributes
51
- EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
52
-
53
- // Initialize the offscreen context for this thread
54
- glContext =
55
- eglCreateContext(glDisplay, glConfig, glContext, contextAttribs);
56
- if (glContext == EGL_NO_CONTEXT) {
57
- RNSkLogger::logToConsole("eglCreateContext failed : %i", glGetError());
58
- }
59
- }
60
-
61
- ~OpenGLResourceHolder() {
62
- if (glContext != EGL_NO_CONTEXT) {
63
- eglDestroyContext(glDisplay, glContext);
64
- glContext = EGL_NO_CONTEXT;
65
- }
66
-
67
- if (glDisplay != EGL_NO_DISPLAY) {
68
- eglTerminate(glDisplay);
69
- glDisplay = EGL_NO_DISPLAY;
70
- }
71
- }
72
- /* Explicitly disallow copying. */
73
- OpenGLResourceHolder(const OpenGLResourceHolder &) = delete;
74
- OpenGLResourceHolder &operator=(const OpenGLResourceHolder &) = delete;
75
-
76
- public:
77
- static OpenGLResourceHolder &getInstance() {
78
- static OpenGLResourceHolder Instance;
79
- return Instance;
80
- }
81
-
82
- /**
83
- * The first context created will be considered the parent / shared context
84
- * and will be used as the parent / shareable context when creating subsequent
85
- * contexts.
86
- */
87
- std::atomic<EGLContext> glContext = EGL_NO_CONTEXT;
88
- /**
89
- * Shared egl display
90
- */
91
- std::atomic<EGLDisplay> glDisplay = EGL_NO_DISPLAY;
92
-
93
- /**
94
- * Shared eglConfig
95
- */
96
- std::atomic<EGLConfig> glConfig = 0;
97
-
98
- private:
99
- /**
100
- * Finds the correct EGL Config for the given parameters
101
- * @param glDisplay
102
- * @return Config or zero if no matching context could be found.
103
- */
104
- static EGLConfig getConfig(EGLDisplay glDisplay) {
105
-
106
- EGLint att[] = {EGL_RENDERABLE_TYPE,
107
- EGL_OPENGL_ES2_BIT,
108
- EGL_ALPHA_SIZE,
109
- 8,
110
- EGL_BLUE_SIZE,
111
- 8,
112
- EGL_GREEN_SIZE,
113
- 8,
114
- EGL_RED_SIZE,
115
- 8,
116
- EGL_DEPTH_SIZE,
117
- 0,
118
- EGL_STENCIL_SIZE,
119
- 0,
120
- EGL_SAMPLE_BUFFERS,
121
- 0,
122
- EGL_NONE};
123
-
124
- EGLint numConfigs;
125
- EGLConfig glConfig = 0;
126
- if (eglChooseConfig(glDisplay, att, &glConfig, 1, &numConfigs) !=
127
- EGL_TRUE ||
128
- numConfigs == 0) {
129
- RNSkLogger::logToConsole(
130
- "Failed to choose a config for %s surface. Error code: %d\n",
131
- eglGetError());
132
- return 0;
133
- }
134
-
135
- return glConfig;
136
- }
137
- };
138
-
139
- struct SkiaOpenGLContext {
140
- SkiaOpenGLContext() {
141
- glContext = EGL_NO_CONTEXT;
142
- gl1x1Surface = EGL_NO_SURFACE;
143
- directContext = nullptr;
144
- }
145
- ~SkiaOpenGLContext() {
146
- if (gl1x1Surface != EGL_NO_SURFACE) {
147
- eglDestroySurface(OpenGLResourceHolder::getInstance().glDisplay,
148
- gl1x1Surface);
149
- gl1x1Surface = EGL_NO_SURFACE;
150
- }
151
-
152
- if (directContext) {
153
- directContext->releaseResourcesAndAbandonContext();
154
- directContext = nullptr;
155
- }
156
-
157
- if (glContext != EGL_NO_CONTEXT) {
158
- eglDestroyContext(OpenGLResourceHolder::getInstance().glDisplay,
159
- glContext);
160
- glContext = EGL_NO_CONTEXT;
161
- }
162
- }
163
- EGLContext glContext;
164
- EGLSurface gl1x1Surface;
165
- sk_sp<GrDirectContext> directContext;
166
- };
167
-
168
- class SkiaOpenGLHelper {
169
- public:
170
- /**
171
- * Calls eglMakeCurrent on the surface provided using the provided
172
- * thread context.
173
- * @param context Skia OpenGL context to use
174
- * @param surface Surface to set as current
175
- * @return true if eglMakeCurrent was successfull
176
- */
177
- static bool makeCurrent(SkiaOpenGLContext *context, EGLSurface glSurface) {
178
- // We don't need to call make current if we already are current:
179
- if (eglGetCurrentSurface(EGL_DRAW) != glSurface ||
180
- eglGetCurrentSurface(EGL_READ) != glSurface ||
181
- eglGetCurrentContext() != context->glContext) {
182
-
183
- // Make current!
184
- if (eglMakeCurrent(OpenGLResourceHolder::getInstance().glDisplay,
185
- glSurface, glSurface,
186
- context->glContext) != EGL_TRUE) {
187
- RNSkLogger::logToConsole("eglMakeCurrent failed: %d\n", eglGetError());
188
- return false;
189
- }
190
- }
191
- return true;
192
- }
193
-
194
- /**
195
- * Creates a new windowed surface
196
- * @param window ANativeWindow to create surface in
197
- * @return EGLSurface or EGL_NO_SURFACE if the call failed
198
- */
199
- static EGLSurface createWindowedSurface(ANativeWindow *window) {
200
- const EGLint attribs[] = {EGL_NONE};
201
- return eglCreateWindowSurface(OpenGLResourceHolder::getInstance().glDisplay,
202
- OpenGLResourceHolder::getInstance().glConfig,
203
- window, attribs);
204
- }
205
-
206
- /**
207
- * Destroys an egl surface
208
- * @param glSurface
209
- * @return
210
- */
211
- static bool destroySurface(EGLSurface glSurface) {
212
- if (eglMakeCurrent(OpenGLResourceHolder::getInstance().glDisplay,
213
- EGL_NO_SURFACE, EGL_NO_SURFACE,
214
- EGL_NO_CONTEXT) != EGL_TRUE) {
215
- RNSkLogger::logToConsole(
216
- "destroySurface: Could not clear selected surface");
217
- return false;
218
- }
219
- return eglDestroySurface(OpenGLResourceHolder::getInstance().glDisplay,
220
- glSurface) == EGL_TRUE;
221
- }
222
-
223
- /**
224
- * Calls the eglSwapBuffer in the current thread with the provided surface
225
- * @param context Thread context
226
- * @param glSurface surface to present
227
- * @return true if eglSwapBuffers succeeded.
228
- */
229
- static bool swapBuffers(SkiaOpenGLContext *context, EGLSurface glSurface) {
230
- if (eglSwapBuffers(OpenGLResourceHolder::getInstance().glDisplay,
231
- glSurface) != EGL_TRUE) {
232
- RNSkLogger::logToConsole("eglSwapBuffers failed: %d\n", eglGetError());
233
- return false;
234
- }
235
- return true;
236
- }
237
-
238
- /***
239
- * Creates a new Skia direct context backed by the provided eglContext in the
240
- * SkiaOpenGLContext.
241
- * @param context Context to store results in
242
- * @param sharedContext Shared Context
243
- * @return true if the call to create a skia direct context suceeded.
244
- */
245
- static bool createSkiaDirectContextIfNecessary(SkiaOpenGLContext *context) {
246
- if (context->directContext == nullptr) {
247
-
248
- // Create OpenGL context
249
- createOpenGLContext(context);
250
-
251
- // Create attributes for a simple 1x1 pbuffer surface that we can
252
- // use to activate and create Skia direct context for
253
- const EGLint offScreenSurfaceAttribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1,
254
- EGL_NONE};
255
-
256
- context->gl1x1Surface =
257
- eglCreatePbufferSurface(OpenGLResourceHolder::getInstance().glDisplay,
258
- OpenGLResourceHolder::getInstance().glConfig,
259
- offScreenSurfaceAttribs);
260
-
261
- if (context->gl1x1Surface == EGL_NO_SURFACE) {
262
- RNSkLogger::logToConsole("Failed creating a 1x1 pbuffer surface");
263
- return false;
264
- }
265
-
266
- // Activate
267
- if (!makeCurrent(context, context->gl1x1Surface)) {
268
- return false;
269
- }
270
-
271
- // Create the Skia context
272
- auto backendInterface = GrGLMakeNativeInterface();
273
- context->directContext = GrDirectContexts::MakeGL(backendInterface);
274
-
275
- if (context->directContext == nullptr) {
276
- RNSkLogger::logToConsole("GrDirectContexts::MakeGL failed");
277
- return false;
278
- }
279
- }
280
-
281
- // It all went well!
282
- return true;
283
- }
284
-
285
- private:
286
- /**
287
- * Creates a new GLContext.
288
- * @param context Context to save results in
289
- * @return True if the call to eglCreateContext returned a valid OpenGL
290
- * Context or if the context already is setup.
291
- */
292
- static bool createOpenGLContext(SkiaOpenGLContext *context) {
293
- // Create OpenGL context attributes
294
- EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
295
-
296
- // Initialize the offscreen context for this thread
297
- context->glContext = eglCreateContext(
298
- OpenGLResourceHolder::getInstance().glDisplay,
299
- OpenGLResourceHolder::getInstance().glConfig,
300
- OpenGLResourceHolder::getInstance().glContext, contextAttribs);
301
-
302
- if (context->glContext == EGL_NO_CONTEXT) {
303
- RNSkLogger::logToConsole("eglCreateContext failed: %d\n", eglGetError());
304
- return EGL_NO_CONTEXT;
305
- }
306
-
307
- return true;
308
- }
309
- };
310
- } // namespace RNSkia
@@ -1,188 +0,0 @@
1
- #include "SkiaOpenGLSurfaceFactory.h"
2
- #include "GrAHardwareBufferUtils.h"
3
- #include "SkiaOpenGLHelper.h"
4
-
5
- #pragma clang diagnostic push
6
- #pragma clang diagnostic ignored "-Wdocumentation"
7
-
8
- #include "include/gpu/ganesh/SkImageGanesh.h"
9
- #include "include/gpu/ganesh/gl/GrGLBackendSurface.h"
10
- #include "src/gpu/ganesh/gl/GrGLDefines.h"
11
-
12
- #pragma clang diagnostic pop
13
-
14
- namespace RNSkia {
15
-
16
- sk_sp<SkImage> SkiaOpenGLSurfaceFactory::makeImageFromHardwareBuffer(
17
- SkiaOpenGLContext *context, void *buffer, bool requireKnownFormat) {
18
- #if __ANDROID_API__ >= 26
19
- const AHardwareBuffer *hardwareBuffer =
20
- static_cast<AHardwareBuffer *>(buffer);
21
- DeleteImageProc deleteImageProc = nullptr;
22
- UpdateImageProc updateImageProc = nullptr;
23
- TexImageCtx deleteImageCtx = nullptr;
24
-
25
- AHardwareBuffer_Desc description;
26
- AHardwareBuffer_describe(hardwareBuffer, &description);
27
- GrBackendFormat format;
28
- switch (description.format) {
29
- // TODO: find out if we can detect, which graphic buffers support
30
- // GR_GL_TEXTURE_2D
31
- case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM:
32
- format = GrBackendFormats::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
33
- case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT:
34
- format = GrBackendFormats::MakeGL(GR_GL_RGBA16F, GR_GL_TEXTURE_EXTERNAL);
35
- case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM:
36
- format = GrBackendFormats::MakeGL(GR_GL_RGB565, GR_GL_TEXTURE_EXTERNAL);
37
- case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM:
38
- format = GrBackendFormats::MakeGL(GR_GL_RGB10_A2, GR_GL_TEXTURE_EXTERNAL);
39
- case AHARDWAREBUFFER_FORMAT_R8G8B8_UNORM:
40
- format = GrBackendFormats::MakeGL(GR_GL_RGB8, GR_GL_TEXTURE_EXTERNAL);
41
- #if __ANDROID_API__ >= 33
42
- case AHARDWAREBUFFER_FORMAT_R8_UNORM:
43
- format = GrBackendFormats::MakeGL(GR_GL_R8, GR_GL_TEXTURE_EXTERNAL);
44
- #endif
45
- default:
46
- if (requireKnownFormat) {
47
- format = GrBackendFormat();
48
- } else {
49
- format = GrBackendFormats::MakeGL(GR_GL_RGBA8, GR_GL_TEXTURE_EXTERNAL);
50
- }
51
- }
52
-
53
- auto backendTex = MakeGLBackendTexture(
54
- context->directContext.get(),
55
- const_cast<AHardwareBuffer *>(hardwareBuffer), description.width,
56
- description.height, &deleteImageProc, &updateImageProc, &deleteImageCtx,
57
- false, format, false);
58
- if (!backendTex.isValid()) {
59
- RNSkLogger::logToConsole(
60
- "Failed to convert HardwareBuffer to OpenGL Texture!");
61
- return nullptr;
62
- }
63
- sk_sp<SkImage> image = SkImages::BorrowTextureFrom(
64
- context->directContext.get(), backendTex, kTopLeft_GrSurfaceOrigin,
65
- kRGBA_8888_SkColorType, kOpaque_SkAlphaType, nullptr, deleteImageProc,
66
- deleteImageCtx);
67
- return image;
68
- #else
69
- throw std::runtime_error(
70
- "HardwareBuffers are only supported on Android API 26 or higher! Set "
71
- "your minSdk to 26 (or higher) and try again.");
72
- #endif
73
- }
74
-
75
- sk_sp<SkSurface>
76
- SkiaOpenGLSurfaceFactory::makeOffscreenSurface(SkiaOpenGLContext *context,
77
- int width, int height) {
78
-
79
- auto colorType = kN32_SkColorType;
80
-
81
- SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
82
-
83
- if (!SkiaOpenGLHelper::makeCurrent(context, context->gl1x1Surface)) {
84
- RNSkLogger::logToConsole(
85
- "Could not create EGL Surface from native window / surface. Could "
86
- "not set new surface as current surface.");
87
- return nullptr;
88
- }
89
-
90
- // Create texture
91
- auto texture = context->directContext->createBackendTexture(
92
- width, height, colorType, skgpu::Mipmapped::kNo, GrRenderable::kYes);
93
-
94
- if (!texture.isValid()) {
95
- RNSkLogger::logToConsole("couldn't create offscreen texture %dx%d", width,
96
- height);
97
- }
98
-
99
- struct ReleaseContext {
100
- SkiaOpenGLContext *context;
101
- GrBackendTexture texture;
102
- };
103
-
104
- auto releaseCtx = new ReleaseContext({context, texture});
105
-
106
- // Create a SkSurface from the GrBackendTexture
107
- return SkSurfaces::WrapBackendTexture(
108
- context->directContext.get(), texture, kTopLeft_GrSurfaceOrigin, 0,
109
- colorType, nullptr, &props,
110
- [](void *addr) {
111
- auto releaseCtx = reinterpret_cast<ReleaseContext *>(addr);
112
-
113
- releaseCtx->context->directContext->deleteBackendTexture(
114
- releaseCtx->texture);
115
- },
116
- releaseCtx);
117
- }
118
-
119
- sk_sp<SkSurface> AndroidSkiaContext::getSurface() {
120
- if (_skSurface == nullptr) {
121
-
122
- // Now we can create a surface
123
- _glSurface = SkiaOpenGLHelper::createWindowedSurface(_window);
124
- if (_glSurface == EGL_NO_SURFACE) {
125
- RNSkLogger::logToConsole(
126
- "Could not create EGL Surface from native window / surface.");
127
- return nullptr;
128
- }
129
-
130
- // Now make this one current
131
- if (!SkiaOpenGLHelper::makeCurrent(_context, _glSurface)) {
132
- RNSkLogger::logToConsole(
133
- "Could not create EGL Surface from native window / surface. Could "
134
- "not set new surface as current surface.");
135
- return nullptr;
136
- }
137
-
138
- // Set up parameters for the render target so that it
139
- // matches the underlying OpenGL context.
140
- GrGLFramebufferInfo fboInfo;
141
-
142
- // We pass 0 as the framebuffer id, since the
143
- // underlying Skia GrGlGpu will read this when wrapping the context in the
144
- // render target and the GrGlGpu object.
145
- fboInfo.fFBOID = 0;
146
- fboInfo.fFormat = 0x8058; // GL_RGBA8
147
-
148
- GLint stencil;
149
- glGetIntegerv(GL_STENCIL_BITS, &stencil);
150
-
151
- GLint samples;
152
- glGetIntegerv(GL_SAMPLES, &samples);
153
-
154
- auto colorType = kN32_SkColorType;
155
-
156
- auto maxSamples =
157
- _context->directContext->maxSurfaceSampleCountForColorType(colorType);
158
-
159
- if (samples > maxSamples) {
160
- samples = maxSamples;
161
- }
162
-
163
- auto renderTarget = GrBackendRenderTargets::MakeGL(_width, _height, samples,
164
- stencil, fboInfo);
165
-
166
- SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
167
-
168
- struct ReleaseContext {
169
- EGLSurface glSurface;
170
- };
171
-
172
- auto releaseCtx = new ReleaseContext({_glSurface});
173
-
174
- // Create surface object
175
- _skSurface = SkSurfaces::WrapBackendRenderTarget(
176
- _context->directContext.get(), renderTarget,
177
- kBottomLeft_GrSurfaceOrigin, colorType, nullptr, &props,
178
- [](void *addr) {
179
- auto releaseCtx = reinterpret_cast<ReleaseContext *>(addr);
180
- SkiaOpenGLHelper::destroySurface(releaseCtx->glSurface);
181
- delete releaseCtx;
182
- },
183
- reinterpret_cast<void *>(releaseCtx));
184
- }
185
- return _skSurface;
186
- }
187
-
188
- } // namespace RNSkia
@@ -1,100 +0,0 @@
1
- #pragma once
2
-
3
- #include "RNSkLog.h"
4
-
5
- #include <fbjni/fbjni.h>
6
- #include <jni.h>
7
-
8
- #include <android/native_window_jni.h>
9
- #include <android/surface_texture.h>
10
- #include <android/surface_texture_jni.h>
11
- #include <condition_variable>
12
- #include <memory>
13
- #include <thread>
14
- #include <unordered_map>
15
-
16
- #include "SkiaOpenGLHelper.h"
17
- #include "WindowContext.h"
18
-
19
- #pragma clang diagnostic push
20
- #pragma clang diagnostic ignored "-Wdocumentation"
21
-
22
- #include "include/core/SkCanvas.h"
23
- #include "include/core/SkColorSpace.h"
24
- #include "include/core/SkSurface.h"
25
- #include "include/gpu/ganesh/GrBackendSurface.h"
26
- #include "include/gpu/ganesh/GrDirectContext.h"
27
- #include "include/gpu/ganesh/SkSurfaceGanesh.h"
28
- #include "include/gpu/ganesh/gl/GrGLInterface.h"
29
-
30
- #pragma clang diagnostic pop
31
-
32
- namespace RNSkia {
33
-
34
- class AndroidSkiaContext : public WindowContext {
35
- public:
36
- AndroidSkiaContext(SkiaOpenGLContext *context, ANativeWindow *window,
37
- int width, int height)
38
- : _context(context), _window(window), _width(width), _height(height) {}
39
-
40
- ~AndroidSkiaContext() { ANativeWindow_release(_window); }
41
-
42
- sk_sp<SkSurface> getSurface() override;
43
-
44
- void present() override {
45
- if (!SkiaOpenGLHelper::makeCurrent(_context, _glSurface)) {
46
- RNSkLogger::logToConsole(
47
- "Could not create EGL Surface from native window / surface. Could "
48
- "not set new surface as current surface.");
49
- return;
50
- }
51
- // Flush and submit the direct context
52
- _context->directContext->flushAndSubmit();
53
-
54
- // Swap buffers
55
- SkiaOpenGLHelper::swapBuffers(_context, _glSurface);
56
- }
57
-
58
- void resize(int width, int height) override {
59
- _skSurface = nullptr;
60
- _width = width;
61
- _height = height;
62
- }
63
-
64
- int getWidth() override { return _width; };
65
-
66
- int getHeight() override { return _height; };
67
-
68
- private:
69
- ANativeWindow *_window;
70
- sk_sp<SkSurface> _skSurface = nullptr;
71
- EGLSurface _glSurface = EGL_NO_SURFACE;
72
- SkiaOpenGLContext *_context;
73
- int _width = 0;
74
- int _height = 0;
75
- };
76
-
77
- class SkiaOpenGLSurfaceFactory {
78
- public:
79
- /**
80
- * Creates a new Skia surface that is backed by a texture.
81
- * @param width Width of surface
82
- * @param height Height of surface
83
- * @return An SkSurface backed by a texture.
84
- */
85
- static sk_sp<SkSurface> makeOffscreenSurface(SkiaOpenGLContext *context,
86
- int width, int height);
87
-
88
- static sk_sp<SkImage>
89
- makeImageFromHardwareBuffer(SkiaOpenGLContext *context, void *buffer,
90
- bool requireKnownFormat = false);
91
-
92
- static std::unique_ptr<AndroidSkiaContext>
93
- makeContext(SkiaOpenGLContext *context, ANativeWindow *surface, int width,
94
- int height) {
95
- return std::make_unique<AndroidSkiaContext>(context, surface, width,
96
- height);
97
- }
98
- };
99
-
100
- } // namespace RNSkia