use shared EGLContext for ANGLE on Windows

This commit is contained in:
Nick Fisher
2023-10-22 17:45:09 +11:00
parent 991e09df32
commit 2b9ddef5e7
8 changed files with 630 additions and 295 deletions

View File

@@ -12,7 +12,6 @@ set(PLUGIN_NAME "polyvox_filament_plugin")
list(APPEND PLUGIN_SOURCES list(APPEND PLUGIN_SOURCES
"polyvox_filament_plugin.cpp" "polyvox_filament_plugin.cpp"
"polyvox_filament_plugin.h" "polyvox_filament_plugin.h"
"opengl_texture_buffer.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/AssetManager.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/AssetManager.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FilamentViewer.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/FilamentViewer.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/PolyvoxFilamentApi.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/PolyvoxFilamentApi.cpp"
@@ -23,11 +22,16 @@ list(APPEND PLUGIN_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/camutils/Bookmark.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/../ios/src/camutils/Bookmark.cpp"
) )
set(USE_ANGLE FALSE) set(USE_ANGLE TRUE)
if(USE_ANGLE) if(USE_ANGLE)
add_compile_definitions(USE_ANGLE) add_compile_definitions(USE_ANGLE)
list(APPEND PLUGIN_SOURCES "PlatformAngle.cpp") list(APPEND PLUGIN_SOURCES
# "PlatformAngle.cpp"
"flutter_angle_texture.cpp"
)
else()
list(APPEND PLUGIN_SOURCES "opengl_texture_buffer.cpp")
endif() endif()
# Define the plugin library target. Its name must not be changed (see comment # Define the plugin library target. Its name must not be changed (see comment
@@ -57,6 +61,8 @@ if(USE_ANGLE)
list(APPEND GL_LIBS list(APPEND GL_LIBS
EGL EGL
GLESv2 GLESv2
#bluegl
#opengl32
) )
set(ANGLE_OR_OPENGL_DIR angle) set(ANGLE_OR_OPENGL_DIR angle)
add_library(EGL SHARED IMPORTED) add_library(EGL SHARED IMPORTED)
@@ -67,6 +73,10 @@ if(USE_ANGLE)
set_property(TARGET GLESv2 PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/angle/libGLESv2.dll.lib") set_property(TARGET GLESv2 PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/angle/libGLESv2.dll.lib")
set_property(TARGET GLESv2 PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/angle/libGLESv2.dll.lib") set_property(TARGET GLESv2 PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/angle/libGLESv2.dll.lib")
set_property(TARGET GLESv2 PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/angle/libGLESv2.dll.lib") set_property(TARGET GLESv2 PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/angle/libGLESv2.dll.lib")
add_library(bluegl SHARED IMPORTED)
set_property(TARGET bluegl PROPERTY IMPORTED_IMPLIB_DEBUG "${CMAKE_CURRENT_SOURCE_DIR}/lib/Debug/angle/bluegl.lib")
set_property(TARGET bluegl PROPERTY IMPORTED_IMPLIB_PROFILE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/angle/bluegl.lib")
set_property(TARGET bluegl PROPERTY IMPORTED_IMPLIB_RELEASE "${CMAKE_CURRENT_SOURCE_DIR}/lib/Release/angle/bluegl.lib")
else() else()
list(APPEND GL_LIBS list(APPEND GL_LIBS
bluegl bluegl

View File

@@ -35,10 +35,10 @@
using namespace utils; using namespace utils;
PROC wglGetProcAddress(LPCSTR name) { // PROC wglGetProcAddress(LPCSTR name) {
// PANIC // // PANIC
return nullptr; // return nullptr;
} // }
namespace filament::backend::GLUtils { namespace filament::backend::GLUtils {
class unordered_string_set : public std::unordered_set<std::string_view> { class unordered_string_set : public std::unordered_set<std::string_view> {
@@ -108,6 +108,9 @@ PlatformANGLE::PlatformANGLE(
} }
PlatformANGLE::~PlatformANGLE() {
}
backend::Driver* PlatformANGLE::createDriver(void* sharedContext, backend::Driver* PlatformANGLE::createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept { const Platform::DriverConfig& driverConfig) noexcept {
@@ -258,6 +261,13 @@ backend::Driver* PlatformANGLE::createDriver(void* sharedContext,
} }
glGenTextures(1, &glTextureId); glGenTextures(1, &glTextureId);
if (glTextureId == 0) {
std::cout << "Failed to generate OpenGL texture for ANGLE, OpenGL err was %d",
glGetError();
return nullptr;
}
glBindTexture(GL_TEXTURE_2D, glTextureId); glBindTexture(GL_TEXTURE_2D, glTextureId);
eglBindTexImage(mEGLDisplay, mCurrentReadSurface, EGL_BACK_BUFFER); eglBindTexImage(mEGLDisplay, mCurrentReadSurface, EGL_BACK_BUFFER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
@@ -437,10 +447,10 @@ bool PlatformANGLE::setExternalImage(void* externalImage,
if (UTILS_LIKELY(ext.gl.OES_EGL_image_external_essl3)) { if (UTILS_LIKELY(ext.gl.OES_EGL_image_external_essl3)) {
assert_invariant(texture->target == GL_TEXTURE_EXTERNAL_OES); assert_invariant(texture->target == GL_TEXTURE_EXTERNAL_OES);
// the texture is guaranteed to be bound here. // the texture is guaranteed to be bound here.
#ifdef GL_OES_EGL_image // #ifdef GL_OES_EGL_image
glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, // glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
static_cast<GLeglImageOES>(externalImage)); // static_cast<GLeglImageOES>(externalImage));
#endif // #endif
} }
return true; return true;
} }

View File

@@ -28,6 +28,7 @@ namespace filament::backend {
class PlatformANGLE : public OpenGLPlatform { class PlatformANGLE : public OpenGLPlatform {
public: public:
PlatformANGLE(HANDLE d3dTextureHandle, uint32_t width, uint32_t height) noexcept; PlatformANGLE(HANDLE d3dTextureHandle, uint32_t width, uint32_t height) noexcept;
~PlatformANGLE();
Driver* createDriver(void* sharedContext, Driver* createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept override; const Platform::DriverConfig& driverConfig) noexcept override;

View File

@@ -0,0 +1,230 @@
#include "flutter_angle_texture.h"
#include <flutter/method_channel.h>
#include <flutter/plugin_registrar_windows.h>
#include <flutter/standard_method_codec.h>
#include <flutter/texture_registrar.h>
#include "backend/platforms/PlatformEGL.h"
#include <thread>
namespace polyvox_filament {
static void logEglError(const char *name) noexcept {
const char *err;
switch (eglGetError()) {
case EGL_NOT_INITIALIZED:
err = "EGL_NOT_INITIALIZED";
break;
case EGL_BAD_ACCESS:
err = "EGL_BAD_ACCESS";
break;
case EGL_BAD_ALLOC:
err = "EGL_BAD_ALLOC";
break;
case EGL_BAD_ATTRIBUTE:
err = "EGL_BAD_ATTRIBUTE";
break;
case EGL_BAD_CONTEXT:
err = "EGL_BAD_CONTEXT";
break;
case EGL_BAD_CONFIG:
err = "EGL_BAD_CONFIG";
break;
case EGL_BAD_CURRENT_SURFACE:
err = "EGL_BAD_CURRENT_SURFACE";
break;
case EGL_BAD_DISPLAY:
err = "EGL_BAD_DISPLAY";
break;
case EGL_BAD_SURFACE:
err = "EGL_BAD_SURFACE";
break;
case EGL_BAD_MATCH:
err = "EGL_BAD_MATCH";
break;
case EGL_BAD_PARAMETER:
err = "EGL_BAD_PARAMETER";
break;
case EGL_BAD_NATIVE_PIXMAP:
err = "EGL_BAD_NATIVE_PIXMAP";
break;
case EGL_BAD_NATIVE_WINDOW:
err = "EGL_BAD_NATIVE_WINDOW";
break;
case EGL_CONTEXT_LOST:
err = "EGL_CONTEXT_LOST";
break;
default:
err = "unknown";
break;
}
std::cout << name << " failed with " << err << std::endl;
}
void FlutterAngleTexture::RenderCallback() {
_D3D11DeviceContext->CopyResource(_externalD3DTexture2D.Get(),
_internalD3DTexture2D.Get());
_D3D11DeviceContext->Flush();
}
FlutterAngleTexture::FlutterAngleTexture(
flutter::PluginRegistrarWindows *pluginRegistrar,
flutter::TextureRegistrar *textureRegistrar,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result,
uint32_t width, uint32_t height, ID3D11Device *D3D11Device,
ID3D11DeviceContext *D3D11DeviceContext, EGLConfig eglConfig,
EGLDisplay eglDisplay, EGLContext eglContext)
: _pluginRegistrar(pluginRegistrar), _textureRegistrar(textureRegistrar),
_width(width), _height(height), _D3D11Device(D3D11Device),
_D3D11DeviceContext(D3D11DeviceContext), _eglConfig(eglConfig),
_eglDisplay(eglDisplay), _eglContext(eglContext) {
auto d3d11_texture2D_desc = D3D11_TEXTURE2D_DESC{0};
d3d11_texture2D_desc.Width = width;
d3d11_texture2D_desc.Height = height;
d3d11_texture2D_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
d3d11_texture2D_desc.MipLevels = 1;
d3d11_texture2D_desc.ArraySize = 1;
d3d11_texture2D_desc.SampleDesc.Count = 1;
d3d11_texture2D_desc.SampleDesc.Quality = 0;
d3d11_texture2D_desc.Usage = D3D11_USAGE_DEFAULT;
d3d11_texture2D_desc.BindFlags =
D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
d3d11_texture2D_desc.CPUAccessFlags = 0;
d3d11_texture2D_desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
// create internal texture
auto hr = _D3D11Device->CreateTexture2D(&d3d11_texture2D_desc, nullptr,
&_internalD3DTexture2D);
if FAILED (hr) {
result->Error("ERROR", "Failed to create D3D texture", nullptr);
return;
;
}
auto resource = Microsoft::WRL::ComPtr<IDXGIResource>{};
hr = _internalD3DTexture2D.As(&resource);
if FAILED (hr) {
result->Error("ERROR", "Failed to create D3D texture", nullptr);
return;
;
}
hr = resource->GetSharedHandle(&_internalD3DTextureHandle);
if FAILED (hr) {
result->Error("ERROR", "Failed to get shared handle to D3D texture",
nullptr);
return;
;
}
_internalD3DTexture2D->AddRef();
std::cout << "Created internal D3D texture" << std::endl;
// external
hr = _D3D11Device->CreateTexture2D(&d3d11_texture2D_desc, nullptr,
&_externalD3DTexture2D);
if FAILED (hr) {
result->Error("ERROR", "Failed to create D3D texture", nullptr);
return;
;
}
hr = _externalD3DTexture2D.As(&resource);
if FAILED (hr) {
result->Error("ERROR", "Failed to create D3D texture", nullptr);
return;
;
}
hr = resource->GetSharedHandle(&_externalD3DTextureHandle);
if FAILED (hr) {
result->Error("ERROR",
"Failed to get shared handle to external D3D texture",
nullptr);
return;
;
}
_externalD3DTexture2D->AddRef();
std::cout << "Created external D3D texture" << std::endl;
EGLint pbufferAttribs[] = {
EGL_WIDTH, width, EGL_HEIGHT, height,
EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
EGL_NONE,
};
auto surface = eglCreatePbufferFromClientBuffer(
_eglDisplay, EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
_internalD3DTextureHandle, _eglConfig, pbufferAttribs);
if (!eglMakeCurrent(_eglDisplay, surface, surface, _eglContext)) {
// eglMakeCurrent failed
logEglError("eglMakeCurrent");
return;
}
glGenTextures(1, &glTextureId);
if (glTextureId == 0) {
std::cout
<< "Failed to generate OpenGL texture for ANGLE, OpenGL err was %d",
glGetError();
return;
}
glBindTexture(GL_TEXTURE_2D, glTextureId);
eglBindTexImage(_eglDisplay, surface, EGL_BACK_BUFFER);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// clearGlError
GLenum const error = glGetError();
if (error != GL_NO_ERROR) {
std::cout << "Ignoring pending GL error " << error << std::endl;
}
char const *version;
version = (char const *)glGetString(GL_VERSION);
std::cout << "Got version " << version << std::endl;
EGLint major, minor;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
// platform = new filament::backend::PlatformANGLE(_internalD3DTextureHandle,
// width, height);
platform = new filament::backend::PlatformEGL(); //_internalD3DTextureHandle,
//width, height);
_textureDescriptor = std::make_unique<FlutterDesktopGpuSurfaceDescriptor>();
_textureDescriptor->struct_size = sizeof(FlutterDesktopGpuSurfaceDescriptor);
_textureDescriptor->handle = _externalD3DTextureHandle;
_textureDescriptor->width = _textureDescriptor->visible_width = width;
_textureDescriptor->height = _textureDescriptor->visible_height = height;
_textureDescriptor->release_context = nullptr;
_textureDescriptor->release_callback = [](void *release_context) {
};
_textureDescriptor->format = kFlutterDesktopPixelFormatBGRA8888;
texture =
std::make_unique<flutter::TextureVariant>(flutter::GpuSurfaceTexture(
kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle,
[&](auto, auto) { return _textureDescriptor.get(); }));
flutterTextureId = _textureRegistrar->RegisterTexture(texture.get());
std::cout << "Registered Flutter texture ID " << flutterTextureId
<< std::endl;
std::vector<flutter::EncodableValue> resultList;
resultList.push_back(flutter::EncodableValue(flutterTextureId));
resultList.push_back(flutter::EncodableValue((int64_t) nullptr));
resultList.push_back(flutter::EncodableValue(glTextureId));
result->Success(resultList);
}
FlutterAngleTexture::~FlutterAngleTexture() {}
} // namespace polyvox_filament

View File

@@ -0,0 +1,81 @@
#pragma once
#ifndef _FLUTTER_ANGLE_TEXTURE_H
#define _FLUTTER_ANGLE_TEXTURE_H
#include <mutex>
#include <flutter/texture_registrar.h>
#include <flutter/method_channel.h>
#include <flutter/plugin_registrar_windows.h>
#include <d3d.h>
#include <d3d11.h>
#include "EGL/egl.h"
#include "EGL/eglext.h"
#include "EGL/eglplatform.h"
#include "GLES2/gl2.h"
#include "GLES2/gl2ext.h"
#include <GLES3/gl31.h>
#include "PlatformANGLE.h"
#include <Windows.h>
#include <wrl.h>
typedef uint32_t GLuint;
namespace polyvox_filament {
class FlutterAngleTexture {
public:
FlutterAngleTexture(
flutter::PluginRegistrarWindows* pluginRegistrar,
flutter::TextureRegistrar* textureRegistrar,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result,
uint32_t width,
uint32_t height,
ID3D11Device* D3D11Device,
ID3D11DeviceContext* D3D11DeviceContext,
EGLConfig eglConfig,
EGLDisplay eglDisplay,
EGLContext eglContext
);
~FlutterAngleTexture();
void RenderCallback();
int64_t flutterTextureId = 0;
GLuint glTextureId = 0;
std::unique_ptr<flutter::TextureVariant> texture;
filament::backend::Platform* platform = nullptr;
private:
flutter::PluginRegistrarWindows* _pluginRegistrar;
flutter::TextureRegistrar* _textureRegistrar;
uint32_t _width = 0;
uint32_t _height = 0;
bool logged = false;
std::shared_ptr<std::mutex> _renderMutex;
// Device
ID3D11Device* _D3D11Device = nullptr;
ID3D11DeviceContext* _D3D11DeviceContext = nullptr;
// Texture objects/shared handles
Microsoft::WRL::ComPtr<ID3D11Texture2D> _externalD3DTexture2D;
Microsoft::WRL::ComPtr<ID3D11Texture2D> _internalD3DTexture2D;
HANDLE _externalD3DTextureHandle = nullptr;
HANDLE _internalD3DTextureHandle = nullptr;
EGLDisplay _eglDisplay = EGL_NO_DISPLAY;
EGLContext _eglContext = EGL_NO_CONTEXT;
EGLConfig _eglConfig = EGL_NO_CONFIG_KHR;
std::unique_ptr<FlutterDesktopGpuSurfaceDescriptor> _textureDescriptor = nullptr;
};
}
#endif // _FLUTTER_ANGLE_TEXTURE

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:bf1bd7a89d00fa74f04c446aaeb9742793e02b42d53c0cf1375951f5948cd2ef oid sha256:1fcbbe01dc1cc92264b2bcf56a386c34c79fb2c90b5ab5f95e8aa37db3542788
size 20108820 size 20903930

View File

@@ -136,249 +136,253 @@ void render_callback(void* owner) {
// this is the method on PolyvoxFilamentPlugin that will copy between D3D textures // this is the method on PolyvoxFilamentPlugin that will copy between D3D textures
void PolyvoxFilamentPlugin::RenderCallback() { void PolyvoxFilamentPlugin::RenderCallback() {
#ifdef USE_ANGLE
_D3D11DeviceContext->CopyResource(_externalD3DTexture2D.Get(),
_internalD3DTexture2D.Get());
_D3D11DeviceContext->Flush();
#endif
std::lock_guard<std::mutex> guard(*(_renderMutex.get())); std::lock_guard<std::mutex> guard(*(_renderMutex.get()));
if (_active) { if (_active) {
#ifdef USE_ANGLE
_active->RenderCallback();
#endif
_textureRegistrar->MarkTextureFrameAvailable(_active->flutterTextureId); _textureRegistrar->MarkTextureFrameAvailable(_active->flutterTextureId);
} }
} }
#ifdef USE_ANGLE #ifdef USE_ANGLE
bool PolyvoxFilamentPlugin::MakeD3DTexture(uint32_t width, uint32_t height,std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) { bool PolyvoxFilamentPlugin::CreateSharedEGLContext() {
// D3D starts here
IDXGIAdapter* adapter_ = nullptr;
// D3D starts here // first, we need to initialize the D3D device and create the backing texture
IDXGIAdapter* adapter_ = nullptr; // this has been taken from https://github.com/alexmercerind/flutter-windows-ANGLE-OpenGL-ES/blob/master/windows/angle_surface_manager.cc
auto feature_levels = {
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
};
// NOTE: Not enabling DirectX 12.
// |D3D11CreateDevice| crashes directly on Windows 7.
// D3D_FEATURE_LEVEL_12_2, D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0,
// D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1,
// D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3,
IDXGIFactory* dxgi = nullptr;
::CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&dxgi);
// Manually selecting adapter. As far as my experience goes, this is the
// safest approach. Passing NULL (so-called default) seems to cause issues
// on Windows 7 or maybe some older graphics drivers.
// First adapter is the default.
// |D3D_DRIVER_TYPE_UNKNOWN| must be passed with manual adapter selection.
dxgi->EnumAdapters(0, &adapter_);
dxgi->Release();
if (!adapter_) {
std::cout << "Failed to locate default D3D adapter"<< std::endl;
return false;
}
DXGI_ADAPTER_DESC adapter_desc_;
adapter_->GetDesc(&adapter_desc_);
std::wcout << L"D3D adapter description: " << adapter_desc_.Description << std::endl;
auto hr = ::D3D11CreateDevice(
adapter_, D3D_DRIVER_TYPE_UNKNOWN, 0, 0, feature_levels.begin(),
static_cast<UINT>(feature_levels.size()), D3D11_SDK_VERSION,
&_D3D11Device, 0, &_D3D11DeviceContext);
// first, we need to initialize the D3D device and create the backing texture if (FAILED(hr)) {
// this has been taken from https://github.com/alexmercerind/flutter-windows-ANGLE-OpenGL-ES/blob/master/windows/angle_surface_manager.cc std::cout << "Failed to create D3D device"<< std::endl;
auto feature_levels = { return false;
D3D_FEATURE_LEVEL_11_0, }
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0, Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device = nullptr;
D3D_FEATURE_LEVEL_9_3, auto dxgi_device_success = _D3D11Device->QueryInterface(
__uuidof(IDXGIDevice), (void**)&dxgi_device);
if (SUCCEEDED(dxgi_device_success) && dxgi_device != nullptr) {
dxgi_device->SetGPUThreadPriority(5); // Must be in interval [-7, 7].
}
auto level = _D3D11Device->GetFeatureLevel();
std::cout << "media_kit: ANGLESurfaceManager: Direct3D Feature Level: "
<< (((unsigned)level) >> 12) << "_"
<< ((((unsigned)level) >> 8) & 0xf) << std::endl;
// *******************
// * *
// * *
// * EGL starts here *
// * *
// * *
// * *
// *******************
EGLBoolean bindAPI = eglBindAPI(EGL_OPENGL_ES_API);
if (UTILS_UNLIKELY(!bindAPI)) {
std::cout << "eglBindAPI EGL_OPENGL_ES_API failed" << std::endl;
return false;
}
_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
assert_invariant(_eglDisplay != EGL_NO_DISPLAY);
EGLint major, minor;
EGLBoolean initialized = false; // = eglInitialize(_eglDisplay, &major, &minor);
// if (!initialized) {
EGLDeviceEXT eglDevice;
EGLint numDevices;
if(auto* getPlatformDisplay = reinterpret_cast<PFNEGLGETPLATFORMDISPLAYEXTPROC>(
eglGetProcAddress("eglGetPlatformDisplayEXT"))) {
EGLint kD3D11DisplayAttributes[] = {
EGL_PLATFORM_ANGLE_TYPE_ANGLE,
EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE,
EGL_TRUE,
EGL_NONE,
};
_eglDisplay = getPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE, EGL_DEFAULT_DISPLAY, kD3D11DisplayAttributes);
initialized = eglInitialize(_eglDisplay, &major, &minor);
}
std::cout << "Got major " << major << " and minor " << minor << std::endl;
if (UTILS_UNLIKELY(!initialized)) {
std::cout << "eglInitialize failed" << std::endl;
return false;
}
importGLESExtensionsEntryPoints();
EGLint configsCount;
EGLint configAttribs[] = {
EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8, EGL_DEPTH_SIZE, 24, EGL_STENCIL_SIZE, 8, EGL_ALPHA_SIZE, 8,
EGL_NONE
}; };
// NOTE: Not enabling DirectX 12.
// |D3D11CreateDevice| crashes directly on Windows 7. EGLint contextAttribs[] = {
// D3D_FEATURE_LEVEL_12_2, D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, EGL_CONTEXT_CLIENT_VERSION, 3,
// D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, EGL_NONE, EGL_NONE, // reserved for EGL_CONTEXT_OPENGL_NO_ERROR_KHR below
// D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3, EGL_NONE
IDXGIFactory* dxgi = nullptr; };
::CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&dxgi);
// Manually selecting adapter. As far as my experience goes, this is the // find an opaque config
// safest approach. Passing NULL (so-called default) seems to cause issues if (!eglChooseConfig(_eglDisplay, configAttribs, &_eglConfig, 1, &configsCount)) {
// on Windows 7 or maybe some older graphics drivers. return false;
// First adapter is the default. }
// |D3D_DRIVER_TYPE_UNKNOWN| must be passed with manual adapter selection.
dxgi->EnumAdapters(0, &adapter_); _context = (void*)eglCreateContext(_eglDisplay, _eglConfig, EGL_NO_CONTEXT, contextAttribs);
dxgi->Release();
if (!adapter_) { if (UTILS_UNLIKELY(_context == EGL_NO_CONTEXT)) {
result->Error("ERROR", "Failed to locate default D3D adapter", nullptr); return false;
}
}
bool PolyvoxFilamentPlugin::MakeD3DTexture(uint32_t width, uint32_t height,std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
importGLESExtensionsEntryPoints();
if(_active.get()) {
result->Error("ERROR", "Texture already exists. You must call destroyTexture before attempting to create a new one.");
return false; return false;
} }
_active = std::make_unique<FlutterAngleTexture>(
_pluginRegistrar,
_textureRegistrar,
std::move(result),
width,
height,
_D3D11Device,
_D3D11DeviceContext,
_eglConfig,
_eglDisplay,
_context
);
DXGI_ADAPTER_DESC adapter_desc_; return _active->flutterTextureId != -1;
adapter_->GetDesc(&adapter_desc_);
std::wcout << L"D3D adapter description: " << adapter_desc_.Description << std::endl;
auto hr = ::D3D11CreateDevice(
adapter_, D3D_DRIVER_TYPE_UNKNOWN, 0, 0, feature_levels.begin(),
static_cast<UINT>(feature_levels.size()), D3D11_SDK_VERSION,
&_D3D11Device, 0, &_D3D11DeviceContext);
if (FAILED(hr)) {
result->Error("ERROR", "Failed to create D3D device", nullptr);
return false;
}
Microsoft::WRL::ComPtr<IDXGIDevice> dxgi_device = nullptr;
auto dxgi_device_success = _D3D11Device->QueryInterface(
__uuidof(IDXGIDevice), (void**)&dxgi_device);
if (SUCCEEDED(dxgi_device_success) && dxgi_device != nullptr) {
dxgi_device->SetGPUThreadPriority(5); // Must be in interval [-7, 7].
}
auto level = _D3D11Device->GetFeatureLevel();
std::cout << "media_kit: ANGLESurfaceManager: Direct3D Feature Level: "
<< (((unsigned)level) >> 12) << "_"
<< ((((unsigned)level) >> 8) & 0xf) << std::endl;
auto d3d11_texture2D_desc = D3D11_TEXTURE2D_DESC{0};
d3d11_texture2D_desc.Width = width;
d3d11_texture2D_desc.Height = height;
d3d11_texture2D_desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
d3d11_texture2D_desc.MipLevels = 1;
d3d11_texture2D_desc.ArraySize = 1;
d3d11_texture2D_desc.SampleDesc.Count = 1;
d3d11_texture2D_desc.SampleDesc.Quality = 0;
d3d11_texture2D_desc.Usage = D3D11_USAGE_DEFAULT;
d3d11_texture2D_desc.BindFlags =
D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
d3d11_texture2D_desc.CPUAccessFlags = 0;
d3d11_texture2D_desc.MiscFlags = D3D11_RESOURCE_MISC_SHARED;
// create internal texture
hr = _D3D11Device->CreateTexture2D(&d3d11_texture2D_desc, nullptr, &_internalD3DTexture2D);
if FAILED(hr)
{
result->Error("ERROR", "Failed to create D3D texture", nullptr);
return false;
}
auto resource = Microsoft::WRL::ComPtr<IDXGIResource>{};
hr = _internalD3DTexture2D.As(&resource);
if FAILED(hr) {
result->Error("ERROR", "Failed to create D3D texture", nullptr);
return false;
}
hr = resource->GetSharedHandle(&_internalD3DTextureHandle);
if FAILED(hr) {
result->Error("ERROR", "Failed to get shared handle to D3D texture", nullptr);
return false;
}
_internalD3DTexture2D->AddRef();
std::cout << "Created internal D3D texture" << std::endl;
// external
hr = _D3D11Device->CreateTexture2D(&d3d11_texture2D_desc, nullptr, &_externalD3DTexture2D);
if FAILED(hr)
{
result->Error("ERROR", "Failed to create D3D texture", nullptr);
return false;
}
hr = _externalD3DTexture2D.As(&resource);
if FAILED(hr) {
result->Error("ERROR", "Failed to create D3D texture", nullptr);
return false;
}
hr = resource->GetSharedHandle(&_externalD3DTextureHandle);
if FAILED(hr) {
result->Error("ERROR", "Failed to get shared handle to external D3D texture", nullptr);
return false;
}
_externalD3DTexture2D->AddRef();
std::cout << "Created external D3D texture" << std::endl;
_platform = new filament::backend::PlatformANGLE(_internalD3DTextureHandle, width, height);
_textureDescriptor = std::make_unique<FlutterDesktopGpuSurfaceDescriptor>();
_textureDescriptor->struct_size = sizeof(FlutterDesktopGpuSurfaceDescriptor);
_textureDescriptor->handle = _externalD3DTextureHandle;
_textureDescriptor->width = _textureDescriptor->visible_width = width;
_textureDescriptor->height = _textureDescriptor->visible_height = height;
_textureDescriptor->release_context = nullptr;
_textureDescriptor->release_callback = [](void* release_context) {};
_textureDescriptor->format = kFlutterDesktopPixelFormatBGRA8888;
_texture =
std::make_unique<flutter::TextureVariant>(flutter::GpuSurfaceTexture(
kFlutterDesktopGpuSurfaceTypeDxgiSharedHandle,
[&](auto, auto) { return _textureDescriptor.get(); }));
_flutterTextureId = _textureRegistrar->RegisterTexture(_texture.get());
std::cout << "Registered Flutter texture ID " << _flutterTextureId << std::endl;
std::vector<flutter::EncodableValue> resultList;
resultList.push_back(flutter::EncodableValue(_flutterTextureId));
resultList.push_back(flutter::EncodableValue((int64_t)nullptr));
resultList.push_back(flutter::EncodableValue(_platform->glTextureId));
result->Success(resultList);
return true;
} }
#else #else
bool PolyvoxFilamentPlugin::MakeOpenGLTexture(uint32_t width, uint32_t height,std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) { bool PolyvoxFilamentPlugin::CreateSharedWGLContext() {
HWND hwnd = _pluginRegistrar->GetView() HWND hwnd = _pluginRegistrar->GetView()
->GetNativeWindow(); ->GetNativeWindow();
HDC whdc = GetDC(hwnd); HDC whdc = GetDC(hwnd);
if (whdc == NULL) { if (whdc == NULL) {
result->Error("ERROR", "No device context for temporary window", nullptr); std::cout << "No device context for temporary window" << std::endl;
return false; return false;
} }
if(!_renderMutex.get()) {
_renderMutex = std::make_shared<std::mutex>();
}
// we need a single context (since this will be passed to the renderer)
// if this is the first time we are attempting to create a texture, let's create the context
if(_context == NULL) {
std::cout << "No GL context exists, creating" << std::endl; std::cout << "No GL context exists, creating" << std::endl;
PIXELFORMATDESCRIPTOR pfd = { PIXELFORMATDESCRIPTOR pfd = {
sizeof(PIXELFORMATDESCRIPTOR), sizeof(PIXELFORMATDESCRIPTOR),
1, 1,
PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags PFD_DRAW_TO_BITMAP | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, // Flags
PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette. PFD_TYPE_RGBA, // The kind of framebuffer. RGBA or palette.
32, // Colordepth of the framebuffer. 32, // Colordepth of the framebuffer.
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0,
0, 0,
0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32, // Number of bits for the depthbuffer 32, // Number of bits for the depthbuffer
0, // Number of bits for the stencilbuffer 0, // Number of bits for the stencilbuffer
0, // Number of Aux buffers in the framebuffer. 0, // Number of Aux buffers in the framebuffer.
PFD_MAIN_PLANE, PFD_MAIN_PLANE,
0, 0,
0, 0, 0 0, 0, 0
}; };
int pixelFormat = ChoosePixelFormat(whdc, &pfd); int pixelFormat = ChoosePixelFormat(whdc, &pfd);
SetPixelFormat(whdc, pixelFormat, &pfd); SetPixelFormat(whdc, pixelFormat, &pfd);
// We need a tmp context to retrieve and call wglCreateContextAttribsARB. // We need a tmp context to retrieve and call wglCreateContextAttribsARB.
HGLRC tempContext = wglCreateContext(whdc); HGLRC tempContext = wglCreateContext(whdc);
if (!wglMakeCurrent(whdc, tempContext)) { if (!wglMakeCurrent(whdc, tempContext)) {
result->Error("ERROR", "Failed to acquire temporary context", nullptr); std::cout <<"Failed to acquire temporary context" << std::endl;
return false;
}
GLenum err = glGetError();
if(err != GL_NO_ERROR) {
std::cout <<"GL Error @ 455 %d" << std::endl;
return false;
}
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs = nullptr;
wglCreateContextAttribs =
(PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress(
"wglCreateContextAttribsARB");
if (!wglCreateContextAttribs) {
std::cout <<"Failed to resolve wglCreateContextAttribsARB" << std::endl;
return false;
}
for (int minor = 5; minor >= 1; minor--) {
std::vector<int> mAttribs = {WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, minor, 0};
_context = wglCreateContextAttribs(whdc, nullptr, mAttribs.data());
if (_context) {
break;
} }
}
GLenum err = glGetError(); wglMakeCurrent(NULL, NULL);
wglDeleteContext(tempContext);
if(err != GL_NO_ERROR) { if (!_context || !wglMakeCurrent(whdc, _context)) {
result->Error("ERROR", "GL Error @ 455 %d", err); std::cout << "Failed to create OpenGL context." << std::endl;
return false; return false;
} }
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribs = nullptr;
wglCreateContextAttribs = }
(PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress(
"wglCreateContextAttribsARB");
if (!wglCreateContextAttribs) { bool PolyvoxFilamentPlugin::MakeOpenGLTexture(uint32_t width, uint32_t height,std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
result->Error("ERROR", "Failed to resolve wglCreateContextAttribsARB",
nullptr);
return false;
}
for (int minor = 5; minor >= 1; minor--) {
std::vector<int> mAttribs = {WGL_CONTEXT_MAJOR_VERSION_ARB, 4,
WGL_CONTEXT_MINOR_VERSION_ARB, minor, 0};
_context = wglCreateContextAttribs(whdc, nullptr, mAttribs.data());
if (_context) {
break;
}
}
wglMakeCurrent(NULL, NULL);
wglDeleteContext(tempContext);
if (!_context || !wglMakeCurrent(whdc, _context)) {
result->Error("ERROR", "Failed to create OpenGL context.");
return false;
}
}
if(_active.get()) { if(_active.get()) {
result->Error("ERROR", "Texture already exists. You must call destroyTexture before attempting to create a new one."); result->Error("ERROR", "Texture already exists. You must call destroyTexture before attempting to create a new one.");
return false; return false;
@@ -397,18 +401,36 @@ bool PolyvoxFilamentPlugin::MakeOpenGLTexture(uint32_t width, uint32_t height,st
return _active->flutterTextureId != -1; return _active->flutterTextureId != -1;
} }
#endif #endif
void PolyvoxFilamentPlugin::CreateTexture( void PolyvoxFilamentPlugin::CreateTexture(
const flutter::MethodCall<flutter::EncodableValue> &methodCall, const flutter::MethodCall<flutter::EncodableValue> &methodCall,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) { std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
if(!_renderMutex.get()) {
_renderMutex = std::make_shared<std::mutex>();
}
std::lock_guard<std::mutex> guard(*(_renderMutex.get()));
const auto *args = const auto *args =
std::get_if<flutter::EncodableList>(methodCall.arguments()); std::get_if<flutter::EncodableList>(methodCall.arguments());
const auto width = (uint32_t)round(*(std::get_if<double>(&(args->at(0))))); const auto width = (uint32_t)round(*(std::get_if<double>(&(args->at(0)))));
const auto height = (uint32_t)round(*(std::get_if<double>(&(args->at(1))))); const auto height = (uint32_t)round(*(std::get_if<double>(&(args->at(1)))));
// create a single shared context for the life of the application
// this will be used to create a backing texture and passed to Filament
if(!_context) {
#ifdef USE_ANGLE
CreateSharedEGLContext();
#else
CreateSharedWGLContext();
#endif
}
#ifdef USE_ANGLE #ifdef USE_ANGLE
bool success = MakeD3DTexture(width, height, std::move(result)); bool success = MakeD3DTexture(width, height, std::move(result));
#else #else
@@ -428,59 +450,55 @@ void PolyvoxFilamentPlugin::DestroyTexture(
return; return;
} }
#ifdef USE_ANGLE
// TODO if(!_active) {
result->Error("NOT_IMPLEMENTED", "Method is not implemented %s", methodCall.method_name()); result->Success("Texture has already been detroyed, ignoring");
#else return;
auto sh = std::make_shared<std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>>>(std::move(result)); }
if(!_active) { if(_active->flutterTextureId != *flutterTextureId) {
result->Success("Texture has already been detroyed, ignoring"); result->Error("TEXTURE_MISMATCH", "Specified texture ID is not active");
return; return;
} }
if(_active->flutterTextureId != *flutterTextureId) { auto sh = std::make_shared<std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>>>(std::move(result));
result->Error("TEXTURE_MISMATCH", "Specified texture ID is not active");
return;
}
// result->Error("NOT_IMPLEMENTED", "Method is not implemented %s", methodCall.method_name());
_textureRegistrar->UnregisterTexture(_active->flutterTextureId, [=, _textureRegistrar->UnregisterTexture(_active->flutterTextureId, [=,
sharedResult=std::move(sh) sharedResult=std::move(sh)
]() { ]() {
#ifdef USE_ANGLE
this->_active = nullptr;
#else
if(this->_inactive) {
HWND hwnd = _pluginRegistrar->GetView()->GetNativeWindow();
HDC whdc = GetDC(hwnd);
if(this->_inactive) { if (!wglMakeCurrent(whdc, _context)) {
std::cout << "Failed to switch OpenGL context in destructor." << std::endl;
HWND hwnd = _pluginRegistrar->GetView()->GetNativeWindow(); // result->Error("CONTEXT", "Failed to switch OpenGL context.", nullptr);
return;
HDC whdc = GetDC(hwnd); }
glDeleteTextures(1, &this->_inactive->glTextureId);
if (!wglMakeCurrent(whdc, _context)) { wglMakeCurrent(NULL, NULL);
std::cout << "Failed to switch OpenGL context in destructor." << std::endl;
// result->Error("CONTEXT", "Failed to switch OpenGL context.", nullptr);
return;
} }
glDeleteTextures(1, &this->_inactive->glTextureId); this->_inactive = std::move(this->_active);
wglMakeCurrent(NULL, NULL); #endif
}
this->_inactive = std::move(this->_active);
auto unique = std::move(*(sharedResult.get())); auto unique = std::move(*(sharedResult.get()));
unique->Success(flutter::EncodableValue(true)); unique->Success(flutter::EncodableValue(true));
std::cout << "Destroyed OpenGLTextureBuffer." << std::endl; std::cout << "Unregistered/destroyed texture." << std::endl;
}); });
#endif
} }
void PolyvoxFilamentPlugin::HandleMethodCall( void PolyvoxFilamentPlugin::HandleMethodCall(
const flutter::MethodCall<flutter::EncodableValue> &methodCall, const flutter::MethodCall<flutter::EncodableValue> &methodCall,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) { std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
// std::cout << methodCall.method_name() << std::endl;
if (methodCall.method_name() == "getSharedContext") { if (methodCall.method_name() == "getSharedContext") {
#ifdef USE_ANGLE
result->Success(flutter::EncodableValue((int64_t)nullptr));
#else
result->Success(flutter::EncodableValue((int64_t)_context)); result->Success(flutter::EncodableValue((int64_t)_context));
#endif
} else if (methodCall.method_name() == "getResourceLoaderWrapper") { } else if (methodCall.method_name() == "getResourceLoaderWrapper") {
const ResourceLoaderWrapper *const resourceLoader = const ResourceLoaderWrapper *const resourceLoader =
new ResourceLoaderWrapper(_loadResource, _freeResource, this); new ResourceLoaderWrapper(_loadResource, _freeResource, this);
@@ -496,7 +514,7 @@ void PolyvoxFilamentPlugin::HandleMethodCall(
result->Success(resultList); result->Success(resultList);
} else if(methodCall.method_name() == "getDriverPlatform") { } else if(methodCall.method_name() == "getDriverPlatform") {
#ifdef USE_ANGLE #ifdef USE_ANGLE
result->Success(flutter::EncodableValue((int64_t)_platform)); result->Success(flutter::EncodableValue((int64_t)_active->platform));
#else #else
result->Success(flutter::EncodableValue((int64_t)nullptr)); result->Success(flutter::EncodableValue((int64_t)nullptr));
#endif #endif

View File

@@ -11,21 +11,11 @@
#include <Windows.h> #include <Windows.h>
#include <wrl.h> #include <wrl.h>
#ifdef USE_ANGLE
#include <d3d.h>
#include <d3d11.h>
#endif
#include "GL/GL.h" #include "GL/GL.h"
#include "GL/GLu.h" #include "GL/GLu.h"
#ifdef USE_ANGLE #ifdef USE_ANGLE
#include "EGL/egl.h" #include "flutter_angle_texture.h"
#include "EGL/eglext.h"
#include "EGL/eglplatform.h"
#include "GLES2/gl2.h"
#include "GLES2/gl2ext.h"
#include "PlatformAngle.h"
#else #else
#include "opengl_texture_buffer.h" #include "opengl_texture_buffer.h"
#endif #endif
@@ -53,33 +43,9 @@ public:
flutter::PluginRegistrarWindows *_pluginRegistrar; flutter::PluginRegistrarWindows *_pluginRegistrar;
flutter::TextureRegistrar *_textureRegistrar; flutter::TextureRegistrar *_textureRegistrar;
std::map<uint32_t, ResourceBuffer> _resources; std::map<uint32_t, ResourceBuffer> _resources;
std::unique_ptr<FlutterDesktopGpuSurfaceDescriptor> _textureDescriptor = nullptr;
#ifdef USE_ANGLE
// Device
ID3D11Device* _D3D11Device = nullptr;
ID3D11DeviceContext* _D3D11DeviceContext = nullptr;
// Texture objects/shared handles
Microsoft::WRL::ComPtr<ID3D11Texture2D> _externalD3DTexture2D;
Microsoft::WRL::ComPtr<ID3D11Texture2D> _internalD3DTexture2D;
HANDLE _externalD3DTextureHandle = nullptr;
HANDLE _internalD3DTextureHandle = nullptr;
filament::backend::PlatformANGLE* _platform = nullptr;
bool MakeD3DTexture(uint32_t width, uint32_t height, std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
#else
std::shared_ptr<std::mutex> _renderMutex; std::shared_ptr<std::mutex> _renderMutex;
std::unique_ptr<OpenGLTextureBuffer> _active = nullptr;
std::unique_ptr<OpenGLTextureBuffer> _inactive = nullptr;
// shared OpenGLContext
HGLRC _context = NULL;
bool MakeOpenGLTexture(uint32_t width, uint32_t height, std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
#endif
void CreateTexture( void CreateTexture(
const flutter::MethodCall<flutter::EncodableValue> &methodCall, const flutter::MethodCall<flutter::EncodableValue> &methodCall,
std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result); std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
@@ -90,6 +56,25 @@ public:
ResourceBuffer loadResource(const char *path); ResourceBuffer loadResource(const char *path);
void freeResource(ResourceBuffer rbuf); void freeResource(ResourceBuffer rbuf);
private:
#ifdef USE_ANGLE
EGLContext _context = NULL;
EGLConfig _eglConfig = NULL;
EGLDisplay _eglDisplay = NULL;
std::unique_ptr<FlutterAngleTexture> _active = nullptr;
ID3D11Device* _D3D11Device = nullptr;
ID3D11DeviceContext* _D3D11DeviceContext = nullptr;
bool CreateSharedEGLContext();
bool MakeD3DTexture(uint32_t width, uint32_t height, std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
#else
std::unique_ptr<OpenGLTextureBuffer> _active = nullptr;
std::unique_ptr<OpenGLTextureBuffer> _inactive = nullptr;
// shared OpenGLContext
HGLRC _context = NULL;
bool CreateSharedWGLContext();
bool MakeOpenGLTexture(uint32_t width, uint32_t height, std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result);
#endif
}; };
} // namespace polyvox_filament } // namespace polyvox_filament