Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 0255691

Browse files
committed
Add kFlutterDesktopGpuSurfaceTypeD3d11Texture2D and rename kFlutterDesktopGpuSurfaceTypeDxgi to kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle
1 parent 823ac4e commit 0255691

File tree

5 files changed

+124
-71
lines changed

5 files changed

+124
-71
lines changed

shell/platform/common/client_wrapper/core_implementations.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,8 @@ int64_t TextureRegistrarImpl::RegisterTexture(TextureVariant* texture) {
170170
} else if (auto gpu_surface_texture =
171171
std::get_if<GpuSurfaceTexture>(texture)) {
172172
info.type = kFlutterDesktopGpuSurfaceTexture;
173+
info.gpu_surface_config.struct_size =
174+
sizeof(FlutterDesktopGpuSurfaceTextureConfig);
173175
info.gpu_surface_config.type = gpu_surface_texture->surface_type();
174176
info.gpu_surface_config.user_data = gpu_surface_texture;
175177
info.gpu_surface_config.callback =

shell/platform/common/public/flutter_texture_registrar.h

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,12 @@ typedef enum {
3232
typedef enum {
3333
// Uninitialized.
3434
kFlutterDesktopGpuSurfaceTypeNone,
35-
// A D3D/DXGI-based surface.
36-
kFlutterDesktopGpuSurfaceTypeDxgi
35+
// A DXGI shared texture handle (Windows only).
36+
// See
37+
// https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiresource-getsharedhandle
38+
kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle,
39+
// A |ID3D11Texture2D| (Windows only).
40+
kFlutterDesktopGpuSurfaceTypeD3d11Texture2D
3741
} FlutterDesktopGpuSurfaceType;
3842

3943
// Supported pixel formats.
@@ -64,9 +68,21 @@ typedef struct {
6468

6569
// A GPU surface descriptor.
6670
typedef struct {
67-
// The surface handle.
68-
// For DirectX textures (kFlutterDesktopGpuSurfaceTypeDxgi), this is the
69-
// shared handle of an IDXGIResource.
71+
// The size of this struct. Must be
72+
// sizeof(FlutterDesktopGpuSurfaceDescriptor).
73+
size_t struct_size;
74+
// The surface handle. The expected type depends on the
75+
// |FlutterDesktopGpuSurfaceType|.
76+
//
77+
// Provide a |ID3D11Texture2D*| when using
78+
// |kFlutterDesktopGpuSurfaceTypeD3d11Texture2D| or a |HANDLE| when using
79+
// |kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle|.
80+
//
81+
// The referenced resource needs to stay valid until it has been opened by
82+
// Flutter. Consider incrementing the resource's reference count in the
83+
// |FlutterDesktopGpuSurfaceTextureCallback| and registering a
84+
// |release_callback| for decrementing the reference count once it has been
85+
// opened.
7086
void* handle;
7187
// The physical width.
7288
size_t width;
@@ -80,22 +96,31 @@ typedef struct {
8096
size_t visible_height;
8197
// The pixel format which might by optional depending on the surface type.
8298
FlutterDesktopPixelFormat format;
99+
// An optional callback that gets invoked when the |handle| has been opened.
100+
void (*release_callback)(void* release_context);
101+
// Opaque data passed to |release_callback|.
102+
void* release_context;
83103
} FlutterDesktopGpuSurfaceDescriptor;
84104

85105
// The pixel buffer copy callback definition provided to
86106
// the Flutter engine to copy the texture.
87107
// It is invoked with the intended surface size specified by |width| and
88-
// |height| and the |user_data| held by FlutterDesktopPixelBufferTextureConfig.
108+
// |height| and the |user_data| held by
109+
// |FlutterDesktopPixelBufferTextureConfig|.
89110
//
90111
// As this is usually called from the render thread, the callee must take
91112
// care of proper synchronization. It also needs to be ensured that the
92-
// returned FlutterDesktopPixelBuffer isn't released prior to unregistering
113+
// returned |FlutterDesktopPixelBuffer| isn't released prior to unregistering
93114
// the corresponding texture.
94115
typedef const FlutterDesktopPixelBuffer* (
95116
*FlutterDesktopPixelBufferTextureCallback)(size_t width,
96117
size_t height,
97118
void* user_data);
98119

120+
// The GPU surface callback definition provided to the Flutter engine to obtain
121+
// the surface. It is invoked with the intended surface size specified by
122+
// |width| and |height| and the |user_data| held by
123+
// |FlutterDesktopGpuSurfaceTextureConfig|.
99124
typedef const FlutterDesktopGpuSurfaceDescriptor* (
100125
*FlutterDesktopGpuSurfaceTextureCallback)(size_t width,
101126
size_t height,
@@ -111,7 +136,11 @@ typedef struct {
111136

112137
// An object used to configure GPU-surface textures.
113138
typedef struct {
114-
// The concrete surface type (e.g. kFlutterDesktopGpuSurfaceTypeDxgi)
139+
// The size of this struct. Must be
140+
// sizeof(FlutterDesktopGpuSurfaceTextureConfig).
141+
size_t struct_size;
142+
// The concrete surface type (e.g.
143+
// |kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle|)
115144
FlutterDesktopGpuSurfaceType type;
116145
// The callback used by the engine to obtain the surface descriptor.
117146
FlutterDesktopGpuSurfaceTextureCallback callback;

shell/platform/windows/external_texture_d3d.cc

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,35 +6,29 @@
66

77
#include <EGL/egl.h>
88
#include <EGL/eglext.h>
9-
109
#include <iostream>
1110

12-
namespace flutter {
11+
#include "flutter/shell/platform/embedder/embedder_struct_macros.h"
1312

14-
struct ExternalTextureD3dState {
15-
GLuint gl_texture = 0;
16-
EGLSurface egl_surface = EGL_NO_SURFACE;
17-
void* last_surface_handle = nullptr;
18-
};
13+
namespace flutter {
1914

2015
ExternalTextureD3d::ExternalTextureD3d(
16+
FlutterDesktopGpuSurfaceType type,
2117
const FlutterDesktopGpuSurfaceTextureCallback texture_callback,
2218
void* user_data,
2319
const AngleSurfaceManager* surface_manager,
2420
const GlProcs& gl_procs)
25-
: state_(std::make_unique<ExternalTextureD3dState>()),
21+
: type_(type),
2622
texture_callback_(texture_callback),
2723
user_data_(user_data),
2824
surface_manager_(surface_manager),
2925
gl_(gl_procs) {}
3026

3127
ExternalTextureD3d::~ExternalTextureD3d() {
32-
if (state_->egl_surface != EGL_NO_SURFACE) {
33-
eglDestroySurface(surface_manager_->egl_display(), state_->egl_surface);
34-
}
28+
ReleaseImage();
3529

36-
if (state_->gl_texture != 0) {
37-
gl_.glDeleteTextures(1, &state_->gl_texture);
30+
if (gl_texture_ != 0) {
31+
gl_.glDeleteTextures(1, &gl_texture_);
3832
}
3933
}
4034

@@ -50,66 +44,81 @@ bool ExternalTextureD3d::PopulateTexture(size_t width,
5044

5145
// Populate the texture object used by the engine.
5246
opengl_texture->target = GL_TEXTURE_2D;
53-
opengl_texture->name = state_->gl_texture;
47+
opengl_texture->name = gl_texture_;
5448
opengl_texture->format = GL_RGBA8;
5549
opengl_texture->destruction_callback = nullptr;
5650
opengl_texture->user_data = nullptr;
57-
opengl_texture->width = descriptor->visible_width;
58-
opengl_texture->height = descriptor->visible_height;
51+
opengl_texture->width = SAFE_ACCESS(descriptor, visible_width, 0);
52+
opengl_texture->height = SAFE_ACCESS(descriptor, visible_height, 0);
5953

6054
return true;
6155
}
6256

57+
void ExternalTextureD3d::ReleaseImage() {
58+
if (egl_surface_ != EGL_NO_SURFACE) {
59+
eglReleaseTexImage(surface_manager_->egl_display(), egl_surface_,
60+
EGL_BACK_BUFFER);
61+
eglDestroySurface(surface_manager_->egl_display(), egl_surface_);
62+
egl_surface_ = EGL_NO_SURFACE;
63+
}
64+
}
65+
6366
bool ExternalTextureD3d::CreateOrUpdateTexture(
6467
const FlutterDesktopGpuSurfaceDescriptor* descriptor) {
65-
if (descriptor == nullptr || descriptor->handle == nullptr) {
68+
if (descriptor == nullptr ||
69+
SAFE_ACCESS(descriptor, handle, nullptr) == nullptr) {
70+
ReleaseImage();
6671
return false;
6772
}
6873

69-
ExternalTextureD3dState* state = state_.get();
70-
if (state->gl_texture == 0) {
71-
gl_.glGenTextures(1, &state_->gl_texture);
74+
if (gl_texture_ == 0) {
75+
gl_.glGenTextures(1, &gl_texture_);
7276

73-
gl_.glBindTexture(GL_TEXTURE_2D, state_->gl_texture);
77+
gl_.glBindTexture(GL_TEXTURE_2D, gl_texture_);
7478

7579
gl_.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
7680
gl_.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
7781

7882
gl_.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
7983
gl_.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
8084
} else {
81-
gl_.glBindTexture(GL_TEXTURE_2D, state->gl_texture);
85+
gl_.glBindTexture(GL_TEXTURE_2D, gl_texture_);
8286
}
8387

84-
if (descriptor->handle != state->last_surface_handle) {
85-
if (state->egl_surface != EGL_NO_SURFACE) {
86-
eglReleaseTexImage(surface_manager_->egl_display(), state->egl_surface,
87-
EGL_BACK_BUFFER);
88-
eglDestroySurface(surface_manager_->egl_display(), state->egl_surface);
89-
}
90-
91-
EGLint attributes[] = {EGL_WIDTH,
92-
static_cast<EGLint>(descriptor->width),
93-
EGL_HEIGHT,
94-
static_cast<EGLint>(descriptor->height),
95-
EGL_TEXTURE_TARGET,
96-
EGL_TEXTURE_2D,
97-
EGL_TEXTURE_FORMAT,
98-
EGL_TEXTURE_RGBA, // always EGL_TEXTURE_RGBA
99-
EGL_NONE};
100-
101-
state->last_surface_handle = descriptor->handle;
102-
state->egl_surface = surface_manager_->CreateSurfaceFromHandle(
103-
EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE, descriptor->handle, attributes);
104-
105-
if (state->egl_surface == EGL_NO_SURFACE ||
106-
eglBindTexImage(surface_manager_->egl_display(), state->egl_surface,
88+
auto handle = SAFE_ACCESS(descriptor, handle, nullptr);
89+
if (handle != last_surface_handle_) {
90+
ReleaseImage();
91+
92+
EGLint attributes[] = {
93+
EGL_WIDTH,
94+
static_cast<EGLint>(SAFE_ACCESS(descriptor, width, 0)),
95+
EGL_HEIGHT,
96+
static_cast<EGLint>(SAFE_ACCESS(descriptor, height, 0)),
97+
EGL_TEXTURE_TARGET,
98+
EGL_TEXTURE_2D,
99+
EGL_TEXTURE_FORMAT,
100+
EGL_TEXTURE_RGBA, // always EGL_TEXTURE_RGBA
101+
EGL_NONE};
102+
103+
egl_surface_ = surface_manager_->CreateSurfaceFromHandle(
104+
(type_ == kFlutterDesktopGpuSurfaceTypeD3d11Texture2D)
105+
? EGL_D3D_TEXTURE_ANGLE
106+
: EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
107+
handle, attributes);
108+
109+
if (egl_surface_ == EGL_NO_SURFACE ||
110+
eglBindTexImage(surface_manager_->egl_display(), egl_surface_,
107111
EGL_BACK_BUFFER) == EGL_FALSE) {
108-
std::cerr << "Binding DXGI surface failed." << std::endl;
112+
std::cerr << "Binding D3D surface failed." << std::endl;
109113
}
114+
last_surface_handle_ = handle;
110115
}
111116

112-
return state->egl_surface != EGL_NO_SURFACE;
117+
auto release_callback = SAFE_ACCESS(descriptor, release_callback, nullptr);
118+
if (release_callback) {
119+
release_callback(SAFE_ACCESS(descriptor, release_context, nullptr));
120+
}
121+
return egl_surface_ != EGL_NO_SURFACE;
113122
}
114123

115124
} // namespace flutter

shell/platform/windows/external_texture_d3d.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,11 @@
1515

1616
namespace flutter {
1717

18-
typedef struct ExternalTextureD3dState ExternalTextureD3dState;
19-
2018
// An external texture that is backed by a DXGI surface.
2119
class ExternalTextureD3d : public ExternalTexture {
2220
public:
2321
ExternalTextureD3d(
22+
FlutterDesktopGpuSurfaceType type,
2423
const FlutterDesktopGpuSurfaceTextureCallback texture_callback,
2524
void* user_data,
2625
const AngleSurfaceManager* surface_manager,
@@ -33,14 +32,21 @@ class ExternalTextureD3d : public ExternalTexture {
3332
FlutterOpenGLTexture* opengl_texture) override;
3433

3534
private:
35+
// Creates or updates the backing texture and associates it with the provided
36+
// surface.
3637
bool CreateOrUpdateTexture(
3738
const FlutterDesktopGpuSurfaceDescriptor* descriptor);
39+
// Detaches the previously attached surface, if any.
40+
void ReleaseImage();
3841

39-
std::unique_ptr<ExternalTextureD3dState> state_;
40-
const FlutterDesktopGpuSurfaceTextureCallback texture_callback_ = nullptr;
41-
void* const user_data_ = nullptr;
42+
FlutterDesktopGpuSurfaceType type_;
43+
const FlutterDesktopGpuSurfaceTextureCallback texture_callback_;
44+
void* const user_data_;
4245
const AngleSurfaceManager* surface_manager_;
4346
const GlProcs& gl_;
47+
GLuint gl_texture_ = 0;
48+
EGLSurface egl_surface_ = EGL_NO_SURFACE;
49+
void* last_surface_handle_ = nullptr;
4450
};
4551

4652
} // namespace flutter

shell/platform/windows/flutter_windows_texture_registrar.cc

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <iostream>
88
#include <mutex>
99

10+
#include "flutter/shell/platform/embedder/embedder_struct_macros.h"
1011
#include "flutter/shell/platform/windows/external_texture_d3d.h"
1112
#include "flutter/shell/platform/windows/external_texture_pixelbuffer.h"
1213
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
@@ -37,18 +38,24 @@ int64_t FlutterWindowsTextureRegistrar::RegisterTexture(
3738
return EmplaceTexture(std::make_unique<flutter::ExternalTexturePixelBuffer>(
3839
texture_info->pixel_buffer_config.callback,
3940
texture_info->pixel_buffer_config.user_data, gl_procs_));
40-
} else if (texture_info->type == kFlutterDesktopGpuSurfaceTexture &&
41-
texture_info->gpu_surface_config.type ==
42-
kFlutterDesktopGpuSurfaceTypeDxgi) {
43-
if (!texture_info->gpu_surface_config.callback) {
44-
std::cerr << "Invalid DXGI surface callback." << std::endl;
45-
return kInvalidTexture;
41+
} else if (texture_info->type == kFlutterDesktopGpuSurfaceTexture) {
42+
const FlutterDesktopGpuSurfaceTextureConfig* gpu_surface_config =
43+
&texture_info->gpu_surface_config;
44+
auto surface_type = SAFE_ACCESS(gpu_surface_config, type,
45+
kFlutterDesktopGpuSurfaceTypeNone);
46+
if (surface_type == kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle ||
47+
surface_type == kFlutterDesktopGpuSurfaceTypeD3d11Texture2D) {
48+
auto callback = SAFE_ACCESS(gpu_surface_config, callback, nullptr);
49+
if (!callback) {
50+
std::cerr << "Invalid GPU surface descriptor callback." << std::endl;
51+
return kInvalidTexture;
52+
}
53+
54+
auto user_data = SAFE_ACCESS(gpu_surface_config, user_data, nullptr);
55+
return EmplaceTexture(std::make_unique<flutter::ExternalTextureD3d>(
56+
surface_type, callback, user_data, engine_->surface_manager(),
57+
gl_procs_));
4658
}
47-
48-
return EmplaceTexture(std::make_unique<flutter::ExternalTextureD3d>(
49-
texture_info->gpu_surface_config.callback,
50-
texture_info->gpu_surface_config.user_data, engine_->surface_manager(),
51-
gl_procs_));
5259
}
5360

5461
std::cerr << "Attempted to register texture of unsupport type." << std::endl;

0 commit comments

Comments
 (0)