mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Windows: Add Direct3D texture interoperability support (flutter/engine#26840)
This commit is contained in:
parent
6c23dd0aab
commit
fa609bd3fa
@ -2227,8 +2227,11 @@ FILE: ../../../flutter/shell/platform/windows/dpi_utils_win32.h
|
||||
FILE: ../../../flutter/shell/platform/windows/dpi_utils_win32_unittests.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/event_watcher_win32.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/event_watcher_win32.h
|
||||
FILE: ../../../flutter/shell/platform/windows/external_texture_gl.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/external_texture_gl.h
|
||||
FILE: ../../../flutter/shell/platform/windows/external_texture.h
|
||||
FILE: ../../../flutter/shell/platform/windows/external_texture_d3d.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/external_texture_d3d.h
|
||||
FILE: ../../../flutter/shell/platform/windows/external_texture_pixelbuffer.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/external_texture_pixelbuffer.h
|
||||
FILE: ../../../flutter/shell/platform/windows/flutter_key_map.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/flutter_platform_node_delegate_win32.cc
|
||||
FILE: ../../../flutter/shell/platform/windows/flutter_platform_node_delegate_win32.h
|
||||
|
||||
@ -157,25 +157,37 @@ TextureRegistrarImpl::TextureRegistrarImpl(
|
||||
TextureRegistrarImpl::~TextureRegistrarImpl() = default;
|
||||
|
||||
int64_t TextureRegistrarImpl::RegisterTexture(TextureVariant* texture) {
|
||||
FlutterDesktopTextureInfo info = {};
|
||||
if (auto pixel_buffer_texture = std::get_if<PixelBufferTexture>(texture)) {
|
||||
FlutterDesktopTextureInfo info = {};
|
||||
info.type = kFlutterDesktopPixelBufferTexture;
|
||||
info.pixel_buffer_config.user_data = pixel_buffer_texture;
|
||||
info.pixel_buffer_config.callback =
|
||||
[](size_t width, size_t height,
|
||||
void* user_data) -> const FlutterDesktopPixelBuffer* {
|
||||
auto texture = static_cast<PixelBufferTexture*>(user_data);
|
||||
auto buffer = texture->CopyPixelBuffer(width, height);
|
||||
return buffer;
|
||||
return texture->CopyPixelBuffer(width, height);
|
||||
};
|
||||
|
||||
int64_t texture_id = FlutterDesktopTextureRegistrarRegisterExternalTexture(
|
||||
texture_registrar_ref_, &info);
|
||||
return texture_id;
|
||||
} else if (auto gpu_surface_texture =
|
||||
std::get_if<GpuSurfaceTexture>(texture)) {
|
||||
info.type = kFlutterDesktopGpuSurfaceTexture;
|
||||
info.gpu_surface_config.struct_size =
|
||||
sizeof(FlutterDesktopGpuSurfaceTextureConfig);
|
||||
info.gpu_surface_config.type = gpu_surface_texture->surface_type();
|
||||
info.gpu_surface_config.user_data = gpu_surface_texture;
|
||||
info.gpu_surface_config.callback =
|
||||
[](size_t width, size_t height,
|
||||
void* user_data) -> const FlutterDesktopGpuSurfaceDescriptor* {
|
||||
auto texture = static_cast<GpuSurfaceTexture*>(user_data);
|
||||
return texture->ObtainDescriptor(width, height);
|
||||
};
|
||||
} else {
|
||||
std::cerr << "Attempting to register unknown texture variant." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::cerr << "Attempting to register unknown texture variant." << std::endl;
|
||||
return -1;
|
||||
int64_t texture_id = FlutterDesktopTextureRegistrarRegisterExternalTexture(
|
||||
texture_registrar_ref_, &info);
|
||||
return texture_id;
|
||||
} // namespace flutter
|
||||
|
||||
bool TextureRegistrarImpl::MarkTextureFrameAvailable(int64_t texture_id) {
|
||||
|
||||
@ -42,10 +42,40 @@ class PixelBufferTexture {
|
||||
const CopyBufferCallback copy_buffer_callback_;
|
||||
};
|
||||
|
||||
// A GPU surface-based texture.
|
||||
class GpuSurfaceTexture {
|
||||
public:
|
||||
// A callback used for retrieving surface descriptors.
|
||||
typedef std::function<
|
||||
const FlutterDesktopGpuSurfaceDescriptor*(size_t width, size_t height)>
|
||||
ObtainDescriptorCallback;
|
||||
|
||||
GpuSurfaceTexture(FlutterDesktopGpuSurfaceType surface_type,
|
||||
ObtainDescriptorCallback obtain_descriptor_callback)
|
||||
: surface_type_(surface_type),
|
||||
obtain_descriptor_callback_(obtain_descriptor_callback) {}
|
||||
|
||||
// Returns the callback-provided FlutterDesktopGpuSurfaceDescriptor that
|
||||
// contains the surface handle. The intended surface size is specified by
|
||||
// |width| and |height|.
|
||||
const FlutterDesktopGpuSurfaceDescriptor* ObtainDescriptor(
|
||||
size_t width,
|
||||
size_t height) const {
|
||||
return obtain_descriptor_callback_(width, height);
|
||||
}
|
||||
|
||||
// Gets the surface type.
|
||||
FlutterDesktopGpuSurfaceType surface_type() const { return surface_type_; }
|
||||
|
||||
private:
|
||||
const FlutterDesktopGpuSurfaceType surface_type_;
|
||||
const ObtainDescriptorCallback obtain_descriptor_callback_;
|
||||
};
|
||||
|
||||
// The available texture variants.
|
||||
// Only PixelBufferTexture is currently implemented.
|
||||
// Other variants are expected to be added in the future.
|
||||
typedef std::variant<PixelBufferTexture> TextureVariant;
|
||||
typedef std::variant<PixelBufferTexture, GpuSurfaceTexture> TextureVariant;
|
||||
|
||||
// An object keeping track of external textures.
|
||||
//
|
||||
|
||||
@ -23,9 +23,35 @@ typedef struct FlutterDesktopTextureRegistrar*
|
||||
// Additional types may be added in the future.
|
||||
typedef enum {
|
||||
// A Pixel buffer-based texture.
|
||||
kFlutterDesktopPixelBufferTexture
|
||||
kFlutterDesktopPixelBufferTexture,
|
||||
// A platform-specific GPU surface-backed texture.
|
||||
kFlutterDesktopGpuSurfaceTexture
|
||||
} FlutterDesktopTextureType;
|
||||
|
||||
// Supported GPU surface types.
|
||||
typedef enum {
|
||||
// Uninitialized.
|
||||
kFlutterDesktopGpuSurfaceTypeNone,
|
||||
// A DXGI shared texture handle (Windows only).
|
||||
// See
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/dxgi/nf-dxgi-idxgiresource-getsharedhandle
|
||||
kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle,
|
||||
// A |ID3D11Texture2D| (Windows only).
|
||||
kFlutterDesktopGpuSurfaceTypeD3d11Texture2D
|
||||
} FlutterDesktopGpuSurfaceType;
|
||||
|
||||
// Supported pixel formats.
|
||||
typedef enum {
|
||||
// Uninitialized.
|
||||
kFlutterDesktopPixelFormatNone,
|
||||
// Represents a 32-bit RGBA color format with 8 bits each for red, green, blue
|
||||
// and alpha.
|
||||
kFlutterDesktopPixelFormatRGBA8888,
|
||||
// Represents a 32-bit BGRA color format with 8 bits each for blue, green, red
|
||||
// and alpha.
|
||||
kFlutterDesktopPixelFormatBGRA8888
|
||||
} FlutterDesktopPixelFormat;
|
||||
|
||||
// An image buffer object.
|
||||
typedef struct {
|
||||
// The pixel data buffer.
|
||||
@ -40,20 +66,66 @@ typedef struct {
|
||||
void* release_context;
|
||||
} FlutterDesktopPixelBuffer;
|
||||
|
||||
// A GPU surface descriptor.
|
||||
typedef struct {
|
||||
// The size of this struct. Must be
|
||||
// sizeof(FlutterDesktopGpuSurfaceDescriptor).
|
||||
size_t struct_size;
|
||||
// The surface handle. The expected type depends on the
|
||||
// |FlutterDesktopGpuSurfaceType|.
|
||||
//
|
||||
// Provide a |ID3D11Texture2D*| when using
|
||||
// |kFlutterDesktopGpuSurfaceTypeD3d11Texture2D| or a |HANDLE| when using
|
||||
// |kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle|.
|
||||
//
|
||||
// The referenced resource needs to stay valid until it has been opened by
|
||||
// Flutter. Consider incrementing the resource's reference count in the
|
||||
// |FlutterDesktopGpuSurfaceTextureCallback| and registering a
|
||||
// |release_callback| for decrementing the reference count once it has been
|
||||
// opened.
|
||||
void* handle;
|
||||
// The physical width.
|
||||
size_t width;
|
||||
// The physical height.
|
||||
size_t height;
|
||||
// The visible width.
|
||||
// It might be less or equal to the physical |width|.
|
||||
size_t visible_width;
|
||||
// The visible height.
|
||||
// It might be less or equal to the physical |height|.
|
||||
size_t visible_height;
|
||||
// The pixel format which might be optional depending on the surface type.
|
||||
FlutterDesktopPixelFormat format;
|
||||
// An optional callback that gets invoked when the |handle| has been opened.
|
||||
void (*release_callback)(void* release_context);
|
||||
// Opaque data passed to |release_callback|.
|
||||
void* release_context;
|
||||
} FlutterDesktopGpuSurfaceDescriptor;
|
||||
|
||||
// The pixel buffer copy callback definition provided to
|
||||
// the Flutter engine to copy the texture.
|
||||
// It is invoked with the intended surface size specified by |width| and
|
||||
// |height| and the |user_data| held by FlutterDesktopPixelBufferTextureConfig.
|
||||
// |height| and the |user_data| held by
|
||||
// |FlutterDesktopPixelBufferTextureConfig|.
|
||||
//
|
||||
// As this is usually called from the render thread, the callee must take
|
||||
// care of proper synchronization. It also needs to be ensured that the
|
||||
// returned FlutterDesktopPixelBuffer isn't released prior to unregistering
|
||||
// returned |FlutterDesktopPixelBuffer| isn't released prior to unregistering
|
||||
// the corresponding texture.
|
||||
typedef const FlutterDesktopPixelBuffer* (
|
||||
*FlutterDesktopPixelBufferTextureCallback)(size_t width,
|
||||
size_t height,
|
||||
void* user_data);
|
||||
|
||||
// The GPU surface callback definition provided to the Flutter engine to obtain
|
||||
// the surface. It is invoked with the intended surface size specified by
|
||||
// |width| and |height| and the |user_data| held by
|
||||
// |FlutterDesktopGpuSurfaceTextureConfig|.
|
||||
typedef const FlutterDesktopGpuSurfaceDescriptor* (
|
||||
*FlutterDesktopGpuSurfaceTextureCallback)(size_t width,
|
||||
size_t height,
|
||||
void* user_data);
|
||||
|
||||
// An object used to configure pixel buffer textures.
|
||||
typedef struct {
|
||||
// The callback used by the engine to copy the pixel buffer object.
|
||||
@ -62,10 +134,25 @@ typedef struct {
|
||||
void* user_data;
|
||||
} FlutterDesktopPixelBufferTextureConfig;
|
||||
|
||||
// An object used to configure GPU-surface textures.
|
||||
typedef struct {
|
||||
// The size of this struct. Must be
|
||||
// sizeof(FlutterDesktopGpuSurfaceTextureConfig).
|
||||
size_t struct_size;
|
||||
// The concrete surface type (e.g.
|
||||
// |kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle|)
|
||||
FlutterDesktopGpuSurfaceType type;
|
||||
// The callback used by the engine to obtain the surface descriptor.
|
||||
FlutterDesktopGpuSurfaceTextureCallback callback;
|
||||
// Opaque data that will get passed to the provided |callback|.
|
||||
void* user_data;
|
||||
} FlutterDesktopGpuSurfaceTextureConfig;
|
||||
|
||||
typedef struct {
|
||||
FlutterDesktopTextureType type;
|
||||
union {
|
||||
FlutterDesktopPixelBufferTextureConfig pixel_buffer_config;
|
||||
FlutterDesktopGpuSurfaceTextureConfig gpu_surface_config;
|
||||
};
|
||||
} FlutterDesktopTextureInfo;
|
||||
|
||||
|
||||
@ -59,8 +59,11 @@ source_set("flutter_windows_source") {
|
||||
"dpi_utils_win32.h",
|
||||
"event_watcher_win32.cc",
|
||||
"event_watcher_win32.h",
|
||||
"external_texture_gl.cc",
|
||||
"external_texture_gl.h",
|
||||
"external_texture.h",
|
||||
"external_texture_d3d.cc",
|
||||
"external_texture_d3d.h",
|
||||
"external_texture_pixelbuffer.cc",
|
||||
"external_texture_pixelbuffer.h",
|
||||
"flutter_key_map.cc",
|
||||
"flutter_platform_node_delegate_win32.cc",
|
||||
"flutter_platform_node_delegate_win32.h",
|
||||
|
||||
@ -174,6 +174,9 @@ bool AngleSurfaceManager::Initialize() {
|
||||
void AngleSurfaceManager::CleanUp() {
|
||||
EGLBoolean result = EGL_FALSE;
|
||||
|
||||
// Needs to be reset before destroying the EGLContext.
|
||||
resolved_device_.Reset();
|
||||
|
||||
if (egl_display_ != EGL_NO_DISPLAY && egl_context_ != EGL_NO_CONTEXT) {
|
||||
result = eglDestroyContext(egl_display_, egl_context_);
|
||||
egl_context_ = EGL_NO_CONTEXT;
|
||||
@ -288,4 +291,44 @@ EGLBoolean AngleSurfaceManager::SwapBuffers() {
|
||||
return (eglSwapBuffers(egl_display_, render_surface_));
|
||||
}
|
||||
|
||||
EGLSurface AngleSurfaceManager::CreateSurfaceFromHandle(
|
||||
EGLenum handle_type,
|
||||
EGLClientBuffer handle,
|
||||
const EGLint* attributes) const {
|
||||
return eglCreatePbufferFromClientBuffer(egl_display_, handle_type, handle,
|
||||
egl_config_, attributes);
|
||||
}
|
||||
|
||||
bool AngleSurfaceManager::GetDevice(ID3D11Device** device) {
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
if (!resolved_device_) {
|
||||
PFNEGLQUERYDISPLAYATTRIBEXTPROC egl_query_display_attrib_EXT =
|
||||
reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(
|
||||
eglGetProcAddress("eglQueryDisplayAttribEXT"));
|
||||
|
||||
PFNEGLQUERYDEVICEATTRIBEXTPROC egl_query_device_attrib_EXT =
|
||||
reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC>(
|
||||
eglGetProcAddress("eglQueryDeviceAttribEXT"));
|
||||
|
||||
if (!egl_query_display_attrib_EXT || !egl_query_device_attrib_EXT) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EGLAttrib egl_device = 0;
|
||||
EGLAttrib angle_device = 0;
|
||||
if (egl_query_display_attrib_EXT(egl_display_, EGL_DEVICE_EXT,
|
||||
&egl_device) == EGL_TRUE) {
|
||||
if (egl_query_device_attrib_EXT(
|
||||
reinterpret_cast<EGLDeviceEXT>(egl_device),
|
||||
EGL_D3D11_DEVICE_ANGLE, &angle_device) == EGL_TRUE) {
|
||||
resolved_device_ = reinterpret_cast<ID3D11Device*>(angle_device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resolved_device_.CopyTo(device);
|
||||
return (resolved_device_ != nullptr);
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -13,7 +13,9 @@
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
// Windows platform specific includes
|
||||
#include <d3d11.h>
|
||||
#include <windows.h>
|
||||
#include <wrl/client.h>
|
||||
#include <memory>
|
||||
|
||||
#include "window_binding_handler.h"
|
||||
@ -69,15 +71,25 @@ class AngleSurfaceManager {
|
||||
// not null.
|
||||
EGLBoolean SwapBuffers();
|
||||
|
||||
private:
|
||||
bool Initialize();
|
||||
void CleanUp();
|
||||
// Creates a |EGLSurface| from the provided handle.
|
||||
EGLSurface CreateSurfaceFromHandle(EGLenum handle_type,
|
||||
EGLClientBuffer handle,
|
||||
const EGLint* attributes) const;
|
||||
|
||||
// Gets the |EGLDisplay|.
|
||||
EGLDisplay egl_display() const { return egl_display_; };
|
||||
|
||||
// Gets the |ID3D11Device| chosen by ANGLE.
|
||||
bool GetDevice(ID3D11Device** device);
|
||||
|
||||
private:
|
||||
// Creates a new surface manager retaining reference to the passed-in target
|
||||
// for the lifetime of the manager.
|
||||
AngleSurfaceManager();
|
||||
|
||||
bool Initialize();
|
||||
void CleanUp();
|
||||
|
||||
// Attempts to initialize EGL using ANGLE.
|
||||
bool InitializeEGL(
|
||||
PFNEGLGETPLATFORMDISPLAYEXTPROC egl_get_platform_display_EXT,
|
||||
@ -108,6 +120,9 @@ class AngleSurfaceManager {
|
||||
EGLint surface_width_ = 0;
|
||||
EGLint surface_height_ = 0;
|
||||
|
||||
// The current D3D device.
|
||||
Microsoft::WRL::ComPtr<ID3D11Device> resolved_device_;
|
||||
|
||||
// Number of active instances of AngleSurfaceManager
|
||||
static int instance_count_;
|
||||
};
|
||||
|
||||
57
engine/src/flutter/shell/platform/windows/external_texture.h
Normal file
57
engine/src/flutter/shell/platform/windows/external_texture.h
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_H_
|
||||
|
||||
#include "flutter/shell/platform/embedder/embedder.h"
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
namespace flutter {
|
||||
|
||||
typedef void (*glGenTexturesProc)(GLsizei n, GLuint* textures);
|
||||
typedef void (*glDeleteTexturesProc)(GLsizei n, const GLuint* textures);
|
||||
typedef void (*glBindTextureProc)(GLenum target, GLuint texture);
|
||||
typedef void (*glTexParameteriProc)(GLenum target, GLenum pname, GLint param);
|
||||
typedef void (*glTexImage2DProc)(GLenum target,
|
||||
GLint level,
|
||||
GLint internalformat,
|
||||
GLsizei width,
|
||||
GLsizei height,
|
||||
GLint border,
|
||||
GLenum format,
|
||||
GLenum type,
|
||||
const void* data);
|
||||
|
||||
// A struct containing pointers to resolved gl* functions.
|
||||
struct GlProcs {
|
||||
glGenTexturesProc glGenTextures;
|
||||
glDeleteTexturesProc glDeleteTextures;
|
||||
glBindTextureProc glBindTexture;
|
||||
glTexParameteriProc glTexParameteri;
|
||||
glTexImage2DProc glTexImage2D;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
// Abstract external texture.
|
||||
class ExternalTexture {
|
||||
public:
|
||||
virtual ~ExternalTexture() = default;
|
||||
|
||||
// Returns the unique id of this texture.
|
||||
int64_t texture_id() const { return reinterpret_cast<int64_t>(this); };
|
||||
|
||||
// Attempts to populate the specified |opengl_texture| with texture details
|
||||
// such as the name, width, height and the pixel format.
|
||||
// Returns true on success.
|
||||
virtual bool PopulateTexture(size_t width,
|
||||
size_t height,
|
||||
FlutterOpenGLTexture* opengl_texture) = 0;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_H_
|
||||
@ -0,0 +1,122 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/shell/platform/windows/external_texture_d3d.h"
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <EGL/eglext.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "flutter/shell/platform/embedder/embedder_struct_macros.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
ExternalTextureD3d::ExternalTextureD3d(
|
||||
FlutterDesktopGpuSurfaceType type,
|
||||
const FlutterDesktopGpuSurfaceTextureCallback texture_callback,
|
||||
void* user_data,
|
||||
const AngleSurfaceManager* surface_manager,
|
||||
const GlProcs& gl_procs)
|
||||
: type_(type),
|
||||
texture_callback_(texture_callback),
|
||||
user_data_(user_data),
|
||||
surface_manager_(surface_manager),
|
||||
gl_(gl_procs) {}
|
||||
|
||||
ExternalTextureD3d::~ExternalTextureD3d() {
|
||||
ReleaseImage();
|
||||
|
||||
if (gl_texture_ != 0) {
|
||||
gl_.glDeleteTextures(1, &gl_texture_);
|
||||
}
|
||||
}
|
||||
|
||||
bool ExternalTextureD3d::PopulateTexture(size_t width,
|
||||
size_t height,
|
||||
FlutterOpenGLTexture* opengl_texture) {
|
||||
const FlutterDesktopGpuSurfaceDescriptor* descriptor =
|
||||
texture_callback_(width, height, user_data_);
|
||||
|
||||
if (!CreateOrUpdateTexture(descriptor)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Populate the texture object used by the engine.
|
||||
opengl_texture->target = GL_TEXTURE_2D;
|
||||
opengl_texture->name = gl_texture_;
|
||||
opengl_texture->format = GL_RGBA;
|
||||
opengl_texture->destruction_callback = nullptr;
|
||||
opengl_texture->user_data = nullptr;
|
||||
opengl_texture->width = SAFE_ACCESS(descriptor, visible_width, 0);
|
||||
opengl_texture->height = SAFE_ACCESS(descriptor, visible_height, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ExternalTextureD3d::ReleaseImage() {
|
||||
if (egl_surface_ != EGL_NO_SURFACE) {
|
||||
eglReleaseTexImage(surface_manager_->egl_display(), egl_surface_,
|
||||
EGL_BACK_BUFFER);
|
||||
eglDestroySurface(surface_manager_->egl_display(), egl_surface_);
|
||||
egl_surface_ = EGL_NO_SURFACE;
|
||||
}
|
||||
}
|
||||
|
||||
bool ExternalTextureD3d::CreateOrUpdateTexture(
|
||||
const FlutterDesktopGpuSurfaceDescriptor* descriptor) {
|
||||
if (descriptor == nullptr ||
|
||||
SAFE_ACCESS(descriptor, handle, nullptr) == nullptr) {
|
||||
ReleaseImage();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (gl_texture_ == 0) {
|
||||
gl_.glGenTextures(1, &gl_texture_);
|
||||
|
||||
gl_.glBindTexture(GL_TEXTURE_2D, gl_texture_);
|
||||
gl_.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
gl_.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
gl_.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
gl_.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
} else {
|
||||
gl_.glBindTexture(GL_TEXTURE_2D, gl_texture_);
|
||||
}
|
||||
|
||||
auto handle = SAFE_ACCESS(descriptor, handle, nullptr);
|
||||
if (handle != last_surface_handle_) {
|
||||
ReleaseImage();
|
||||
|
||||
EGLint attributes[] = {
|
||||
EGL_WIDTH,
|
||||
static_cast<EGLint>(SAFE_ACCESS(descriptor, width, 0)),
|
||||
EGL_HEIGHT,
|
||||
static_cast<EGLint>(SAFE_ACCESS(descriptor, height, 0)),
|
||||
EGL_TEXTURE_TARGET,
|
||||
EGL_TEXTURE_2D,
|
||||
EGL_TEXTURE_FORMAT,
|
||||
EGL_TEXTURE_RGBA, // always EGL_TEXTURE_RGBA
|
||||
EGL_NONE};
|
||||
|
||||
egl_surface_ = surface_manager_->CreateSurfaceFromHandle(
|
||||
(type_ == kFlutterDesktopGpuSurfaceTypeD3d11Texture2D)
|
||||
? EGL_D3D_TEXTURE_ANGLE
|
||||
: EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
|
||||
handle, attributes);
|
||||
|
||||
if (egl_surface_ == EGL_NO_SURFACE ||
|
||||
eglBindTexImage(surface_manager_->egl_display(), egl_surface_,
|
||||
EGL_BACK_BUFFER) == EGL_FALSE) {
|
||||
std::cerr << "Binding D3D surface failed." << std::endl;
|
||||
}
|
||||
last_surface_handle_ = handle;
|
||||
}
|
||||
|
||||
auto release_callback = SAFE_ACCESS(descriptor, release_callback, nullptr);
|
||||
if (release_callback) {
|
||||
release_callback(SAFE_ACCESS(descriptor, release_context, nullptr));
|
||||
}
|
||||
return egl_surface_ != EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
@ -0,0 +1,54 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_D3D_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_D3D_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/shell/platform/common/public/flutter_texture_registrar.h"
|
||||
#include "flutter/shell/platform/windows/angle_surface_manager.h"
|
||||
#include "flutter/shell/platform/windows/external_texture.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
// An external texture that is backed by a DXGI surface.
|
||||
class ExternalTextureD3d : public ExternalTexture {
|
||||
public:
|
||||
ExternalTextureD3d(
|
||||
FlutterDesktopGpuSurfaceType type,
|
||||
const FlutterDesktopGpuSurfaceTextureCallback texture_callback,
|
||||
void* user_data,
|
||||
const AngleSurfaceManager* surface_manager,
|
||||
const GlProcs& gl_procs);
|
||||
virtual ~ExternalTextureD3d();
|
||||
|
||||
// |ExternalTexture|
|
||||
bool PopulateTexture(size_t width,
|
||||
size_t height,
|
||||
FlutterOpenGLTexture* opengl_texture) override;
|
||||
|
||||
private:
|
||||
// Creates or updates the backing texture and associates it with the provided
|
||||
// surface.
|
||||
bool CreateOrUpdateTexture(
|
||||
const FlutterDesktopGpuSurfaceDescriptor* descriptor);
|
||||
// Detaches the previously attached surface, if any.
|
||||
void ReleaseImage();
|
||||
|
||||
FlutterDesktopGpuSurfaceType type_;
|
||||
const FlutterDesktopGpuSurfaceTextureCallback texture_callback_;
|
||||
void* const user_data_;
|
||||
const AngleSurfaceManager* surface_manager_;
|
||||
const GlProcs& gl_;
|
||||
GLuint gl_texture_ = 0;
|
||||
EGLSurface egl_surface_ = EGL_NO_SURFACE;
|
||||
void* last_surface_handle_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_D3D_H_
|
||||
@ -1,85 +0,0 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_GL_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_GL_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/shell/platform/common/public/flutter_texture_registrar.h"
|
||||
#include "flutter/shell/platform/embedder/embedder.h"
|
||||
|
||||
#include <GLES2/gl2.h>
|
||||
#include <GLES2/gl2ext.h>
|
||||
|
||||
namespace flutter {
|
||||
|
||||
typedef struct ExternalTextureGLState ExternalTextureGLState;
|
||||
|
||||
typedef void (*glGenTexturesProc)(GLsizei n, GLuint* textures);
|
||||
typedef void (*glDeleteTexturesProc)(GLsizei n, const GLuint* textures);
|
||||
typedef void (*glBindTextureProc)(GLenum target, GLuint texture);
|
||||
typedef void (*glTexParameteriProc)(GLenum target, GLenum pname, GLint param);
|
||||
typedef void (*glTexImage2DProc)(GLenum target,
|
||||
GLint level,
|
||||
GLint internalformat,
|
||||
GLsizei width,
|
||||
GLsizei height,
|
||||
GLint border,
|
||||
GLenum format,
|
||||
GLenum type,
|
||||
const void* data);
|
||||
|
||||
// A struct containing pointers to resolved gl* functions.
|
||||
struct GlProcs {
|
||||
glGenTexturesProc glGenTextures;
|
||||
glDeleteTexturesProc glDeleteTextures;
|
||||
glBindTextureProc glBindTexture;
|
||||
glTexParameteriProc glTexParameteri;
|
||||
glTexImage2DProc glTexImage2D;
|
||||
bool valid;
|
||||
};
|
||||
|
||||
// An abstraction of an OpenGL texture.
|
||||
class ExternalTextureGL {
|
||||
public:
|
||||
ExternalTextureGL(FlutterDesktopPixelBufferTextureCallback texture_callback,
|
||||
void* user_data,
|
||||
const GlProcs& gl_procs);
|
||||
|
||||
virtual ~ExternalTextureGL();
|
||||
|
||||
// Returns the unique id of this texture.
|
||||
int64_t texture_id() { return reinterpret_cast<int64_t>(this); }
|
||||
|
||||
void MarkFrameAvailable();
|
||||
|
||||
// Attempts to populate the specified |opengl_texture| with texture details
|
||||
// such as the name, width, height and the pixel format upon successfully
|
||||
// copying the buffer provided by |texture_callback_|. See |CopyPixelBuffer|.
|
||||
// Returns true on success or false if the pixel buffer could not be copied.
|
||||
bool PopulateTexture(size_t width,
|
||||
size_t height,
|
||||
FlutterOpenGLTexture* opengl_texture);
|
||||
|
||||
private:
|
||||
// Attempts to copy the pixel buffer returned by |texture_callback_| to
|
||||
// OpenGL.
|
||||
// The |width| and |height| will be set to the actual bounds of the copied
|
||||
// pixel buffer.
|
||||
// Returns true on success or false if the pixel buffer returned
|
||||
// by |texture_callback_| was invalid.
|
||||
bool CopyPixelBuffer(size_t& width, size_t& height);
|
||||
|
||||
std::unique_ptr<ExternalTextureGLState> state_;
|
||||
FlutterDesktopPixelBufferTextureCallback texture_callback_ = nullptr;
|
||||
void* user_data_ = nullptr;
|
||||
const GlProcs& gl_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_GL_H_
|
||||
@ -2,33 +2,33 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "flutter/shell/platform/windows/external_texture_gl.h"
|
||||
#include "flutter/shell/platform/windows/external_texture_pixelbuffer.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
struct ExternalTextureGLState {
|
||||
struct ExternalTexturePixelBufferState {
|
||||
GLuint gl_texture = 0;
|
||||
};
|
||||
|
||||
ExternalTextureGL::ExternalTextureGL(
|
||||
ExternalTexturePixelBuffer::ExternalTexturePixelBuffer(
|
||||
FlutterDesktopPixelBufferTextureCallback texture_callback,
|
||||
void* user_data,
|
||||
const GlProcs& gl_procs)
|
||||
: state_(std::make_unique<ExternalTextureGLState>()),
|
||||
: state_(std::make_unique<ExternalTexturePixelBufferState>()),
|
||||
texture_callback_(texture_callback),
|
||||
user_data_(user_data),
|
||||
gl_(gl_procs) {}
|
||||
|
||||
ExternalTextureGL::~ExternalTextureGL() {
|
||||
const auto& gl = GlProcs();
|
||||
ExternalTexturePixelBuffer::~ExternalTexturePixelBuffer() {
|
||||
if (state_->gl_texture != 0) {
|
||||
gl_.glDeleteTextures(1, &state_->gl_texture);
|
||||
}
|
||||
}
|
||||
|
||||
bool ExternalTextureGL::PopulateTexture(size_t width,
|
||||
size_t height,
|
||||
FlutterOpenGLTexture* opengl_texture) {
|
||||
bool ExternalTexturePixelBuffer::PopulateTexture(
|
||||
size_t width,
|
||||
size_t height,
|
||||
FlutterOpenGLTexture* opengl_texture) {
|
||||
if (!CopyPixelBuffer(width, height)) {
|
||||
return false;
|
||||
}
|
||||
@ -45,7 +45,8 @@ bool ExternalTextureGL::PopulateTexture(size_t width,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ExternalTextureGL::CopyPixelBuffer(size_t& width, size_t& height) {
|
||||
bool ExternalTexturePixelBuffer::CopyPixelBuffer(size_t& width,
|
||||
size_t& height) {
|
||||
const FlutterDesktopPixelBuffer* pixel_buffer =
|
||||
texture_callback_(width, height, user_data_);
|
||||
if (!pixel_buffer || !pixel_buffer->buffer) {
|
||||
@ -0,0 +1,52 @@
|
||||
// Copyright 2013 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_PIXELBUFFER_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_PIXELBUFFER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/shell/platform/common/public/flutter_texture_registrar.h"
|
||||
|
||||
#include "flutter/shell/platform/windows/external_texture.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
typedef struct ExternalTexturePixelBufferState ExternalTexturePixelBufferState;
|
||||
|
||||
// An abstraction of an pixel-buffer based texture.
|
||||
class ExternalTexturePixelBuffer : public ExternalTexture {
|
||||
public:
|
||||
ExternalTexturePixelBuffer(
|
||||
FlutterDesktopPixelBufferTextureCallback texture_callback,
|
||||
void* user_data,
|
||||
const GlProcs& gl_procs);
|
||||
|
||||
virtual ~ExternalTexturePixelBuffer();
|
||||
|
||||
// |ExternalTexture|
|
||||
bool PopulateTexture(size_t width,
|
||||
size_t height,
|
||||
FlutterOpenGLTexture* opengl_texture) override;
|
||||
|
||||
private:
|
||||
// Attempts to copy the pixel buffer returned by |texture_callback_| to
|
||||
// OpenGL.
|
||||
// The |width| and |height| will be set to the actual bounds of the copied
|
||||
// pixel buffer.
|
||||
// Returns true on success or false if the pixel buffer returned
|
||||
// by |texture_callback_| was invalid.
|
||||
bool CopyPixelBuffer(size_t& width, size_t& height);
|
||||
|
||||
std::unique_ptr<ExternalTexturePixelBufferState> state_;
|
||||
FlutterDesktopPixelBufferTextureCallback texture_callback_ = nullptr;
|
||||
void* const user_data_ = nullptr;
|
||||
const GlProcs& gl_;
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_SHELL_PLATFORM_WINDOWS_EXTERNAL_TEXTURE_PIXELBUFFER_H_
|
||||
@ -4,11 +4,18 @@
|
||||
|
||||
#include "flutter/shell/platform/windows/flutter_windows_texture_registrar.h"
|
||||
|
||||
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <mutex>
|
||||
|
||||
#include "flutter/shell/platform/embedder/embedder_struct_macros.h"
|
||||
#include "flutter/shell/platform/windows/external_texture_d3d.h"
|
||||
#include "flutter/shell/platform/windows/external_texture_pixelbuffer.h"
|
||||
#include "flutter/shell/platform/windows/flutter_windows_engine.h"
|
||||
|
||||
namespace {
|
||||
static constexpr int64_t kInvalidTexture = -1;
|
||||
}
|
||||
|
||||
namespace flutter {
|
||||
|
||||
FlutterWindowsTextureRegistrar::FlutterWindowsTextureRegistrar(
|
||||
@ -19,28 +26,48 @@ FlutterWindowsTextureRegistrar::FlutterWindowsTextureRegistrar(
|
||||
int64_t FlutterWindowsTextureRegistrar::RegisterTexture(
|
||||
const FlutterDesktopTextureInfo* texture_info) {
|
||||
if (!gl_procs_.valid) {
|
||||
return -1;
|
||||
return kInvalidTexture;
|
||||
}
|
||||
|
||||
if (texture_info->type != kFlutterDesktopPixelBufferTexture) {
|
||||
std::cerr << "Attempted to register texture of unsupport type."
|
||||
<< std::endl;
|
||||
return -1;
|
||||
if (texture_info->type == kFlutterDesktopPixelBufferTexture) {
|
||||
if (!texture_info->pixel_buffer_config.callback) {
|
||||
std::cerr << "Invalid pixel buffer texture callback." << std::endl;
|
||||
return kInvalidTexture;
|
||||
}
|
||||
|
||||
return EmplaceTexture(std::make_unique<flutter::ExternalTexturePixelBuffer>(
|
||||
texture_info->pixel_buffer_config.callback,
|
||||
texture_info->pixel_buffer_config.user_data, gl_procs_));
|
||||
} else if (texture_info->type == kFlutterDesktopGpuSurfaceTexture) {
|
||||
const FlutterDesktopGpuSurfaceTextureConfig* gpu_surface_config =
|
||||
&texture_info->gpu_surface_config;
|
||||
auto surface_type = SAFE_ACCESS(gpu_surface_config, type,
|
||||
kFlutterDesktopGpuSurfaceTypeNone);
|
||||
if (surface_type == kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle ||
|
||||
surface_type == kFlutterDesktopGpuSurfaceTypeD3d11Texture2D) {
|
||||
auto callback = SAFE_ACCESS(gpu_surface_config, callback, nullptr);
|
||||
if (!callback) {
|
||||
std::cerr << "Invalid GPU surface descriptor callback." << std::endl;
|
||||
return kInvalidTexture;
|
||||
}
|
||||
|
||||
auto user_data = SAFE_ACCESS(gpu_surface_config, user_data, nullptr);
|
||||
return EmplaceTexture(std::make_unique<flutter::ExternalTextureD3d>(
|
||||
surface_type, callback, user_data, engine_->surface_manager(),
|
||||
gl_procs_));
|
||||
}
|
||||
}
|
||||
|
||||
if (!texture_info->pixel_buffer_config.callback) {
|
||||
std::cerr << "Invalid pixel buffer texture callback." << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
auto texture_gl = std::make_unique<flutter::ExternalTextureGL>(
|
||||
texture_info->pixel_buffer_config.callback,
|
||||
texture_info->pixel_buffer_config.user_data, gl_procs_);
|
||||
int64_t texture_id = texture_gl->texture_id();
|
||||
std::cerr << "Attempted to register texture of unsupport type." << std::endl;
|
||||
return kInvalidTexture;
|
||||
}
|
||||
|
||||
int64_t FlutterWindowsTextureRegistrar::EmplaceTexture(
|
||||
std::unique_ptr<ExternalTexture> texture) {
|
||||
int64_t texture_id = texture->texture_id();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(map_mutex_);
|
||||
textures_[texture_id] = std::move(texture_gl);
|
||||
textures_[texture_id] = std::move(texture);
|
||||
}
|
||||
|
||||
engine_->task_runner()->RunNowOrPostTask([engine = engine_, texture_id]() {
|
||||
@ -79,7 +106,7 @@ bool FlutterWindowsTextureRegistrar::PopulateTexture(
|
||||
size_t width,
|
||||
size_t height,
|
||||
FlutterOpenGLTexture* opengl_texture) {
|
||||
flutter::ExternalTextureGL* texture;
|
||||
flutter::ExternalTexture* texture;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(map_mutex_);
|
||||
auto it = textures_.find(texture_id);
|
||||
|
||||
@ -9,7 +9,8 @@
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "flutter/shell/platform/windows/external_texture_gl.h"
|
||||
#include "flutter/shell/platform/common/public/flutter_texture_registrar.h"
|
||||
#include "flutter/shell/platform/windows/external_texture.h"
|
||||
|
||||
namespace flutter {
|
||||
|
||||
@ -50,9 +51,11 @@ class FlutterWindowsTextureRegistrar {
|
||||
const GlProcs& gl_procs_;
|
||||
|
||||
// All registered textures, keyed by their IDs.
|
||||
std::unordered_map<int64_t, std::unique_ptr<flutter::ExternalTextureGL>>
|
||||
std::unordered_map<int64_t, std::unique_ptr<flutter::ExternalTexture>>
|
||||
textures_;
|
||||
std::mutex map_mutex_;
|
||||
|
||||
int64_t EmplaceTexture(std::unique_ptr<ExternalTexture> texture);
|
||||
};
|
||||
|
||||
}; // namespace flutter
|
||||
|
||||
@ -14,6 +14,8 @@
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
using Microsoft::WRL::ComPtr;
|
||||
|
||||
namespace {
|
||||
// Returns an engine instance configured with dummy project path values.
|
||||
std::unique_ptr<FlutterWindowsEngine> GetTestEngine() {
|
||||
@ -22,14 +24,46 @@ std::unique_ptr<FlutterWindowsEngine> GetTestEngine() {
|
||||
properties.icu_data_path = L"C:\\foo\\icudtl.dat";
|
||||
properties.aot_library_path = L"C:\\foo\\aot.so";
|
||||
FlutterProjectBundle project(properties);
|
||||
return std::make_unique<FlutterWindowsEngine>(project);
|
||||
auto engine = std::make_unique<FlutterWindowsEngine>(project);
|
||||
|
||||
EngineModifier modifier(engine.get());
|
||||
modifier.embedder_api().RegisterExternalTexture =
|
||||
MOCK_ENGINE_PROC(RegisterExternalTexture,
|
||||
([](auto engine, auto texture_id) { return kSuccess; }));
|
||||
|
||||
return engine;
|
||||
}
|
||||
|
||||
// Creates a ID3D11Texture2D with the specified size.
|
||||
ComPtr<ID3D11Texture2D> CreateD3dTexture(FlutterWindowsEngine* engine,
|
||||
UINT width,
|
||||
UINT height) {
|
||||
ComPtr<ID3D11Device> d3d_device;
|
||||
ComPtr<ID3D11Texture2D> d3d_texture;
|
||||
if (engine->surface_manager()->GetDevice(d3d_device.GetAddressOf())) {
|
||||
D3D11_TEXTURE2D_DESC texture_description = {};
|
||||
texture_description.MipLevels = 1;
|
||||
texture_description.SampleDesc.Count = 1;
|
||||
texture_description.BindFlags = D3D11_BIND_RENDER_TARGET;
|
||||
texture_description.Usage = D3D11_USAGE_DEFAULT;
|
||||
texture_description.CPUAccessFlags = 0;
|
||||
texture_description.ArraySize = 1;
|
||||
texture_description.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
texture_description.Height = width;
|
||||
texture_description.Width = height;
|
||||
texture_description.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
|
||||
|
||||
d3d_device->CreateTexture2D(&texture_description, nullptr,
|
||||
d3d_texture.GetAddressOf());
|
||||
}
|
||||
return d3d_texture;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(FlutterWindowsTextureRegistrarTest, CreateDestroy) {
|
||||
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
|
||||
std::unique_ptr<MockGlFunctions> gl = std::make_unique<MockGlFunctions>();
|
||||
|
||||
FlutterWindowsTextureRegistrar registrar(engine.get(), gl->gl_procs());
|
||||
|
||||
EXPECT_TRUE(true);
|
||||
@ -107,9 +141,7 @@ TEST(FlutterWindowsTextureRegistrarTest, RegisterUnknownTextureType) {
|
||||
|
||||
TEST(FlutterWindowsTextureRegistrarTest, PopulatePixelBufferTexture) {
|
||||
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
|
||||
EngineModifier modifier(engine.get());
|
||||
std::unique_ptr<MockGlFunctions> gl = std::make_unique<MockGlFunctions>();
|
||||
|
||||
FlutterWindowsTextureRegistrar registrar(engine.get(), gl->gl_procs());
|
||||
|
||||
bool release_callback_called = false;
|
||||
@ -136,9 +168,109 @@ TEST(FlutterWindowsTextureRegistrarTest, PopulatePixelBufferTexture) {
|
||||
return reinterpret_cast<const FlutterDesktopPixelBuffer*>(user_data);
|
||||
};
|
||||
|
||||
modifier.embedder_api().RegisterExternalTexture =
|
||||
MOCK_ENGINE_PROC(RegisterExternalTexture,
|
||||
([](auto engine, auto texture_id) { return kSuccess; }));
|
||||
FlutterOpenGLTexture flutter_texture = {};
|
||||
auto texture_id = registrar.RegisterTexture(&texture_info);
|
||||
EXPECT_NE(texture_id, -1);
|
||||
|
||||
auto result =
|
||||
registrar.PopulateTexture(texture_id, 640, 480, &flutter_texture);
|
||||
EXPECT_TRUE(result);
|
||||
EXPECT_EQ(flutter_texture.width, width);
|
||||
EXPECT_EQ(flutter_texture.height, height);
|
||||
EXPECT_EQ(flutter_texture.target, GL_TEXTURE_2D);
|
||||
EXPECT_TRUE(release_callback_called);
|
||||
}
|
||||
|
||||
TEST(FlutterWindowsTextureRegistrarTest, PopulateD3dTextureWithHandle) {
|
||||
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
|
||||
std::unique_ptr<MockGlFunctions> gl = std::make_unique<MockGlFunctions>();
|
||||
FlutterWindowsTextureRegistrar registrar(engine.get(), gl->gl_procs());
|
||||
|
||||
UINT width = 100;
|
||||
UINT height = 100;
|
||||
auto d3d_texture = CreateD3dTexture(engine.get(), width, height);
|
||||
EXPECT_TRUE(d3d_texture);
|
||||
|
||||
ComPtr<IDXGIResource> shared_resource;
|
||||
EXPECT_TRUE(SUCCEEDED(d3d_texture.As(&shared_resource)));
|
||||
|
||||
HANDLE shared_handle;
|
||||
EXPECT_TRUE(SUCCEEDED(shared_resource->GetSharedHandle(&shared_handle)));
|
||||
|
||||
bool release_callback_called = false;
|
||||
FlutterDesktopGpuSurfaceDescriptor surface_descriptor = {};
|
||||
surface_descriptor.struct_size = sizeof(FlutterDesktopGpuSurfaceDescriptor);
|
||||
surface_descriptor.handle = shared_handle;
|
||||
surface_descriptor.width = surface_descriptor.visible_width = width;
|
||||
surface_descriptor.height = surface_descriptor.visible_height = height;
|
||||
surface_descriptor.release_context = &release_callback_called;
|
||||
surface_descriptor.release_callback = [](void* release_context) {
|
||||
bool* called = reinterpret_cast<bool*>(release_context);
|
||||
*called = true;
|
||||
};
|
||||
|
||||
FlutterDesktopTextureInfo texture_info = {};
|
||||
texture_info.type = kFlutterDesktopGpuSurfaceTexture;
|
||||
texture_info.gpu_surface_config.struct_size =
|
||||
sizeof(FlutterDesktopGpuSurfaceTextureConfig);
|
||||
texture_info.gpu_surface_config.type =
|
||||
kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle;
|
||||
texture_info.gpu_surface_config.user_data = &surface_descriptor;
|
||||
texture_info.gpu_surface_config.callback =
|
||||
[](size_t width, size_t height,
|
||||
void* user_data) -> const FlutterDesktopGpuSurfaceDescriptor* {
|
||||
return reinterpret_cast<const FlutterDesktopGpuSurfaceDescriptor*>(
|
||||
user_data);
|
||||
};
|
||||
|
||||
FlutterOpenGLTexture flutter_texture = {};
|
||||
auto texture_id = registrar.RegisterTexture(&texture_info);
|
||||
EXPECT_NE(texture_id, -1);
|
||||
|
||||
auto result =
|
||||
registrar.PopulateTexture(texture_id, 640, 480, &flutter_texture);
|
||||
EXPECT_TRUE(result);
|
||||
EXPECT_EQ(flutter_texture.width, width);
|
||||
EXPECT_EQ(flutter_texture.height, height);
|
||||
EXPECT_EQ(flutter_texture.target, GL_TEXTURE_2D);
|
||||
EXPECT_TRUE(release_callback_called);
|
||||
}
|
||||
|
||||
TEST(FlutterWindowsTextureRegistrarTest, PopulateD3dTexture) {
|
||||
std::unique_ptr<FlutterWindowsEngine> engine = GetTestEngine();
|
||||
std::unique_ptr<MockGlFunctions> gl = std::make_unique<MockGlFunctions>();
|
||||
FlutterWindowsTextureRegistrar registrar(engine.get(), gl->gl_procs());
|
||||
|
||||
UINT width = 100;
|
||||
UINT height = 100;
|
||||
auto d3d_texture = CreateD3dTexture(engine.get(), width, height);
|
||||
EXPECT_TRUE(d3d_texture);
|
||||
|
||||
bool release_callback_called = false;
|
||||
FlutterDesktopGpuSurfaceDescriptor surface_descriptor = {};
|
||||
surface_descriptor.struct_size = sizeof(FlutterDesktopGpuSurfaceDescriptor);
|
||||
surface_descriptor.handle = d3d_texture.Get();
|
||||
surface_descriptor.width = surface_descriptor.visible_width = width;
|
||||
surface_descriptor.height = surface_descriptor.visible_height = height;
|
||||
surface_descriptor.release_context = &release_callback_called;
|
||||
surface_descriptor.release_callback = [](void* release_context) {
|
||||
bool* called = reinterpret_cast<bool*>(release_context);
|
||||
*called = true;
|
||||
};
|
||||
|
||||
FlutterDesktopTextureInfo texture_info = {};
|
||||
texture_info.type = kFlutterDesktopGpuSurfaceTexture;
|
||||
texture_info.gpu_surface_config.struct_size =
|
||||
sizeof(FlutterDesktopGpuSurfaceTextureConfig);
|
||||
texture_info.gpu_surface_config.type =
|
||||
kFlutterDesktopGpuSurfaceTypeD3d11Texture2D;
|
||||
texture_info.gpu_surface_config.user_data = &surface_descriptor;
|
||||
texture_info.gpu_surface_config.callback =
|
||||
[](size_t width, size_t height,
|
||||
void* user_data) -> const FlutterDesktopGpuSurfaceDescriptor* {
|
||||
return reinterpret_cast<const FlutterDesktopGpuSurfaceDescriptor*>(
|
||||
user_data);
|
||||
};
|
||||
|
||||
FlutterOpenGLTexture flutter_texture = {};
|
||||
auto texture_id = registrar.RegisterTexture(&texture_info);
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#ifndef FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_MOCK_GL_FUNCTIONS_H_
|
||||
#define FLUTTER_SHELL_PLATFORM_WINDOWS_TESTING_MOCK_GL_FUNCTIONS_H_
|
||||
|
||||
#include "flutter/shell/platform/windows/external_texture_gl.h"
|
||||
#include "flutter/shell/platform/windows/external_texture.h"
|
||||
|
||||
namespace flutter {
|
||||
namespace testing {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user