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,20 +136,18 @@ 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 // D3D starts here
IDXGIAdapter* adapter_ = nullptr; IDXGIAdapter* adapter_ = nullptr;
@@ -176,7 +174,7 @@ bool PolyvoxFilamentPlugin::MakeD3DTexture(uint32_t width, uint32_t height,std::
dxgi->EnumAdapters(0, &adapter_); dxgi->EnumAdapters(0, &adapter_);
dxgi->Release(); dxgi->Release();
if (!adapter_) { if (!adapter_) {
result->Error("ERROR", "Failed to locate default D3D adapter", nullptr); std::cout << "Failed to locate default D3D adapter"<< std::endl;
return false; return false;
} }
@@ -190,7 +188,7 @@ bool PolyvoxFilamentPlugin::MakeD3DTexture(uint32_t width, uint32_t height,std::
&_D3D11Device, 0, &_D3D11DeviceContext); &_D3D11Device, 0, &_D3D11DeviceContext);
if (FAILED(hr)) { if (FAILED(hr)) {
result->Error("ERROR", "Failed to create D3D device", nullptr); std::cout << "Failed to create D3D device"<< std::endl;
return false; return false;
} }
@@ -200,117 +198,120 @@ bool PolyvoxFilamentPlugin::MakeD3DTexture(uint32_t width, uint32_t height,std::
if (SUCCEEDED(dxgi_device_success) && dxgi_device != nullptr) { if (SUCCEEDED(dxgi_device_success) && dxgi_device != nullptr) {
dxgi_device->SetGPUThreadPriority(5); // Must be in interval [-7, 7]. dxgi_device->SetGPUThreadPriority(5); // Must be in interval [-7, 7].
} }
auto level = _D3D11Device->GetFeatureLevel(); auto level = _D3D11Device->GetFeatureLevel();
std::cout << "media_kit: ANGLESurfaceManager: Direct3D Feature Level: " std::cout << "media_kit: ANGLESurfaceManager: Direct3D Feature Level: "
<< (((unsigned)level) >> 12) << "_" << (((unsigned)level) >> 12) << "_"
<< ((((unsigned)level) >> 8) & 0xf) << std::endl; << ((((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); // * 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; return false;
} }
auto resource = Microsoft::WRL::ComPtr<IDXGIResource>{};
hr = _internalD3DTexture2D.As(&resource);
if FAILED(hr) { _eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
result->Error("ERROR", "Failed to create D3D texture", nullptr); 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; return false;
} }
hr = resource->GetSharedHandle(&_internalD3DTextureHandle);
if FAILED(hr) { importGLESExtensionsEntryPoints();
result->Error("ERROR", "Failed to get shared handle to D3D texture", nullptr);
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
};
EGLint contextAttribs[] = {
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_NONE, EGL_NONE, // reserved for EGL_CONTEXT_OPENGL_NO_ERROR_KHR below
EGL_NONE
};
// find an opaque config
if (!eglChooseConfig(_eglDisplay, configAttribs, &_eglConfig, 1, &configsCount)) {
return false; return false;
} }
_internalD3DTexture2D->AddRef();
std::cout << "Created internal D3D texture" << std::endl; _context = (void*)eglCreateContext(_eglDisplay, _eglConfig, EGL_NO_CONTEXT, contextAttribs);
// external if (UTILS_UNLIKELY(_context == EGL_NO_CONTEXT)) {
hr = _D3D11Device->CreateTexture2D(&d3d11_texture2D_desc, nullptr, &_externalD3DTexture2D);
if FAILED(hr)
{
result->Error("ERROR", "Failed to create D3D texture", nullptr);
return false; return false;
} }
hr = _externalD3DTexture2D.As(&resource); }
if FAILED(hr) { bool PolyvoxFilamentPlugin::MakeD3DTexture(uint32_t width, uint32_t height,std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
result->Error("ERROR", "Failed to create D3D texture", nullptr); 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;
} }
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; _active = std::make_unique<FlutterAngleTexture>(
_pluginRegistrar,
_textureRegistrar,
std::move(result),
width,
height,
_D3D11Device,
_D3D11DeviceContext,
_eglConfig,
_eglDisplay,
_context
);
_platform = new filament::backend::PlatformANGLE(_internalD3DTextureHandle, width, height); return _active->flutterTextureId != -1;
_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 = {
@@ -338,13 +339,14 @@ bool PolyvoxFilamentPlugin::MakeOpenGLTexture(uint32_t width, uint32_t height,st
// 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(); GLenum err = glGetError();
if(err != GL_NO_ERROR) { if(err != GL_NO_ERROR) {
result->Error("ERROR", "GL Error @ 455 %d", err); std::cout <<"GL Error @ 455 %d" << std::endl;
return false; return false;
} }
@@ -355,8 +357,7 @@ bool PolyvoxFilamentPlugin::MakeOpenGLTexture(uint32_t width, uint32_t height,st
"wglCreateContextAttribsARB"); "wglCreateContextAttribsARB");
if (!wglCreateContextAttribs) { if (!wglCreateContextAttribs) {
result->Error("ERROR", "Failed to resolve wglCreateContextAttribsARB", std::cout <<"Failed to resolve wglCreateContextAttribsARB" << std::endl;
nullptr);
return false; return false;
} }
@@ -373,12 +374,15 @@ bool PolyvoxFilamentPlugin::MakeOpenGLTexture(uint32_t width, uint32_t height,st
wglDeleteContext(tempContext); wglDeleteContext(tempContext);
if (!_context || !wglMakeCurrent(whdc, _context)) { if (!_context || !wglMakeCurrent(whdc, _context)) {
result->Error("ERROR", "Failed to create OpenGL context."); std::cout << "Failed to create OpenGL context." << std::endl;
return false; return false;
} }
} }
bool PolyvoxFilamentPlugin::MakeOpenGLTexture(uint32_t width, uint32_t height,std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>> result) {
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;
@@ -399,16 +403,34 @@ bool PolyvoxFilamentPlugin::MakeOpenGLTexture(uint32_t width, uint32_t height,st
} }
#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,11 +450,6 @@ void PolyvoxFilamentPlugin::DestroyTexture(
return; return;
} }
#ifdef USE_ANGLE
// TODO
result->Error("NOT_IMPLEMENTED", "Method is not implemented %s", methodCall.method_name());
#else
auto sh = std::make_shared<std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>>>(std::move(result));
if(!_active) { if(!_active) {
result->Success("Texture has already been detroyed, ignoring"); result->Success("Texture has already been detroyed, ignoring");
@@ -444,14 +461,18 @@ void PolyvoxFilamentPlugin::DestroyTexture(
return; return;
} }
auto sh = std::make_shared<std::unique_ptr<flutter::MethodResult<flutter::EncodableValue>>>(std::move(result));
// 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) { if(this->_inactive) {
HWND hwnd = _pluginRegistrar->GetView()->GetNativeWindow(); HWND hwnd = _pluginRegistrar->GetView()->GetNativeWindow();
HDC whdc = GetDC(hwnd); HDC whdc = GetDC(hwnd);
if (!wglMakeCurrent(whdc, _context)) { if (!wglMakeCurrent(whdc, _context)) {
@@ -463,24 +484,21 @@ void PolyvoxFilamentPlugin::DestroyTexture(
wglMakeCurrent(NULL, NULL); wglMakeCurrent(NULL, NULL);
} }
this->_inactive = std::move(this->_active); this->_inactive = std::move(this->_active);
#endif
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,32 +43,8 @@ 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,
@@ -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