feat: paint
event move texture data to handle
, add colorSpace
(#47315)
* feat: paint event move shared texture to handle, add color space * feat: add breaking change * fix: properties. * fix: remove utf8 bom
This commit is contained in:
parent
095e622a6a
commit
9dcdec5015
7 changed files with 60 additions and 27 deletions
|
@ -4,7 +4,8 @@
|
||||||
* `widgetType` string - The widget type of the texture. Can be `popup` or `frame`.
|
* `widgetType` string - The widget type of the texture. Can be `popup` or `frame`.
|
||||||
* `pixelFormat` string - The pixel format of the texture. Can be `rgba` or `bgra`.
|
* `pixelFormat` string - The pixel format of the texture. Can be `rgba` or `bgra`.
|
||||||
* `codedSize` [Size](size.md) - The full dimensions of the video frame.
|
* `codedSize` [Size](size.md) - The full dimensions of the video frame.
|
||||||
* `visibleRect` [Rectangle](rectangle.md) - A subsection of [0, 0, codedSize.width(), codedSize.height()]. In OSR case, it is expected to have the full section area.
|
* `colorSpace` [ColorSpace](color-space.md) - The color space of the video frame.
|
||||||
|
* `visibleRect` [Rectangle](rectangle.md) - A subsection of [0, 0, codedSize.width, codedSize.height]. In OSR case, it is expected to have the full section area.
|
||||||
* `contentRect` [Rectangle](rectangle.md) - The region of the video frame that capturer would like to populate. In OSR case, it is the same with `dirtyRect` that needs to be painted.
|
* `contentRect` [Rectangle](rectangle.md) - The region of the video frame that capturer would like to populate. In OSR case, it is the same with `dirtyRect` that needs to be painted.
|
||||||
* `timestamp` number - The time in microseconds since the capture start.
|
* `timestamp` number - The time in microseconds since the capture start.
|
||||||
* `metadata` Object - Extra metadata. See comments in src\media\base\video_frame_metadata.h for accurate details.
|
* `metadata` Object - Extra metadata. See comments in src\media\base\video_frame_metadata.h for accurate details.
|
||||||
|
@ -12,13 +13,6 @@
|
||||||
* `regionCaptureRect` [Rectangle](rectangle.md) (optional) - May reflect the frame's contents origin if region capture is used internally.
|
* `regionCaptureRect` [Rectangle](rectangle.md) (optional) - May reflect the frame's contents origin if region capture is used internally.
|
||||||
* `sourceSize` [Rectangle](rectangle.md) (optional) - Full size of the source frame.
|
* `sourceSize` [Rectangle](rectangle.md) (optional) - Full size of the source frame.
|
||||||
* `frameCount` number (optional) - The increasing count of captured frame. May contain gaps if frames are dropped between two consecutively received frames.
|
* `frameCount` number (optional) - The increasing count of captured frame. May contain gaps if frames are dropped between two consecutively received frames.
|
||||||
* `sharedTextureHandle` Buffer _Windows_ _macOS_ - The handle to the shared texture.
|
* `handle` [SharedTextureHandle](shared-texture-handle.md) - The shared texture handle data.
|
||||||
* `planes` Object[] _Linux_ - Each plane's info of the shared texture.
|
|
||||||
* `stride` number - The strides and offsets in bytes to be used when accessing the buffers via a memory mapping. One per plane per entry.
|
|
||||||
* `offset` number - The strides and offsets in bytes to be used when accessing the buffers via a memory mapping. One per plane per entry.
|
|
||||||
* `size` number - Size in bytes of the plane. This is necessary to map the buffers.
|
|
||||||
* `fd` number - File descriptor for the underlying memory object (usually dmabuf).
|
|
||||||
* `modifier` string _Linux_ - The modifier is retrieved from GBM library and passed to EGL driver.
|
|
||||||
* `release` Function - Release the resources. The `texture` cannot be directly passed to another process, users need to maintain texture lifecycles in
|
* `release` Function - Release the resources. The `texture` cannot be directly passed to another process, users need to maintain texture lifecycles in
|
||||||
main process, but it is safe to pass the `textureInfo` to another process. Only a limited number of textures can exist at the same time, so it's important
|
main process, but it is safe to pass the `textureInfo` to another process. Only a limited number of textures can exist at the same time, so it's important that you call `texture.release()` as soon as you're done with the texture.
|
||||||
that you call `texture.release()` as soon as you're done with the texture.
|
|
||||||
|
|
12
docs/api/structures/shared-texture-handle.md
Normal file
12
docs/api/structures/shared-texture-handle.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# SharedTextureHandle Object
|
||||||
|
|
||||||
|
* `ntHandle` Buffer (optional) _Windows_ - NT HANDLE holds the shared texture. Note that this NT HANDLE is local to current process.
|
||||||
|
* `ioSurface` Buffer (optional) _macOS_ - IOSurfaceRef holds the shared texture. Note that this IOSurface is local to current process (not global).
|
||||||
|
* `nativePixmap` Object (optional) _Linux_ - Structure contains planes of shared texture.
|
||||||
|
* `planes` Object[] _Linux_ - Each plane's info of the shared texture.
|
||||||
|
* `stride` number - The strides and offsets in bytes to be used when accessing the buffers via a memory mapping. One per plane per entry.
|
||||||
|
* `offset` number - The strides and offsets in bytes to be used when accessing the buffers via a memory mapping. One per plane per entry.
|
||||||
|
* `size` number - Size in bytes of the plane. This is necessary to map the buffers.
|
||||||
|
* `fd` number - File descriptor for the underlying memory object (usually dmabuf).
|
||||||
|
* `modifier` string _Linux_ - The modifier is retrieved from GBM library and passed to EGL driver.
|
||||||
|
* `supportsZeroCopyWebGpuImport` boolean _Linux_ - Indicates whether supports zero copy import to WebGPU.
|
|
@ -54,6 +54,12 @@ webContents.setWindowOpenHandler((details) => {
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Behavior Changed: shared texture OSR `paint` event data structure
|
||||||
|
|
||||||
|
When using shared texture offscreen rendering feature, the `paint` event now emits a more structured object.
|
||||||
|
It moves the `sharedTextureHandle`, `planes`, `modifier` into a unified `handle` property.
|
||||||
|
See [here](https://www.electronjs.org/docs/latest/api/structures/offscreen-shared-texture) for more details.
|
||||||
|
|
||||||
## Planned Breaking API Changes (37.0)
|
## Planned Breaking API Changes (37.0)
|
||||||
|
|
||||||
### Utility Process unhandled rejection behavior change
|
### Utility Process unhandled rejection behavior change
|
||||||
|
|
|
@ -77,6 +77,9 @@ struct OffscreenSharedTextureValue {
|
||||||
// In OSR case, it is the same with `dirtyRect` that needs to be painted.
|
// In OSR case, it is the same with `dirtyRect` that needs to be painted.
|
||||||
gfx::Rect content_rect;
|
gfx::Rect content_rect;
|
||||||
|
|
||||||
|
// Color space of the video frame.
|
||||||
|
gfx::ColorSpace color_space;
|
||||||
|
|
||||||
// Extra metadata for the video frame.
|
// Extra metadata for the video frame.
|
||||||
// See comments in src\media\base\video_frame_metadata.h for more details.
|
// See comments in src\media\base\video_frame_metadata.h for more details.
|
||||||
std::optional<gfx::Rect> capture_update_rect;
|
std::optional<gfx::Rect> capture_update_rect;
|
||||||
|
@ -99,6 +102,7 @@ struct OffscreenSharedTextureValue {
|
||||||
#elif BUILDFLAG(IS_LINUX)
|
#elif BUILDFLAG(IS_LINUX)
|
||||||
std::vector<OffscreenNativePixmapPlaneInfo> planes;
|
std::vector<OffscreenNativePixmapPlaneInfo> planes;
|
||||||
uint64_t modifier;
|
uint64_t modifier;
|
||||||
|
bool supports_zero_copy_webgpu_import;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -95,6 +95,7 @@ void OffScreenVideoConsumer::OnFrameCaptured(
|
||||||
texture.coded_size = info->coded_size;
|
texture.coded_size = info->coded_size;
|
||||||
texture.visible_rect = info->visible_rect;
|
texture.visible_rect = info->visible_rect;
|
||||||
texture.content_rect = content_rect;
|
texture.content_rect = content_rect;
|
||||||
|
texture.color_space = info->color_space;
|
||||||
texture.timestamp = info->timestamp.InMicroseconds();
|
texture.timestamp = info->timestamp.InMicroseconds();
|
||||||
texture.frame_count = info->metadata.capture_counter.value_or(0);
|
texture.frame_count = info->metadata.capture_counter.value_or(0);
|
||||||
texture.capture_update_rect = info->metadata.capture_update_rect;
|
texture.capture_update_rect = info->metadata.capture_update_rect;
|
||||||
|
@ -111,6 +112,8 @@ void OffScreenVideoConsumer::OnFrameCaptured(
|
||||||
#elif BUILDFLAG(IS_LINUX)
|
#elif BUILDFLAG(IS_LINUX)
|
||||||
const auto& native_pixmap = gmb_handle.native_pixmap_handle();
|
const auto& native_pixmap = gmb_handle.native_pixmap_handle();
|
||||||
texture.modifier = native_pixmap.modifier;
|
texture.modifier = native_pixmap.modifier;
|
||||||
|
texture.supports_zero_copy_webgpu_import =
|
||||||
|
native_pixmap.supports_zero_copy_webgpu_import;
|
||||||
for (const auto& plane : native_pixmap.planes) {
|
for (const auto& plane : native_pixmap.planes) {
|
||||||
texture.planes.emplace_back(plane.stride, plane.offset, plane.size,
|
texture.planes.emplace_back(plane.stride, plane.offset, plane.size,
|
||||||
plane.fd.get());
|
plane.fd.get());
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
|
// Copyright (c) 2025 GitHub, Inc.
|
||||||
// Copyright (c) 2024 GitHub, Inc.
|
// Use of this source code is governed by the MIT license that can be
|
||||||
// Use of this source code is governed by the MIT license that can be found in
|
// found in the LICENSE file.
|
||||||
// the LICENSE file.
|
|
||||||
|
|
||||||
#include "shell/common/gin_converters/osr_converter.h"
|
#include "shell/common/gin_converters/osr_converter.h"
|
||||||
|
|
||||||
|
@ -17,6 +16,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include "shell/common/gin_converters/gfx_converter.h"
|
#include "shell/common/gin_converters/gfx_converter.h"
|
||||||
#include "shell/common/gin_converters/optional_converter.h"
|
#include "shell/common/gin_converters/optional_converter.h"
|
||||||
|
#include "shell/common/gin_helper/error_thrower.h"
|
||||||
#include "shell/common/node_includes.h"
|
#include "shell/common/node_includes.h"
|
||||||
#include "shell/common/node_util.h"
|
#include "shell/common/node_util.h"
|
||||||
|
|
||||||
|
@ -87,10 +87,11 @@ v8::Local<v8::Value> Converter<electron::OffscreenSharedTextureValue>::ToV8(
|
||||||
|
|
||||||
auto releaserHolder = v8::External::New(isolate, monitor);
|
auto releaserHolder = v8::External::New(isolate, monitor);
|
||||||
auto releaserFunc = [](const v8::FunctionCallbackInfo<v8::Value>& info) {
|
auto releaserFunc = [](const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||||
auto* holder = static_cast<OffscreenReleaseHolderMonitor*>(
|
auto* mon = static_cast<OffscreenReleaseHolderMonitor*>(
|
||||||
info.Data().As<v8::External>()->Value());
|
info.Data().As<v8::External>()->Value());
|
||||||
// Release the shared texture, so that future frames can be generated.
|
// Release the shared texture, so that future frames can be generated.
|
||||||
holder->ReleaseTexture();
|
mon->ReleaseTexture();
|
||||||
|
// Release the monitor happens at GC, don't release here.
|
||||||
};
|
};
|
||||||
auto releaser = v8::Function::New(isolate->GetCurrentContext(), releaserFunc,
|
auto releaser = v8::Function::New(isolate->GetCurrentContext(), releaserFunc,
|
||||||
releaserHolder)
|
releaserHolder)
|
||||||
|
@ -104,6 +105,7 @@ v8::Local<v8::Value> Converter<electron::OffscreenSharedTextureValue>::ToV8(
|
||||||
dict.Set("visibleRect", val.visible_rect);
|
dict.Set("visibleRect", val.visible_rect);
|
||||||
dict.Set("contentRect", val.content_rect);
|
dict.Set("contentRect", val.content_rect);
|
||||||
dict.Set("timestamp", val.timestamp);
|
dict.Set("timestamp", val.timestamp);
|
||||||
|
dict.Set("colorSpace", val.color_space);
|
||||||
dict.Set("widgetType", OsrWidgetTypeToString(val.widget_type));
|
dict.Set("widgetType", OsrWidgetTypeToString(val.widget_type));
|
||||||
|
|
||||||
gin::Dictionary metadata(isolate, v8::Object::New(isolate));
|
gin::Dictionary metadata(isolate, v8::Object::New(isolate));
|
||||||
|
@ -113,12 +115,21 @@ v8::Local<v8::Value> Converter<electron::OffscreenSharedTextureValue>::ToV8(
|
||||||
metadata.Set("frameCount", val.frame_count);
|
metadata.Set("frameCount", val.frame_count);
|
||||||
dict.Set("metadata", ConvertToV8(isolate, metadata));
|
dict.Set("metadata", ConvertToV8(isolate, metadata));
|
||||||
|
|
||||||
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
|
gin::Dictionary sharedTexture(isolate, v8::Object::New(isolate));
|
||||||
dict.Set("sharedTextureHandle",
|
#if BUILDFLAG(IS_WIN)
|
||||||
|
sharedTexture.Set(
|
||||||
|
"ntHandle",
|
||||||
|
electron::Buffer::Copy(
|
||||||
|
isolate, base::byte_span_from_ref(val.shared_texture_handle))
|
||||||
|
.ToLocalChecked());
|
||||||
|
#elif BUILDFLAG(IS_MAC)
|
||||||
|
sharedTexture.Set(
|
||||||
|
"ioSurface",
|
||||||
electron::Buffer::Copy(
|
electron::Buffer::Copy(
|
||||||
isolate, base::byte_span_from_ref(val.shared_texture_handle))
|
isolate, base::byte_span_from_ref(val.shared_texture_handle))
|
||||||
.ToLocalChecked());
|
.ToLocalChecked());
|
||||||
#elif BUILDFLAG(IS_LINUX)
|
#elif BUILDFLAG(IS_LINUX)
|
||||||
|
gin::Dictionary nativePixmap(isolate, v8::Object::New(isolate));
|
||||||
auto v8_planes = base::ToVector(val.planes, [isolate](const auto& plane) {
|
auto v8_planes = base::ToVector(val.planes, [isolate](const auto& plane) {
|
||||||
gin::Dictionary v8_plane(isolate, v8::Object::New(isolate));
|
gin::Dictionary v8_plane(isolate, v8::Object::New(isolate));
|
||||||
v8_plane.Set("stride", plane.stride);
|
v8_plane.Set("stride", plane.stride);
|
||||||
|
@ -127,10 +138,14 @@ v8::Local<v8::Value> Converter<electron::OffscreenSharedTextureValue>::ToV8(
|
||||||
v8_plane.Set("fd", plane.fd);
|
v8_plane.Set("fd", plane.fd);
|
||||||
return v8_plane;
|
return v8_plane;
|
||||||
});
|
});
|
||||||
dict.Set("planes", v8_planes);
|
nativePixmap.Set("planes", v8_planes);
|
||||||
dict.Set("modifier", base::NumberToString(val.modifier));
|
nativePixmap.Set("modifier", base::NumberToString(val.modifier));
|
||||||
|
nativePixmap.Set("supportsZeroCopyWebGpuImport",
|
||||||
|
val.supports_zero_copy_webgpu_import);
|
||||||
|
sharedTexture.Set("nativePixmap", ConvertToV8(isolate, nativePixmap));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
dict.Set("handle", ConvertToV8(isolate, sharedTexture));
|
||||||
root.Set("textureInfo", ConvertToV8(isolate, dict));
|
root.Set("textureInfo", ConvertToV8(isolate, dict));
|
||||||
auto root_local = ConvertToV8(isolate, root);
|
auto root_local = ConvertToV8(isolate, root);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
|
// Copyright (c) 2025 GitHub, Inc.
|
||||||
// Copyright (c) 2024 GitHub, Inc.
|
// Use of this source code is governed by the MIT license that can be
|
||||||
// Use of this source code is governed by the MIT license that can be found in
|
// found in the LICENSE file.
|
||||||
// the LICENSE file.
|
|
||||||
|
|
||||||
#ifndef ELECTRON_SHELL_COMMON_GIN_CONVERTERS_OSR_CONVERTER_H_
|
#ifndef ELECTRON_SHELL_COMMON_GIN_CONVERTERS_OSR_CONVERTER_H_
|
||||||
#define ELECTRON_SHELL_COMMON_GIN_CONVERTERS_OSR_CONVERTER_H_
|
#define ELECTRON_SHELL_COMMON_GIN_CONVERTERS_OSR_CONVERTER_H_
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue