@shopify/react-native-skia 2.5.1 → 2.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/CMakeLists.txt +8 -6
- package/android/build.gradle +5 -32
- package/android/cpp/jni/JniWebGPUView.cpp +67 -0
- package/android/cpp/rnskia-android/OpenGLContext.h +9 -2
- package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +6 -3
- package/android/cpp/rnskia-android/SkiaPlatformContext.h +26 -0
- package/android/src/main/java/com/shopify/reactnative/skia/RNSkiaPackage.java +4 -1
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUSurfaceView.java +41 -0
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUTextureView.java +44 -0
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUView.java +95 -0
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUViewAPI.java +14 -0
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUViewManager.java +58 -0
- package/apple/MetalContext.h +10 -2
- package/apple/MetalWindowContext.h +1 -0
- package/apple/MetalWindowContext.mm +8 -1
- package/apple/RNSkApplePlatformContext.h +2 -1
- package/apple/RNSkApplePlatformContext.mm +6 -4
- package/apple/RNSkUIKit.h +13 -0
- package/apple/SkiaPictureView.mm +3 -0
- package/apple/SkiaPlatformContext.h +20 -0
- package/apple/SkiaPlatformContext.mm +21 -0
- package/apple/WebGPUMetalView.h +12 -0
- package/apple/WebGPUMetalView.mm +93 -0
- package/apple/WebGPUView.h +20 -0
- package/apple/WebGPUView.mm +77 -0
- package/cpp/api/JsiSkImage.h +76 -0
- package/cpp/api/JsiSkSurfaceFactory.h +12 -1
- package/cpp/jsi2/JSIConverter.h +11 -0
- package/cpp/rnskia/RNDawnContext.h +24 -16
- package/cpp/rnskia/RNDawnUtils.h +12 -0
- package/cpp/rnskia/RNSkManager.cpp +11 -4
- package/cpp/rnskia/RNSkPlatformContext.h +3 -1
- package/cpp/rnwgpu/Canvas.h +45 -0
- package/cpp/rnwgpu/PlatformContext.h +18 -0
- package/cpp/rnwgpu/SurfaceRegistry.h +229 -0
- package/cpp/rnwgpu/api/GPUAdapter.cpp +26 -0
- package/cpp/rnwgpu/api/GPUCanvasContext.cpp +64 -0
- package/cpp/rnwgpu/api/GPUCanvasContext.h +65 -0
- package/cpp/rnwgpu/api/GPUDevice.cpp +52 -0
- package/cpp/rnwgpu/api/GPUDevice.h +62 -1
- package/cpp/rnwgpu/api/GPUUncapturedErrorEvent.h +61 -0
- package/cpp/rnwgpu/api/RNWebGPU.h +62 -0
- package/cpp/rnwgpu/api/descriptors/GPUBindGroupEntry.h +4 -0
- package/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h +76 -0
- package/lib/commonjs/external/reanimated/useVideo.js +1 -4
- package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
- package/lib/commonjs/mock/index.js +1 -0
- package/lib/commonjs/mock/index.js.map +1 -1
- package/lib/commonjs/skia/types/Surface/SurfaceFactory.d.ts +10 -1
- package/lib/commonjs/skia/types/Surface/SurfaceFactory.js +5 -0
- package/lib/commonjs/skia/types/Surface/SurfaceFactory.js.map +1 -1
- package/lib/commonjs/sksg/Container.native.js +4 -0
- package/lib/commonjs/sksg/Container.native.js.map +1 -1
- package/lib/commonjs/sksg/Container.web.js +4 -0
- package/lib/commonjs/sksg/Container.web.js.map +1 -1
- package/lib/commonjs/specs/WebGPUViewNativeComponent.d.ts +8 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.js +11 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.js.map +1 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.web.js +101 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.web.js.map +1 -0
- package/lib/commonjs/specs/utils.d.ts +1 -0
- package/lib/commonjs/specs/utils.js +11 -0
- package/lib/commonjs/specs/utils.js.map +1 -0
- package/lib/commonjs/views/WebGPUCanvas.d.ts +32 -0
- package/lib/commonjs/views/WebGPUCanvas.js +66 -0
- package/lib/commonjs/views/WebGPUCanvas.js.map +1 -0
- package/lib/commonjs/views/WebGPUCanvas.web.d.ts +23 -0
- package/lib/commonjs/views/WebGPUCanvas.web.js +20 -0
- package/lib/commonjs/views/WebGPUCanvas.web.js.map +1 -0
- package/lib/commonjs/views/index.d.ts +1 -0
- package/lib/commonjs/views/index.js +11 -0
- package/lib/commonjs/views/index.js.map +1 -1
- package/lib/module/external/reanimated/useVideo.js +1 -4
- package/lib/module/external/reanimated/useVideo.js.map +1 -1
- package/lib/module/mock/index.js +1 -0
- package/lib/module/mock/index.js.map +1 -1
- package/lib/module/skia/types/Surface/SurfaceFactory.d.ts +10 -1
- package/lib/module/skia/types/Surface/SurfaceFactory.js +4 -1
- package/lib/module/skia/types/Surface/SurfaceFactory.js.map +1 -1
- package/lib/module/sksg/Container.native.js +5 -0
- package/lib/module/sksg/Container.native.js.map +1 -1
- package/lib/module/sksg/Container.web.js +5 -0
- package/lib/module/sksg/Container.web.js.map +1 -1
- package/lib/module/specs/WebGPUViewNativeComponent.d.ts +8 -0
- package/lib/module/specs/WebGPUViewNativeComponent.js +4 -0
- package/lib/module/specs/WebGPUViewNativeComponent.js.map +1 -0
- package/lib/module/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
- package/lib/module/specs/WebGPUViewNativeComponent.web.js +94 -0
- package/lib/module/specs/WebGPUViewNativeComponent.web.js.map +1 -0
- package/lib/module/specs/utils.d.ts +1 -0
- package/lib/module/specs/utils.js +5 -0
- package/lib/module/specs/utils.js.map +1 -0
- package/lib/module/views/WebGPUCanvas.d.ts +32 -0
- package/lib/module/views/WebGPUCanvas.js +57 -0
- package/lib/module/views/WebGPUCanvas.js.map +1 -0
- package/lib/module/views/WebGPUCanvas.web.d.ts +23 -0
- package/lib/module/views/WebGPUCanvas.web.js +12 -0
- package/lib/module/views/WebGPUCanvas.web.js.map +1 -0
- package/lib/module/views/index.d.ts +1 -0
- package/lib/module/views/index.js +1 -0
- package/lib/module/views/index.js.map +1 -1
- package/lib/typescript/lib/commonjs/mock/index.d.ts +1 -0
- package/lib/typescript/lib/commonjs/skia/types/Surface/SurfaceFactory.d.ts +4 -0
- package/lib/typescript/lib/commonjs/specs/WebGPUViewNativeComponent.d.ts +3 -0
- package/lib/typescript/lib/commonjs/specs/WebGPUViewNativeComponent.web.d.ts +3 -0
- package/lib/typescript/lib/commonjs/specs/utils.d.ts +2 -0
- package/lib/typescript/lib/commonjs/views/WebGPUCanvas.d.ts +6 -0
- package/lib/typescript/lib/commonjs/views/WebGPUCanvas.web.d.ts +6 -0
- package/lib/typescript/lib/module/mock/index.d.ts +7 -1
- package/lib/typescript/lib/module/skia/types/Surface/SurfaceFactory.d.ts +4 -1
- package/lib/typescript/lib/module/specs/WebGPUViewNativeComponent.d.ts +2 -0
- package/lib/typescript/lib/module/specs/WebGPUViewNativeComponent.web.d.ts +2 -0
- package/lib/typescript/lib/module/specs/utils.d.ts +1 -0
- package/lib/typescript/lib/module/views/WebGPUCanvas.d.ts +7 -0
- package/lib/typescript/lib/module/views/WebGPUCanvas.web.d.ts +8 -0
- package/lib/typescript/lib/module/views/index.d.ts +1 -0
- package/lib/typescript/src/skia/types/Surface/SurfaceFactory.d.ts +10 -1
- package/lib/typescript/src/specs/WebGPUViewNativeComponent.d.ts +8 -0
- package/lib/typescript/src/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
- package/lib/typescript/src/specs/utils.d.ts +1 -0
- package/lib/typescript/src/views/WebGPUCanvas.d.ts +32 -0
- package/lib/typescript/src/views/WebGPUCanvas.web.d.ts +23 -0
- package/lib/typescript/src/views/index.d.ts +1 -0
- package/package.json +7 -3
- package/react-native-skia.podspec +16 -83
- package/scripts/install-libs.js +131 -0
- package/src/external/reanimated/useVideo.ts +1 -4
- package/src/mock/index.ts +1 -0
- package/src/skia/types/Surface/SurfaceFactory.ts +17 -1
- package/src/sksg/Container.native.ts +3 -0
- package/src/sksg/Container.web.ts +3 -0
- package/src/specs/WebGPUViewNativeComponent.ts +11 -0
- package/src/specs/WebGPUViewNativeComponent.web.ts +108 -0
- package/src/specs/utils.ts +4 -0
- package/src/views/WebGPUCanvas.tsx +109 -0
- package/src/views/WebGPUCanvas.web.tsx +36 -0
- package/src/views/index.ts +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
#ifdef SK_GRAPHITE
|
|
2
|
+
|
|
3
|
+
#include "SkiaPlatformContext.h"
|
|
4
|
+
|
|
5
|
+
#include <TargetConditionals.h>
|
|
6
|
+
|
|
7
|
+
namespace rnwgpu {
|
|
8
|
+
|
|
9
|
+
wgpu::Surface SkiaPlatformContext::makeSurface(wgpu::Instance instance,
|
|
10
|
+
void *surface, int width,
|
|
11
|
+
int height) {
|
|
12
|
+
wgpu::SurfaceSourceMetalLayer metalSurfaceDesc;
|
|
13
|
+
metalSurfaceDesc.layer = surface;
|
|
14
|
+
wgpu::SurfaceDescriptor surfaceDescriptor;
|
|
15
|
+
surfaceDescriptor.nextInChain = &metalSurfaceDesc;
|
|
16
|
+
return instance.CreateSurface(&surfaceDescriptor);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
} // namespace rnwgpu
|
|
20
|
+
|
|
21
|
+
#endif // SK_GRAPHITE
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#import "WebGPUMetalView.h"
|
|
2
|
+
|
|
3
|
+
#ifdef SK_GRAPHITE
|
|
4
|
+
|
|
5
|
+
#import "webgpu/webgpu_cpp.h"
|
|
6
|
+
#import <QuartzCore/CAMetalLayer.h>
|
|
7
|
+
|
|
8
|
+
#import "rnwgpu/SurfaceRegistry.h"
|
|
9
|
+
#import "rnskia/RNDawnContext.h"
|
|
10
|
+
|
|
11
|
+
@implementation WebGPUMetalView {
|
|
12
|
+
BOOL _isConfigured;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
#if !TARGET_OS_OSX
|
|
16
|
+
+ (Class)layerClass {
|
|
17
|
+
return [CAMetalLayer class];
|
|
18
|
+
}
|
|
19
|
+
#else // !TARGET_OS_OSX
|
|
20
|
+
- (instancetype)init {
|
|
21
|
+
self = [super init];
|
|
22
|
+
if (self) {
|
|
23
|
+
self.wantsLayer = true;
|
|
24
|
+
self.layer = [CAMetalLayer layer];
|
|
25
|
+
}
|
|
26
|
+
return self;
|
|
27
|
+
}
|
|
28
|
+
#endif // !TARGET_OS_OSX
|
|
29
|
+
|
|
30
|
+
- (void)configure {
|
|
31
|
+
auto size = self.frame.size;
|
|
32
|
+
void *nativeSurface = (__bridge void *)self.layer;
|
|
33
|
+
auto ®istry = rnwgpu::SurfaceRegistry::getInstance();
|
|
34
|
+
auto &dawnContext = RNSkia::DawnContext::getInstance();
|
|
35
|
+
auto gpu = dawnContext.getWGPUInstance();
|
|
36
|
+
|
|
37
|
+
// Create the surface using Dawn's API directly
|
|
38
|
+
wgpu::SurfaceSourceMetalLayer metalSurfaceDesc;
|
|
39
|
+
metalSurfaceDesc.layer = nativeSurface;
|
|
40
|
+
wgpu::SurfaceDescriptor surfaceDescriptor;
|
|
41
|
+
surfaceDescriptor.nextInChain = &metalSurfaceDesc;
|
|
42
|
+
auto surface = gpu.CreateSurface(&surfaceDescriptor);
|
|
43
|
+
|
|
44
|
+
registry
|
|
45
|
+
.getSurfaceInfoOrCreate([_contextId intValue], gpu, size.width,
|
|
46
|
+
size.height)
|
|
47
|
+
->switchToOnscreen(nativeSurface, surface);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
- (void)update {
|
|
51
|
+
auto size = self.frame.size;
|
|
52
|
+
auto ®istry = rnwgpu::SurfaceRegistry::getInstance();
|
|
53
|
+
auto surfaceInfo = registry.getSurfaceInfo([_contextId intValue]);
|
|
54
|
+
if (surfaceInfo) {
|
|
55
|
+
surfaceInfo->resize(size.width, size.height);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
- (void)dealloc {
|
|
60
|
+
auto ®istry = rnwgpu::SurfaceRegistry::getInstance();
|
|
61
|
+
// Remove the surface info from the registry
|
|
62
|
+
registry.removeSurfaceInfo([_contextId intValue]);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
@end
|
|
66
|
+
|
|
67
|
+
#else // SK_GRAPHITE
|
|
68
|
+
|
|
69
|
+
// Stub implementation when GRAPHITE is not enabled
|
|
70
|
+
@implementation WebGPUMetalView
|
|
71
|
+
|
|
72
|
+
#if !TARGET_OS_OSX
|
|
73
|
+
+ (Class)layerClass {
|
|
74
|
+
return [CAMetalLayer class];
|
|
75
|
+
}
|
|
76
|
+
#else // !TARGET_OS_OSX
|
|
77
|
+
- (instancetype)init {
|
|
78
|
+
self = [super init];
|
|
79
|
+
return self;
|
|
80
|
+
}
|
|
81
|
+
#endif // !TARGET_OS_OSX
|
|
82
|
+
|
|
83
|
+
- (void)configure {
|
|
84
|
+
// No-op when GRAPHITE is not enabled
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
- (void)update {
|
|
88
|
+
// No-op when GRAPHITE is not enabled
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@end
|
|
92
|
+
|
|
93
|
+
#endif // SK_GRAPHITE
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
4
|
+
|
|
5
|
+
#import "WebGPUMetalView.h"
|
|
6
|
+
#import <React/RCTViewComponentView.h>
|
|
7
|
+
#if !TARGET_OS_OSX
|
|
8
|
+
#import <UIKit/UIKit.h>
|
|
9
|
+
#else
|
|
10
|
+
#import <AppKit/AppKit.h>
|
|
11
|
+
#endif
|
|
12
|
+
|
|
13
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
14
|
+
|
|
15
|
+
@interface WebGPUView : RCTViewComponentView
|
|
16
|
+
@end
|
|
17
|
+
|
|
18
|
+
NS_ASSUME_NONNULL_END
|
|
19
|
+
|
|
20
|
+
#endif // RCT_NEW_ARCH_ENABLED
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
2
|
+
|
|
3
|
+
#import "WebGPUView.h"
|
|
4
|
+
|
|
5
|
+
#import <react/renderer/components/rnskia/ComponentDescriptors.h>
|
|
6
|
+
#import <react/renderer/components/rnskia/EventEmitters.h>
|
|
7
|
+
#import <react/renderer/components/rnskia/Props.h>
|
|
8
|
+
#import <react/renderer/components/rnskia/RCTComponentViewHelpers.h>
|
|
9
|
+
|
|
10
|
+
#import "WebGPUMetalView.h"
|
|
11
|
+
#import "RCTFabricComponentsPlugins.h"
|
|
12
|
+
|
|
13
|
+
using namespace facebook::react;
|
|
14
|
+
|
|
15
|
+
@implementation WebGPUView
|
|
16
|
+
|
|
17
|
+
- (instancetype)initWithFrame:(CGRect)frame {
|
|
18
|
+
if (self = [super initWithFrame:frame]) {
|
|
19
|
+
static const auto defaultProps = std::make_shared<const WebGPUViewProps>();
|
|
20
|
+
_props = defaultProps;
|
|
21
|
+
}
|
|
22
|
+
return self;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
+ (ComponentDescriptorProvider)componentDescriptorProvider {
|
|
26
|
+
return concreteComponentDescriptorProvider<WebGPUViewComponentDescriptor>();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
- (void)prepareForRecycle {
|
|
30
|
+
[super prepareForRecycle];
|
|
31
|
+
/*
|
|
32
|
+
It's important to destroy the Metal Layer before releasing a view
|
|
33
|
+
to the recycled pool to prevent displaying outdated content from
|
|
34
|
+
the last usage in the new context.
|
|
35
|
+
*/
|
|
36
|
+
self.contentView = nil;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
- (WebGPUMetalView *)getContentView {
|
|
40
|
+
if (!self.contentView) {
|
|
41
|
+
self.contentView = [WebGPUMetalView new];
|
|
42
|
+
}
|
|
43
|
+
return (WebGPUMetalView *)self.contentView;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
- (void)updateProps:(const Props::Shared &)props
|
|
47
|
+
oldProps:(const Props::Shared &)oldProps {
|
|
48
|
+
const auto &oldViewProps =
|
|
49
|
+
*std::static_pointer_cast<const WebGPUViewProps>(_props);
|
|
50
|
+
const auto &newViewProps =
|
|
51
|
+
*std::static_pointer_cast<const WebGPUViewProps>(props);
|
|
52
|
+
|
|
53
|
+
if (newViewProps.contextId != oldViewProps.contextId) {
|
|
54
|
+
/*
|
|
55
|
+
The context is set only once during mounting the component
|
|
56
|
+
and never changes because it isn't available for users to modify.
|
|
57
|
+
*/
|
|
58
|
+
WebGPUMetalView *metalView = [WebGPUMetalView new];
|
|
59
|
+
self.contentView = metalView;
|
|
60
|
+
[metalView setContextId:@(newViewProps.contextId)];
|
|
61
|
+
[metalView configure];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
[super updateProps:props oldProps:oldProps];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
- (void)updateLayoutMetrics:(const LayoutMetrics &)layoutMetrics
|
|
68
|
+
oldLayoutMetrics:(const LayoutMetrics &)oldLayoutMetrics {
|
|
69
|
+
[super updateLayoutMetrics:layoutMetrics oldLayoutMetrics:oldLayoutMetrics];
|
|
70
|
+
[(WebGPUMetalView *)self.contentView update];
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@end
|
|
74
|
+
|
|
75
|
+
Class<RCTComponentViewProtocol> WebGPUViewCls(void) { return WebGPUView.class; }
|
|
76
|
+
|
|
77
|
+
#endif // RCT_NEW_ARCH_ENABLED
|
package/cpp/api/JsiSkImage.h
CHANGED
|
@@ -35,6 +35,75 @@
|
|
|
35
35
|
|
|
36
36
|
#include <jsi/jsi.h>
|
|
37
37
|
|
|
38
|
+
#ifdef __APPLE__
|
|
39
|
+
#include <CoreFoundation/CoreFoundation.h>
|
|
40
|
+
#include <CoreGraphics/CoreGraphics.h>
|
|
41
|
+
#include <cstring>
|
|
42
|
+
|
|
43
|
+
// Replaces Skia's generated "Display P3 Gamut with sRGB Transfer" (Google/Skia
|
|
44
|
+
// copyright) ICC profile in a JPEG with Apple's canonical Display P3 ICC bytes
|
|
45
|
+
// from CGColorSpace.displayP3. This is needed because apps like Instagram only
|
|
46
|
+
// recognise the canonical Apple profile, not Skia's mathematically equivalent
|
|
47
|
+
// but non-standard one. Pixel values are untouched — zero quality loss.
|
|
48
|
+
static sk_sp<SkData> replaceJpegICCWithAppleP3(sk_sp<SkData> jpegData) {
|
|
49
|
+
if (!jpegData || jpegData->size() < 4) return jpegData;
|
|
50
|
+
|
|
51
|
+
const uint8_t *src = jpegData->bytes();
|
|
52
|
+
size_t srcLen = jpegData->size();
|
|
53
|
+
if (src[0] != 0xFF || src[1] != 0xD8) return jpegData; // not a JPEG
|
|
54
|
+
|
|
55
|
+
CGColorSpaceRef p3 = CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3);
|
|
56
|
+
if (!p3) return jpegData;
|
|
57
|
+
CFDataRef cfICC = CGColorSpaceCopyICCData(p3);
|
|
58
|
+
CGColorSpaceRelease(p3);
|
|
59
|
+
if (!cfICC) return jpegData;
|
|
60
|
+
|
|
61
|
+
const uint8_t *iccBytes = CFDataGetBytePtr(cfICC);
|
|
62
|
+
size_t iccLen = (size_t)CFDataGetLength(cfICC);
|
|
63
|
+
|
|
64
|
+
// "ICC_PROFILE\0" APP2 marker signature (12 bytes)
|
|
65
|
+
static const uint8_t iccSig[] = {0x49, 0x43, 0x43, 0x5F, 0x50, 0x52,
|
|
66
|
+
0x4F, 0x46, 0x49, 0x4C, 0x45, 0x00};
|
|
67
|
+
|
|
68
|
+
SkDynamicMemoryWStream out;
|
|
69
|
+
|
|
70
|
+
out.write(src, 2); // SOI
|
|
71
|
+
|
|
72
|
+
// Structure: marker(2) + length(2) + "ICC_PROFILE\0"(12) + chunk[1,1](2) + profile
|
|
73
|
+
size_t iccContentLen = sizeof(iccSig) + 2 + iccLen;
|
|
74
|
+
size_t segLen = iccContentLen + 2; // length field includes itself
|
|
75
|
+
uint8_t app2hdr[4] = {0xFF, 0xE2, (uint8_t)(segLen >> 8),
|
|
76
|
+
(uint8_t)(segLen & 0xFF)};
|
|
77
|
+
uint8_t chunkInfo[2] = {0x01, 0x01}; // chunk 1 of 1
|
|
78
|
+
out.write(app2hdr, 4);
|
|
79
|
+
out.write(iccSig, sizeof(iccSig));
|
|
80
|
+
out.write(chunkInfo, 2);
|
|
81
|
+
out.write(iccBytes, iccLen);
|
|
82
|
+
|
|
83
|
+
// Copy all header segments except any existing ICC APP2
|
|
84
|
+
size_t i = 2;
|
|
85
|
+
while (i + 3 < srcLen) {
|
|
86
|
+
if (src[i] != 0xFF) break;
|
|
87
|
+
uint8_t marker = src[i + 1];
|
|
88
|
+
if (marker == 0xDA || marker == 0xD9) break; // SOS / EOI
|
|
89
|
+
size_t segLenVal = (size_t(src[i + 2]) << 8) | src[i + 3];
|
|
90
|
+
size_t end = i + 2 + segLenVal;
|
|
91
|
+
if (end > srcLen) break;
|
|
92
|
+
bool isICC = marker == 0xE2 && end > i + 4 + sizeof(iccSig) &&
|
|
93
|
+
memcmp(src + i + 4, iccSig, sizeof(iccSig)) == 0;
|
|
94
|
+
if (!isICC) {
|
|
95
|
+
out.write(src + i, end - i);
|
|
96
|
+
}
|
|
97
|
+
i = end;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
out.write(src + i, srcLen - i);
|
|
101
|
+
|
|
102
|
+
CFRelease(cfICC);
|
|
103
|
+
return out.detachAsData();
|
|
104
|
+
}
|
|
105
|
+
#endif // __APPLE__
|
|
106
|
+
|
|
38
107
|
namespace RNSkia {
|
|
39
108
|
|
|
40
109
|
namespace jsi = facebook::jsi;
|
|
@@ -138,6 +207,13 @@ public:
|
|
|
138
207
|
SkJpegEncoder::Options options;
|
|
139
208
|
options.fQuality = quality;
|
|
140
209
|
data = SkJpegEncoder::Encode(nullptr, image.get(), options);
|
|
210
|
+
#ifdef __APPLE__
|
|
211
|
+
// Replace Skia's generated ICC with Apple's canonical Display P3 profile
|
|
212
|
+
// so apps like Instagram recognise the wide-gamut colour space.
|
|
213
|
+
if (data && image->colorSpace() && !image->colorSpace()->isSRGB()) {
|
|
214
|
+
data = replaceJpegICCWithAppleP3(data);
|
|
215
|
+
}
|
|
216
|
+
#endif
|
|
141
217
|
} else if (format == SkEncodedImageFormat::kWEBP) {
|
|
142
218
|
SkWebpEncoder::Options options;
|
|
143
219
|
if (quality >= 100) {
|
|
@@ -39,8 +39,19 @@ public:
|
|
|
39
39
|
JSI_HOST_FUNCTION(MakeOffscreen) {
|
|
40
40
|
auto width = static_cast<int>(arguments[0].asNumber());
|
|
41
41
|
auto height = static_cast<int>(arguments[1].asNumber());
|
|
42
|
+
bool useP3ColorSpace = false;
|
|
43
|
+
if (count >= 3 && arguments[2].isObject()) {
|
|
44
|
+
auto opts = arguments[2].asObject(runtime);
|
|
45
|
+
if (opts.hasProperty(runtime, "colorSpace")) {
|
|
46
|
+
auto colorSpaceVal = opts.getProperty(runtime, "colorSpace");
|
|
47
|
+
if (colorSpaceVal.isString()) {
|
|
48
|
+
useP3ColorSpace =
|
|
49
|
+
colorSpaceVal.asString(runtime).utf8(runtime) == "display-p3";
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
42
53
|
auto context = getContext();
|
|
43
|
-
auto surface = context->makeOffscreenSurface(width, height);
|
|
54
|
+
auto surface = context->makeOffscreenSurface(width, height, useP3ColorSpace);
|
|
44
55
|
if (surface == nullptr) {
|
|
45
56
|
return jsi::Value::null();
|
|
46
57
|
}
|
package/cpp/jsi2/JSIConverter.h
CHANGED
|
@@ -238,6 +238,17 @@ template <> struct JSIConverter<rnwgpu::async::AsyncTaskHandle> {
|
|
|
238
238
|
};
|
|
239
239
|
#endif
|
|
240
240
|
|
|
241
|
+
// jsi::Function <> Function
|
|
242
|
+
template <> struct JSIConverter<jsi::Function> {
|
|
243
|
+
static jsi::Function fromJSI(jsi::Runtime &runtime, const jsi::Value &arg,
|
|
244
|
+
bool outOfBound) {
|
|
245
|
+
return arg.asObject(runtime).asFunction(runtime);
|
|
246
|
+
}
|
|
247
|
+
static jsi::Value toJSI(jsi::Runtime &runtime, jsi::Function &&arg) {
|
|
248
|
+
return std::move(arg);
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
241
252
|
// std::map<std::string, T> <> Record<string, T>
|
|
242
253
|
template <typename ValueType>
|
|
243
254
|
struct JSIConverter<std::map<std::string, ValueType>> {
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include "RNDawnWindowContext.h"
|
|
8
8
|
#include "RNImageProvider.h"
|
|
9
9
|
|
|
10
|
+
#include "include/core/SkColorSpace.h"
|
|
10
11
|
#include "include/core/SkData.h"
|
|
11
12
|
#include "include/gpu/graphite/BackendTexture.h"
|
|
12
13
|
#include "include/gpu/graphite/Context.h"
|
|
@@ -162,9 +163,16 @@ public:
|
|
|
162
163
|
}
|
|
163
164
|
|
|
164
165
|
// Create offscreen surface
|
|
165
|
-
sk_sp<SkSurface> MakeOffscreen(int width, int height
|
|
166
|
+
sk_sp<SkSurface> MakeOffscreen(int width, int height,
|
|
167
|
+
bool useP3ColorSpace = false) {
|
|
168
|
+
sk_sp<SkColorSpace> colorSpace =
|
|
169
|
+
useP3ColorSpace
|
|
170
|
+
? SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
|
|
171
|
+
SkNamedGamut::kDisplayP3)
|
|
172
|
+
: nullptr;
|
|
166
173
|
SkImageInfo info = SkImageInfo::Make(
|
|
167
|
-
width, height, DawnUtils::PreferedColorType, kPremul_SkAlphaType
|
|
174
|
+
width, height, DawnUtils::PreferedColorType, kPremul_SkAlphaType,
|
|
175
|
+
colorSpace);
|
|
168
176
|
sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(getRecorder(), info);
|
|
169
177
|
|
|
170
178
|
if (!surface) {
|
|
@@ -303,6 +311,20 @@ public:
|
|
|
303
311
|
getRecorder(), backendContext.fDevice, surface, width, height);
|
|
304
312
|
}
|
|
305
313
|
|
|
314
|
+
skgpu::graphite::Recorder *getRecorder() {
|
|
315
|
+
static thread_local skgpu::graphite::RecorderOptions recorderOptions;
|
|
316
|
+
if (!recorderOptions.fImageProvider) {
|
|
317
|
+
auto imageProvider = ImageProvider::Make();
|
|
318
|
+
recorderOptions.fImageProvider = imageProvider;
|
|
319
|
+
}
|
|
320
|
+
static thread_local auto recorder =
|
|
321
|
+
fGraphiteContext->makeRecorder(recorderOptions);
|
|
322
|
+
if (!recorder) {
|
|
323
|
+
throw std::runtime_error("Failed to create graphite context");
|
|
324
|
+
}
|
|
325
|
+
return recorder.get();
|
|
326
|
+
}
|
|
327
|
+
|
|
306
328
|
private:
|
|
307
329
|
std::unique_ptr<dawn::native::Instance> instance;
|
|
308
330
|
std::unique_ptr<skgpu::graphite::Context> fGraphiteContext;
|
|
@@ -346,20 +368,6 @@ private:
|
|
|
346
368
|
backendContext.fTick(backendContext.fInstance);
|
|
347
369
|
}
|
|
348
370
|
}
|
|
349
|
-
|
|
350
|
-
skgpu::graphite::Recorder *getRecorder() {
|
|
351
|
-
static thread_local skgpu::graphite::RecorderOptions recorderOptions;
|
|
352
|
-
if (!recorderOptions.fImageProvider) {
|
|
353
|
-
auto imageProvider = ImageProvider::Make();
|
|
354
|
-
recorderOptions.fImageProvider = imageProvider;
|
|
355
|
-
}
|
|
356
|
-
static thread_local auto recorder =
|
|
357
|
-
fGraphiteContext->makeRecorder(recorderOptions);
|
|
358
|
-
if (!recorder) {
|
|
359
|
-
throw std::runtime_error("Failed to create graphite context");
|
|
360
|
-
}
|
|
361
|
-
return recorder.get();
|
|
362
|
-
}
|
|
363
371
|
};
|
|
364
372
|
|
|
365
373
|
} // namespace RNSkia
|
package/cpp/rnskia/RNDawnUtils.h
CHANGED
|
@@ -177,6 +177,18 @@ createDawnBackendContext(dawn::native::Instance *instance) {
|
|
|
177
177
|
if (adapter.HasFeature(wgpu::FeatureName::SharedTextureMemoryIOSurface)) {
|
|
178
178
|
features.push_back(wgpu::FeatureName::SharedTextureMemoryIOSurface);
|
|
179
179
|
}
|
|
180
|
+
if (adapter.HasFeature(wgpu::FeatureName::DawnMultiPlanarFormats)) {
|
|
181
|
+
features.push_back(wgpu::FeatureName::DawnMultiPlanarFormats);
|
|
182
|
+
}
|
|
183
|
+
if (adapter.HasFeature(wgpu::FeatureName::MultiPlanarFormatP010)) {
|
|
184
|
+
features.push_back(wgpu::FeatureName::MultiPlanarFormatP010);
|
|
185
|
+
}
|
|
186
|
+
if (adapter.HasFeature(wgpu::FeatureName::MultiPlanarFormatP210)) {
|
|
187
|
+
features.push_back(wgpu::FeatureName::MultiPlanarFormatP210);
|
|
188
|
+
}
|
|
189
|
+
if (adapter.HasFeature(wgpu::FeatureName::MultiPlanarFormatExtendedUsages)) {
|
|
190
|
+
features.push_back(wgpu::FeatureName::MultiPlanarFormatExtendedUsages);
|
|
191
|
+
}
|
|
180
192
|
#else
|
|
181
193
|
if (adapter.HasFeature(
|
|
182
194
|
wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer)) {
|
|
@@ -14,6 +14,8 @@
|
|
|
14
14
|
#ifdef SK_GRAPHITE
|
|
15
15
|
#include "RNDawnContext.h"
|
|
16
16
|
#include "rnwgpu/api/GPU.h"
|
|
17
|
+
#include "rnwgpu/api/GPUUncapturedErrorEvent.h"
|
|
18
|
+
#include "rnwgpu/api/RNWebGPU.h"
|
|
17
19
|
#include "rnwgpu/api/descriptors/GPUBufferUsage.h"
|
|
18
20
|
#include "rnwgpu/api/descriptors/GPUColorWrite.h"
|
|
19
21
|
#include "rnwgpu/api/descriptors/GPUMapMode.h"
|
|
@@ -73,8 +75,9 @@ void RNSkManager::installBindings() {
|
|
|
73
75
|
jsi::Object::createFromHostObject(*_jsRuntime, _viewApi));
|
|
74
76
|
|
|
75
77
|
#ifdef SK_GRAPHITE
|
|
76
|
-
// Install WebGPU
|
|
78
|
+
// Install WebGPU constructors
|
|
77
79
|
rnwgpu::GPU::installConstructor(*_jsRuntime);
|
|
80
|
+
rnwgpu::GPUUncapturedErrorEvent::installConstructor(*_jsRuntime);
|
|
78
81
|
// Create and expose navigator.gpu using DawnContext's instance
|
|
79
82
|
auto &dawnContext = DawnContext::getInstance();
|
|
80
83
|
auto gpu =
|
|
@@ -103,9 +106,13 @@ void RNSkManager::installBindings() {
|
|
|
103
106
|
rnwgpu::GPUMapMode::create(*_jsRuntime));
|
|
104
107
|
_jsRuntime->global().setProperty(*_jsRuntime, "GPUShaderStage",
|
|
105
108
|
rnwgpu::GPUShaderStage::create(*_jsRuntime));
|
|
106
|
-
_jsRuntime->global().setProperty(
|
|
107
|
-
|
|
108
|
-
|
|
109
|
+
_jsRuntime->global().setProperty(*_jsRuntime, "GPUTextureUsage",
|
|
110
|
+
rnwgpu::GPUTextureUsage::create(*_jsRuntime));
|
|
111
|
+
|
|
112
|
+
// Install RNWebGPU global object for WebGPU Canvas support
|
|
113
|
+
auto rnWebGPU = std::make_shared<rnwgpu::RNWebGPU>(gpu, nullptr);
|
|
114
|
+
_jsRuntime->global().setProperty(*_jsRuntime, "RNWebGPU",
|
|
115
|
+
rnwgpu::RNWebGPU::create(*_jsRuntime, rnWebGPU));
|
|
109
116
|
#endif
|
|
110
117
|
}
|
|
111
118
|
} // namespace RNSkia
|
|
@@ -90,9 +90,11 @@ public:
|
|
|
90
90
|
* Creates an offscreen surface
|
|
91
91
|
* @param width Width of the offscreen surface
|
|
92
92
|
* @param height Height of the offscreen surface
|
|
93
|
+
* @param useP3ColorSpace If true, surface will use Display P3 color space
|
|
93
94
|
* @return sk_sp<SkSurface>
|
|
94
95
|
*/
|
|
95
|
-
virtual sk_sp<SkSurface> makeOffscreenSurface(int width, int height
|
|
96
|
+
virtual sk_sp<SkSurface> makeOffscreenSurface(int width, int height,
|
|
97
|
+
bool useP3ColorSpace = false) = 0;
|
|
96
98
|
|
|
97
99
|
virtual std::shared_ptr<WindowContext>
|
|
98
100
|
makeContextFromNativeSurface(void *surface, int width, int height) = 0;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
|
|
5
|
+
#include "jsi2/NativeObject.h"
|
|
6
|
+
|
|
7
|
+
namespace rnwgpu {
|
|
8
|
+
|
|
9
|
+
namespace jsi = facebook::jsi;
|
|
10
|
+
|
|
11
|
+
class Canvas : public NativeObject<Canvas> {
|
|
12
|
+
public:
|
|
13
|
+
static constexpr const char *CLASS_NAME = "Canvas";
|
|
14
|
+
|
|
15
|
+
Canvas(void *nativeSurface, int width, int height)
|
|
16
|
+
: NativeObject(CLASS_NAME), _nativeSurface(nativeSurface), _width(width),
|
|
17
|
+
_height(height), _clientWidth(width), _clientHeight(height) {}
|
|
18
|
+
|
|
19
|
+
void *getNativeSurface() { return _nativeSurface; }
|
|
20
|
+
|
|
21
|
+
int getWidth() { return _width; }
|
|
22
|
+
int getHeight() { return _height; }
|
|
23
|
+
|
|
24
|
+
int getClientWidth() { return _clientWidth; }
|
|
25
|
+
int getClientHeight() { return _clientHeight; }
|
|
26
|
+
|
|
27
|
+
void setClientWidth(int width) { _clientWidth = width; }
|
|
28
|
+
void setClientHeight(int height) { _clientHeight = height; }
|
|
29
|
+
|
|
30
|
+
static void definePrototype(jsi::Runtime &runtime, jsi::Object &prototype) {
|
|
31
|
+
installGetter(runtime, prototype, "width", &Canvas::getWidth);
|
|
32
|
+
installGetter(runtime, prototype, "height", &Canvas::getHeight);
|
|
33
|
+
installGetter(runtime, prototype, "clientWidth", &Canvas::getClientWidth);
|
|
34
|
+
installGetter(runtime, prototype, "clientHeight", &Canvas::getClientHeight);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private:
|
|
38
|
+
void *_nativeSurface;
|
|
39
|
+
int _width;
|
|
40
|
+
int _height;
|
|
41
|
+
int _clientWidth;
|
|
42
|
+
int _clientHeight;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
} // namespace rnwgpu
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <memory>
|
|
4
|
+
|
|
5
|
+
#include "webgpu/webgpu_cpp.h"
|
|
6
|
+
|
|
7
|
+
namespace rnwgpu {
|
|
8
|
+
|
|
9
|
+
class PlatformContext {
|
|
10
|
+
public:
|
|
11
|
+
PlatformContext() = default;
|
|
12
|
+
virtual ~PlatformContext() = default;
|
|
13
|
+
|
|
14
|
+
virtual wgpu::Surface makeSurface(wgpu::Instance instance, void *surface,
|
|
15
|
+
int width, int height) = 0;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
} // namespace rnwgpu
|