add first pass vulkan implementation
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
set(PROJECT_NAME "thermion_egl")
|
||||
project(${PROJECT_NAME} LANGUAGES C CXX)
|
||||
|
||||
cmake_policy(VERSION 3.14...3.25)
|
||||
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
set(BUILD_SHARED_LIBS TRUE)
|
||||
set(CMAKE_ENABLE_EXPORTS TRUE)
|
||||
|
||||
add_definitions(-DVK_STATIC_DISPATCH)
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED
|
||||
"d3d_texture.cpp"
|
||||
)
|
||||
|
||||
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20)
|
||||
include_directories(${PROJECT_NAME} INTERFACE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../include"
|
||||
)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} PRIVATE
|
||||
Shlwapi
|
||||
dxgi
|
||||
d3d11
|
||||
)
|
||||
|
||||
# Test executable
|
||||
add_executable(${PROJECT_NAME}_test
|
||||
"main.cpp"
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}_test PRIVATE
|
||||
E:\\VulkanSDK\\1.3.296.0\\Include
|
||||
)
|
||||
target_link_directories(${PROJECT_NAME}_test PRIVATE
|
||||
E:\\VulkanSDK\\1.3.296.0\\Lib
|
||||
)
|
||||
target_link_libraries(${PROJECT_NAME}_test PRIVATE
|
||||
${PROJECT_NAME}
|
||||
vulkan-1
|
||||
)
|
||||
|
||||
# Make sure the test depends on the library
|
||||
add_dependencies(${PROJECT_NAME}_test ${PROJECT_NAME})
|
||||
@@ -0,0 +1,272 @@
|
||||
#include "d3d_texture.h"
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
namespace thermion::windows::d3d {
|
||||
|
||||
void D3DTexture::Flush() {
|
||||
// glFlush(); // Ensure GL commands are completed
|
||||
_D3D11DeviceContext->Flush();
|
||||
}
|
||||
|
||||
HANDLE D3DTexture::GetTextureHandle() {
|
||||
return _d3dTexture2DHandle;
|
||||
}
|
||||
|
||||
D3DTexture::~D3DTexture() {
|
||||
_d3dTexture2D->Release();
|
||||
}
|
||||
|
||||
bool IsNTHandleSupported(ID3D11Device* device) {
|
||||
Microsoft::WRL::ComPtr<ID3D11Device5> device5;
|
||||
return SUCCEEDED(device->QueryInterface(IID_PPV_ARGS(&device5)));
|
||||
}
|
||||
|
||||
D3DTexture::D3DTexture(
|
||||
uint32_t width, uint32_t height,
|
||||
std::function<void(size_t, size_t)> onResizeRequested
|
||||
)
|
||||
: _width(width), _height(height), _onResizeRequested(onResizeRequested) {
|
||||
|
||||
IDXGIAdapter *adapter_ = nullptr;
|
||||
|
||||
auto feature_levels = {
|
||||
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,
|
||||
};
|
||||
|
||||
IDXGIFactory1 *dxgi = nullptr;
|
||||
HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory1), (void **)&dxgi);
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to create DXGI 1.1 factory" << std::endl;
|
||||
return;
|
||||
}
|
||||
dxgi->EnumAdapters(0, &adapter_);
|
||||
dxgi->Release();
|
||||
if (!adapter_) {
|
||||
std::cout << "Failed to locate default D3D adapter" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
Microsoft::WRL::ComPtr<IDXGIFactory2> factory2;
|
||||
if (SUCCEEDED(dxgi->QueryInterface(IID_PPV_ARGS(&factory2)))) {
|
||||
std::cout << "DXGI 1.2 or higher supported" << std::endl;
|
||||
}
|
||||
|
||||
DXGI_ADAPTER_DESC adapter_desc_;
|
||||
adapter_->GetDesc(&adapter_desc_);
|
||||
std::wcout << L"D3D adapter description: " << adapter_desc_.Description
|
||||
<< std::endl;
|
||||
|
||||
hr = ::D3D11CreateDevice(
|
||||
adapter_, D3D_DRIVER_TYPE_UNKNOWN, 0, D3D11_CREATE_DEVICE_BGRA_SUPPORT, feature_levels.begin(),
|
||||
static_cast<UINT>(feature_levels.size()), D3D11_SDK_VERSION,
|
||||
&_D3D11Device, 0, &_D3D11DeviceContext);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to create D3D device" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
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].
|
||||
}
|
||||
|
||||
if(IsNTHandleSupported(_D3D11Device)) {
|
||||
std::cout << "NT HANDLE SUPPORT" << std::endl;
|
||||
} else {
|
||||
std::cout << "NT HANDLE NOT SUPPORT" << std::endl;
|
||||
}
|
||||
auto level = _D3D11Device->GetFeatureLevel();
|
||||
std::cout << "Direct3D Feature Level: "
|
||||
<< (((unsigned)level) >> 12) << "_"
|
||||
<< ((((unsigned)level) >> 8) & 0xf) << std::endl;
|
||||
|
||||
// Create texture
|
||||
auto d3d11_texture2D_desc = D3D11_TEXTURE2D_DESC{0};
|
||||
d3d11_texture2D_desc.Width = width;
|
||||
d3d11_texture2D_desc.Height = height;
|
||||
d3d11_texture2D_desc.Format = DXGI_FORMAT_R8G8B8A8_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;
|
||||
|
||||
hr = _D3D11Device->CreateTexture2D(&d3d11_texture2D_desc, nullptr, &_d3dTexture2D);
|
||||
if FAILED (hr) {
|
||||
std::cout << "Failed to create D3D texture (" << hr << ")" << std::endl;
|
||||
return;
|
||||
}
|
||||
auto resource = Microsoft::WRL::ComPtr<IDXGIResource1>{};
|
||||
hr = _d3dTexture2D.As(&resource);
|
||||
|
||||
if FAILED (hr) {
|
||||
std::cout << "Failed to create D3D texture" << std::endl;
|
||||
return;
|
||||
;
|
||||
}
|
||||
hr = resource->GetSharedHandle(&_d3dTexture2DHandle);
|
||||
if FAILED (hr) {
|
||||
std::cout << "Failed to get shared handle to external D3D texture" << std::endl;
|
||||
return;
|
||||
;
|
||||
}
|
||||
_d3dTexture2D->AddRef();
|
||||
|
||||
std::cout << "Created external D3D texture " << width << "x" << height << std::endl;
|
||||
|
||||
// Create render target view of the texture
|
||||
ID3D11RenderTargetView* rtv = nullptr;
|
||||
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
|
||||
rtvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
rtvDesc.Texture2D.MipSlice = 0;
|
||||
|
||||
hr = _D3D11Device->CreateRenderTargetView(_d3dTexture2D.Get(), &rtvDesc, &rtv);
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to create render target view" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear the texture to blue
|
||||
float blueColor[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; // RGBA
|
||||
_D3D11DeviceContext->ClearRenderTargetView(rtv, blueColor);
|
||||
_D3D11DeviceContext->Flush();
|
||||
|
||||
}
|
||||
|
||||
void D3DTexture::FillBlueAndSaveToBMP(const char* filename) {
|
||||
// Create render target view of the texture
|
||||
ID3D11RenderTargetView* rtv = nullptr;
|
||||
D3D11_RENDER_TARGET_VIEW_DESC rtvDesc = {};
|
||||
rtvDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
|
||||
rtvDesc.Texture2D.MipSlice = 0;
|
||||
|
||||
HRESULT hr = _D3D11Device->CreateRenderTargetView(_d3dTexture2D.Get(), &rtvDesc, &rtv);
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to create render target view" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear the texture to blue
|
||||
float blueColor[4] = { 0.0f, 0.0f, 1.0f, 1.0f }; // RGBA
|
||||
_D3D11DeviceContext->ClearRenderTargetView(rtv, blueColor);
|
||||
|
||||
// Create staging texture for CPU read access
|
||||
D3D11_TEXTURE2D_DESC stagingDesc = {};
|
||||
_d3dTexture2D->GetDesc(&stagingDesc);
|
||||
stagingDesc.Usage = D3D11_USAGE_STAGING;
|
||||
stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
stagingDesc.BindFlags = 0;
|
||||
stagingDesc.MiscFlags = 0;
|
||||
|
||||
ID3D11Texture2D* stagingTexture = nullptr;
|
||||
hr = _D3D11Device->CreateTexture2D(&stagingDesc, nullptr, &stagingTexture);
|
||||
if (FAILED(hr)) {
|
||||
rtv->Release();
|
||||
std::cout << "Failed to create staging texture" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Copy to staging texture
|
||||
_D3D11DeviceContext->CopyResource(stagingTexture, _d3dTexture2D.Get());
|
||||
|
||||
// Save to BMP
|
||||
bool success = SaveTextureAsBMP(stagingTexture, filename);
|
||||
|
||||
// Cleanup
|
||||
stagingTexture->Release();
|
||||
rtv->Release();
|
||||
|
||||
if (success) {
|
||||
std::cout << "Successfully saved texture to " << filename << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool D3DTexture::SaveTextureAsBMP(ID3D11Texture2D* texture, const char* filename) {
|
||||
D3D11_TEXTURE2D_DESC desc;
|
||||
texture->GetDesc(&desc);
|
||||
|
||||
// Map texture to get pixel data
|
||||
D3D11_MAPPED_SUBRESOURCE mappedResource;
|
||||
HRESULT hr = _D3D11DeviceContext->Map(texture, 0, D3D11_MAP_READ, 0, &mappedResource);
|
||||
if (FAILED(hr)) {
|
||||
std::cout << "Failed to map texture" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// BMP file header
|
||||
#pragma pack(push, 1)
|
||||
struct BMPHeader {
|
||||
uint16_t signature;
|
||||
uint32_t fileSize;
|
||||
uint32_t reserved;
|
||||
uint32_t dataOffset;
|
||||
uint32_t headerSize;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
uint16_t planes;
|
||||
uint16_t bitsPerPixel;
|
||||
uint32_t compression;
|
||||
uint32_t imageSize;
|
||||
int32_t xPixelsPerMeter;
|
||||
int32_t yPixelsPerMeter;
|
||||
uint32_t totalColors;
|
||||
uint32_t importantColors;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
// Create and fill header
|
||||
BMPHeader header = {};
|
||||
header.signature = 0x4D42; // 'BM'
|
||||
header.fileSize = sizeof(BMPHeader) + desc.Width * desc.Height * 4;
|
||||
header.dataOffset = sizeof(BMPHeader);
|
||||
header.headerSize = 40;
|
||||
header.width = desc.Width;
|
||||
header.height = desc.Height;
|
||||
header.planes = 1;
|
||||
header.bitsPerPixel = 32;
|
||||
header.compression = 0;
|
||||
header.imageSize = desc.Width * desc.Height * 4;
|
||||
header.xPixelsPerMeter = 2835; // 72 DPI
|
||||
header.yPixelsPerMeter = 2835; // 72 DPI
|
||||
|
||||
// Write to file
|
||||
FILE* file = nullptr;
|
||||
fopen_s(&file, filename, "wb");
|
||||
if (!file) {
|
||||
_D3D11DeviceContext->Unmap(texture, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
fwrite(&header, sizeof(header), 1, file);
|
||||
|
||||
// Write pixel data (need to flip rows as BMP is bottom-up)
|
||||
uint8_t* srcData = reinterpret_cast<uint8_t*>(mappedResource.pData);
|
||||
for (int y = desc.Height - 1; y >= 0; y--) {
|
||||
uint8_t* rowData = srcData + y * mappedResource.RowPitch;
|
||||
fwrite(rowData, desc.Width * 4, 1, file);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
_D3D11DeviceContext->Unmap(texture, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace thermion_flutter
|
||||
@@ -0,0 +1,51 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
|
||||
#include <d3d.h>
|
||||
#include <d3d11.h>
|
||||
#include <dxgi1_2.h> // Add this line
|
||||
#include <d3d11_4.h>
|
||||
#include <Windows.h>
|
||||
#include <wrl.h>
|
||||
|
||||
typedef uint32_t GLuint;
|
||||
|
||||
namespace thermion::windows::d3d {
|
||||
|
||||
class D3DTexture {
|
||||
public:
|
||||
D3DTexture(
|
||||
uint32_t width,
|
||||
uint32_t height,
|
||||
std::function<void(size_t, size_t)> onResizeRequested
|
||||
);
|
||||
~D3DTexture();
|
||||
|
||||
void Flush();
|
||||
HANDLE GetTextureHandle();
|
||||
|
||||
GLuint glTextureId = 0;
|
||||
|
||||
void FillBlueAndSaveToBMP(const char* filename);
|
||||
bool SaveTextureAsBMP(ID3D11Texture2D* texture, const char* filename);
|
||||
// Device
|
||||
ID3D11Device* _D3D11Device = nullptr;
|
||||
|
||||
private:
|
||||
bool _error = false;
|
||||
uint32_t _width = 0;
|
||||
uint32_t _height = 0;
|
||||
bool logged = false;
|
||||
std::function<void(size_t, size_t)> _onResizeRequested;
|
||||
|
||||
|
||||
ID3D11DeviceContext* _D3D11DeviceContext = nullptr;
|
||||
// Texture objects/shared handles
|
||||
Microsoft::WRL::ComPtr<ID3D11Texture2D> _d3dTexture2D;
|
||||
HANDLE _d3dTexture2DHandle = nullptr;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <Windows.h>
|
||||
|
||||
#include "egl_texture.h"
|
||||
|
||||
namespace thermion::windows::egl {
|
||||
|
||||
class ThermionEGLContext {
|
||||
public:
|
||||
ThermionEGLContext();
|
||||
void* GetSharedContext();
|
||||
EGLTexture * CreateRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top);
|
||||
void DestroyRenderingSurface();
|
||||
void ResizeRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top);
|
||||
|
||||
EGLTexture * GetActiveTexture();
|
||||
|
||||
private:
|
||||
void* _context = nullptr;
|
||||
EGLConfig _eglConfig = NULL;
|
||||
EGLDisplay _eglDisplay = NULL;
|
||||
ID3D11Device* _D3D11Device = nullptr;
|
||||
ID3D11DeviceContext* _D3D11DeviceContext = nullptr;
|
||||
std::unique_ptr<EGLTexture> _active = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,484 @@
|
||||
#include "d3d_texture.h"
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <vulkan/vulkan_win32.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "d3d_texture.h"
|
||||
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
// Helper function to convert VkResult to string for error reporting
|
||||
const char *VkResultToString(VkResult result)
|
||||
{
|
||||
switch (result)
|
||||
{
|
||||
case VK_SUCCESS:
|
||||
return "VK_SUCCESS";
|
||||
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
||||
return "VK_ERROR_OUT_OF_HOST_MEMORY";
|
||||
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
|
||||
return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
|
||||
case VK_ERROR_INITIALIZATION_FAILED:
|
||||
return "VK_ERROR_INITIALIZATION_FAILED";
|
||||
case VK_ERROR_LAYER_NOT_PRESENT:
|
||||
return "VK_ERROR_LAYER_NOT_PRESENT";
|
||||
case VK_ERROR_EXTENSION_NOT_PRESENT:
|
||||
return "VK_ERROR_EXTENSION_NOT_PRESENT";
|
||||
default:
|
||||
return "UNKNOWN_ERROR";
|
||||
}
|
||||
}
|
||||
|
||||
// Modified memory type selection function with more detailed requirements checking
|
||||
uint32_t findOptimalMemoryType(VkPhysicalDevice physicalDevice,
|
||||
uint32_t typeFilter,
|
||||
VkMemoryPropertyFlags requiredProperties,
|
||||
VkMemoryPropertyFlags preferredProperties = 0) {
|
||||
VkPhysicalDeviceMemoryProperties memProperties;
|
||||
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties);
|
||||
|
||||
// First try to find memory type with all preferred properties
|
||||
if (preferredProperties != 0) {
|
||||
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
|
||||
if ((typeFilter & (1 << i)) &&
|
||||
(memProperties.memoryTypes[i].propertyFlags & (requiredProperties | preferredProperties)) ==
|
||||
(requiredProperties | preferredProperties)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to just required properties
|
||||
for (uint32_t i = 0; i < memProperties.memoryTypeCount; i++) {
|
||||
if ((typeFilter & (1 << i)) &&
|
||||
(memProperties.memoryTypes[i].propertyFlags & requiredProperties) == requiredProperties) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return UINT32_MAX;
|
||||
}
|
||||
|
||||
// Consolidated function for creating Vulkan instance
|
||||
VkResult createVulkanInstance(VkInstance *instance)
|
||||
{
|
||||
std::vector<const char *> instanceExtensions = {
|
||||
VK_KHR_SURFACE_EXTENSION_NAME,
|
||||
VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
|
||||
VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
|
||||
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME};
|
||||
|
||||
VkApplicationInfo appInfo = {};
|
||||
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||
appInfo.pApplicationName = "Vulkan-D3D11 Interop";
|
||||
appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
|
||||
appInfo.pEngineName = "No Engine";
|
||||
appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0);
|
||||
appInfo.apiVersion = VK_API_VERSION_1_1;
|
||||
|
||||
VkInstanceCreateInfo createInfo = {};
|
||||
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||
createInfo.pApplicationInfo = &appInfo;
|
||||
createInfo.enabledExtensionCount = static_cast<uint32_t>(instanceExtensions.size());
|
||||
createInfo.ppEnabledExtensionNames = instanceExtensions.data();
|
||||
|
||||
return vkCreateInstance(&createInfo, nullptr, instance);
|
||||
}
|
||||
|
||||
// Consolidated function for creating logical device
|
||||
VkResult createLogicalDevice(VkInstance instance, VkPhysicalDevice *physicalDevice, VkDevice *device)
|
||||
{
|
||||
uint32_t deviceCount = 0;
|
||||
vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr);
|
||||
std::vector<VkPhysicalDevice> physicalDevices(deviceCount);
|
||||
vkEnumeratePhysicalDevices(instance, &deviceCount, physicalDevices.data());
|
||||
|
||||
if (deviceCount == 0)
|
||||
{
|
||||
return VK_ERROR_INITIALIZATION_FAILED;
|
||||
}
|
||||
|
||||
*physicalDevice = physicalDevices[0];
|
||||
|
||||
std::vector<const char *> deviceExtensions = {
|
||||
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
|
||||
VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME};
|
||||
|
||||
float queuePriority = 1.0f;
|
||||
VkDeviceQueueCreateInfo queueCreateInfo = {};
|
||||
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||
queueCreateInfo.queueFamilyIndex = 0;
|
||||
queueCreateInfo.queueCount = 1;
|
||||
queueCreateInfo.pQueuePriorities = &queuePriority;
|
||||
|
||||
VkDeviceCreateInfo deviceCreateInfo = {};
|
||||
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
||||
deviceCreateInfo.queueCreateInfoCount = 1;
|
||||
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
|
||||
deviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
|
||||
deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data();
|
||||
|
||||
return vkCreateDevice(*physicalDevice, &deviceCreateInfo, nullptr, device);
|
||||
}
|
||||
|
||||
bool checkD3D11VulkanInterop(VkPhysicalDevice physicalDevice, ID3D11Device *d3dDevice)
|
||||
{
|
||||
std::cout << "\n=== Checking D3D11-Vulkan Interop Support in QEMU ===" << std::endl;
|
||||
|
||||
// Check Vulkan external memory capabilities
|
||||
VkPhysicalDeviceExternalImageFormatInfo externFormatInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
|
||||
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT};
|
||||
|
||||
VkPhysicalDeviceImageFormatInfo2 formatInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
|
||||
.pNext = &externFormatInfo,
|
||||
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
.type = VK_IMAGE_TYPE_2D,
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL,
|
||||
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
|
||||
.flags = 0};
|
||||
|
||||
VkExternalImageFormatProperties externFormatProps = {
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES};
|
||||
|
||||
VkImageFormatProperties2 formatProps = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
|
||||
.pNext = &externFormatProps};
|
||||
|
||||
// Check device properties
|
||||
VkPhysicalDeviceProperties deviceProps;
|
||||
vkGetPhysicalDeviceProperties(physicalDevice, &deviceProps);
|
||||
|
||||
std::cout << "Vulkan Device: " << deviceProps.deviceName << std::endl;
|
||||
std::cout << "Driver Version: " << deviceProps.driverVersion << std::endl;
|
||||
std::cout << "API Version: " << VK_VERSION_MAJOR(deviceProps.apiVersion) << "." << VK_VERSION_MINOR(deviceProps.apiVersion) << "." << VK_VERSION_PATCH(deviceProps.apiVersion) << std::endl;
|
||||
|
||||
// Check D3D11 device capabilities
|
||||
D3D11_FEATURE_DATA_D3D11_OPTIONS3 featureData = {};
|
||||
HRESULT hr = d3dDevice->CheckFeatureSupport(
|
||||
D3D11_FEATURE_D3D11_OPTIONS3,
|
||||
&featureData,
|
||||
sizeof(featureData));
|
||||
|
||||
std::cout << "\nChecking D3D11 Device:" << std::endl;
|
||||
|
||||
// Get D3D11 device information
|
||||
IDXGIDevice *dxgiDevice = nullptr;
|
||||
hr = d3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IDXGIAdapter *adapter = nullptr;
|
||||
hr = dxgiDevice->GetAdapter(&adapter);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
DXGI_ADAPTER_DESC desc;
|
||||
adapter->GetDesc(&desc);
|
||||
std::wcout << L"D3D11 Adapter: " << desc.Description << std::endl;
|
||||
adapter->Release();
|
||||
}
|
||||
dxgiDevice->Release();
|
||||
}
|
||||
|
||||
// Check for external memory support
|
||||
VkResult result = vkGetPhysicalDeviceImageFormatProperties2(
|
||||
physicalDevice,
|
||||
&formatInfo,
|
||||
&formatProps);
|
||||
|
||||
std::cout << "\nInterop Support Details:" << std::endl;
|
||||
|
||||
// Check external memory extension
|
||||
uint32_t extensionCount = 0;
|
||||
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, nullptr);
|
||||
std::vector<VkExtensionProperties> extensions(extensionCount);
|
||||
vkEnumerateDeviceExtensionProperties(physicalDevice, nullptr, &extensionCount, extensions.data());
|
||||
|
||||
bool hasExternalMemoryExt = false;
|
||||
bool hasWin32Ext = false;
|
||||
|
||||
for (const auto &ext : extensions)
|
||||
{
|
||||
if (strcmp(ext.extensionName, VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME) == 0)
|
||||
{
|
||||
hasExternalMemoryExt = true;
|
||||
}
|
||||
if (strcmp(ext.extensionName, VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME) == 0)
|
||||
{
|
||||
hasWin32Ext = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "External Memory Extension: " << (hasExternalMemoryExt ? "Yes" : "No") << std::endl;
|
||||
std::cout << "Win32 External Memory Extension: " << (hasWin32Ext ? "Yes" : "No") << std::endl;
|
||||
std::cout << "Format Properties Check: " << (result == VK_SUCCESS ? "Passed" : "Failed") << std::endl;
|
||||
|
||||
// Check memory properties
|
||||
VkPhysicalDeviceMemoryProperties memProps;
|
||||
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps);
|
||||
|
||||
std::cout << "\nMemory Types Available:" << std::endl;
|
||||
for (uint32_t i = 0; i < memProps.memoryTypeCount; i++)
|
||||
{
|
||||
VkMemoryPropertyFlags flags = memProps.memoryTypes[i].propertyFlags;
|
||||
std::cout << "Type " << i << ": ";
|
||||
if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
|
||||
std::cout << "Device Local ";
|
||||
if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
|
||||
std::cout << "Host Visible ";
|
||||
if (flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
|
||||
std::cout << "Host Coherent ";
|
||||
if (flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
|
||||
std::cout << "Host Cached ";
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
// Check if all required features are available
|
||||
bool supportsInterop =
|
||||
hasExternalMemoryExt &&
|
||||
hasWin32Ext &&
|
||||
result == VK_SUCCESS;
|
||||
|
||||
std::cout << "\nFinal Result: " << (supportsInterop ? "Interop Supported" : "Interop Not Supported") << std::endl;
|
||||
std::cout << "================================================" << std::endl;
|
||||
|
||||
return supportsInterop;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
VkInstance instance = VK_NULL_HANDLE;
|
||||
VkPhysicalDevice physicalDevice = VK_NULL_HANDLE;
|
||||
VkDevice device = VK_NULL_HANDLE;
|
||||
VkImage image = VK_NULL_HANDLE;
|
||||
HANDLE sharedHandle = nullptr;
|
||||
|
||||
uint32_t height = 100;
|
||||
uint32_t width = 100;
|
||||
|
||||
std::cout << "[Step 1] Initializing D3D texture..." << std::endl;
|
||||
thermion::windows::d3d::D3DTexture texture(width, height, [=](size_t width, size_t height) {});
|
||||
|
||||
sharedHandle = texture.GetTextureHandle();
|
||||
if (!sharedHandle)
|
||||
{
|
||||
std::cout << "[ERROR] Failed to get shared texture handle!" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
texture.FillBlueAndSaveToBMP("output.bmp");
|
||||
std::cout << "[Info] Filled texture with blue and saved to output.bmp" << std::endl;
|
||||
|
||||
// Create Vulkan instance
|
||||
VkResult result = createVulkanInstance(&instance);
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
std::cout << "[ERROR] Failed to create Vulkan instance! Error: " << VkResultToString(result) << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Create logical device
|
||||
result = createLogicalDevice(instance, &physicalDevice, &device);
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
std::cout << "[ERROR] Failed to create logical device! Error: " << VkResultToString(result) << std::endl;
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// In main(), after creating both D3D11 and Vulkan devices:
|
||||
texture.FillBlueAndSaveToBMP("output.bmp");
|
||||
if (!checkD3D11VulkanInterop(physicalDevice, texture._D3D11Device))
|
||||
{
|
||||
std::cout << "D3D11-Vulkan interop is not supported in this QEMU environment" << std::endl;
|
||||
// Consider falling back to a different approach
|
||||
return 1;
|
||||
}
|
||||
|
||||
VkPhysicalDeviceExternalImageFormatInfo externFormatInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO,
|
||||
.pNext = nullptr,
|
||||
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT};
|
||||
|
||||
VkPhysicalDeviceImageFormatInfo2 formatInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
|
||||
.pNext = &externFormatInfo,
|
||||
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
.type = VK_IMAGE_TYPE_2D,
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL, // Changed to LINEAR for VM compatibility
|
||||
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, // Simplified usage flags
|
||||
.flags = 0};
|
||||
|
||||
VkExternalImageFormatProperties externFormatProps = {
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_IMAGE_FORMAT_PROPERTIES};
|
||||
|
||||
VkImageFormatProperties2 formatProps = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
|
||||
.pNext = &externFormatProps};
|
||||
|
||||
// Query supported features
|
||||
result = vkGetPhysicalDeviceImageFormatProperties2(
|
||||
physicalDevice,
|
||||
&formatInfo,
|
||||
&formatProps);
|
||||
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
std::cout << "VM environment may not support required external memory features" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::cout << "VM environment supports required external memory features" << std::endl;
|
||||
|
||||
// Create image with external memory support
|
||||
VkExternalMemoryImageCreateInfo extImageInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
|
||||
.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT};
|
||||
|
||||
VkImageCreateInfo imageInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||
.pNext = &extImageInfo,
|
||||
.flags = 0,
|
||||
.imageType = VK_IMAGE_TYPE_2D,
|
||||
.format = VK_FORMAT_R8G8B8A8_UNORM,
|
||||
.extent = {width, height, 1},
|
||||
.mipLevels = 1,
|
||||
.arrayLayers = 1,
|
||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||
.tiling = VK_IMAGE_TILING_OPTIMAL, // Changed to LINEAR for VM
|
||||
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, // Simplified usage
|
||||
.sharingMode = VK_SHARING_MODE_EXCLUSIVE,
|
||||
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED};
|
||||
|
||||
result = vkCreateImage(device, &imageInfo, nullptr, &image);
|
||||
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
std::cout << "Failed to create iamge " << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Successfully created image " << std::endl;
|
||||
}
|
||||
|
||||
VkMemoryDedicatedRequirements MemoryDedicatedRequirements{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_REQUIREMENTS,
|
||||
.pNext = nullptr};
|
||||
VkMemoryRequirements2 MemoryRequirements2{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
||||
.pNext = &MemoryDedicatedRequirements};
|
||||
const VkImageMemoryRequirementsInfo2 ImageMemoryRequirementsInfo2{
|
||||
.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_REQUIREMENTS_INFO_2,
|
||||
.pNext = nullptr,
|
||||
.image = image};
|
||||
// WARN: Memory access violation unless validation instance layer is enabled, otherwise success but...
|
||||
vkGetImageMemoryRequirements2(device, &ImageMemoryRequirementsInfo2, &MemoryRequirements2);
|
||||
// ... if we happen to be here, MemoryRequirements2 is empty
|
||||
VkMemoryRequirements &MemoryRequirements = MemoryRequirements2.memoryRequirements;
|
||||
|
||||
const VkMemoryDedicatedAllocateInfo MemoryDedicatedAllocateInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_DEDICATED_ALLOCATE_INFO,
|
||||
.pNext = nullptr,
|
||||
.image = image,
|
||||
.buffer = VK_NULL_HANDLE};
|
||||
const VkImportMemoryWin32HandleInfoKHR ImportMemoryWin32HandleInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_IMPORT_MEMORY_WIN32_HANDLE_INFO_KHR,
|
||||
.pNext = &MemoryDedicatedAllocateInfo,
|
||||
.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT,
|
||||
.handle = sharedHandle,
|
||||
.name = nullptr};
|
||||
VkDeviceMemory ImageMemory = VK_NULL_HANDLE;
|
||||
|
||||
// Find suitable memory type
|
||||
uint32_t memoryTypeIndex = findOptimalMemoryType(
|
||||
physicalDevice,
|
||||
MemoryRequirements.memoryTypeBits,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT // You might need to adjust these flags
|
||||
);
|
||||
|
||||
VkMemoryAllocateInfo allocInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||
.pNext = &ImportMemoryWin32HandleInfo,
|
||||
.allocationSize = MemoryRequirements.size,
|
||||
.memoryTypeIndex = memoryTypeIndex // Assuming 'properties' is your memory type index
|
||||
};
|
||||
|
||||
VkResult allocResult = vkAllocateMemory(device, &allocInfo, nullptr, &ImageMemory);
|
||||
if (allocResult != VK_SUCCESS || ImageMemory == VK_NULL_HANDLE)
|
||||
{
|
||||
std::cout << "IMAGE MEMORY ALLOCATION FAILED:" << std::endl;
|
||||
std::cout << " Allocation size: " << MemoryRequirements.size << " bytes" << std::endl;
|
||||
std::cout << " Memory type index: " << allocInfo.memoryTypeIndex << std::endl;
|
||||
std::cout << " Error code: " << allocResult << std::endl;
|
||||
|
||||
// Get more detailed error message based on VkResult
|
||||
const char *errorMsg;
|
||||
switch (allocResult)
|
||||
{
|
||||
case VK_ERROR_OUT_OF_HOST_MEMORY:
|
||||
errorMsg = "VK_ERROR_OUT_OF_HOST_MEMORY: Out of host memory";
|
||||
break;
|
||||
case VK_ERROR_OUT_OF_DEVICE_MEMORY:
|
||||
errorMsg = "VK_ERROR_OUT_OF_DEVICE_MEMORY: Out of device memory";
|
||||
break;
|
||||
case VK_ERROR_INVALID_EXTERNAL_HANDLE:
|
||||
errorMsg = "VK_ERROR_INVALID_EXTERNAL_HANDLE: The external handle is invalid";
|
||||
break;
|
||||
case VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS:
|
||||
errorMsg = "VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS: The requested address is not available";
|
||||
break;
|
||||
default:
|
||||
errorMsg = "Unknown error";
|
||||
}
|
||||
std::cout << " Error message: " << errorMsg << std::endl;
|
||||
|
||||
// Print shared handle info
|
||||
std::cout << " Shared handle value: " << sharedHandle << std::endl;
|
||||
|
||||
// Print memory requirements
|
||||
std::cout << " Memory requirements:" << std::endl;
|
||||
std::cout << " Size: " << MemoryRequirements.size << std::endl;
|
||||
std::cout << " Alignment: " << MemoryRequirements.alignment << std::endl;
|
||||
std::cout << " Memory type bits: 0x" << std::hex << MemoryRequirements.memoryTypeBits << std::dec << std::endl;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
// memAllocator->Allocate(MemoryRequirements, &ImageMemory, properties, &ImportMemoryWin32HandleInfo);
|
||||
// if(ImageMemory == VK_NULL_HANDLE) {
|
||||
// std::cout << "IMAGE MEMORY ALLOCATION FAILED" << std::endl;
|
||||
// return;
|
||||
// }
|
||||
|
||||
const VkBindImageMemoryInfo bindImageMemoryInfo{
|
||||
.sType = VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_INFO,
|
||||
.pNext = nullptr,
|
||||
.image = image,
|
||||
.memory = ImageMemory,
|
||||
.memoryOffset = 0};
|
||||
|
||||
result = vkBindImageMemory2(device, 1, &bindImageMemoryInfo);
|
||||
|
||||
if (result != VK_SUCCESS)
|
||||
{
|
||||
std::cout << "bindimagememory2 failed" << std::endl;
|
||||
}
|
||||
std::cout << "FIISHED" << std::endl;
|
||||
|
||||
// Cleanup
|
||||
std::cout << "\n[Step 6] Cleaning up resources..." << std::endl;
|
||||
vkDestroyImage(device, image, nullptr);
|
||||
// vkFreeMemory(device, memory, nullptr);
|
||||
vkDestroyDevice(device, nullptr);
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
std::cout << "[Complete] All resources cleaned up successfully" << std::endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
|
||||
#include "egl_context.h"
|
||||
|
||||
namespace thermion::windows::vulkan {
|
||||
|
||||
ThermionEGLContext::ThermionEGLContext() {
|
||||
|
||||
|
||||
|
||||
// *******************
|
||||
// * *
|
||||
// * *
|
||||
// * EGL starts here *
|
||||
// * *
|
||||
// * *
|
||||
// * *
|
||||
// *******************
|
||||
EGLBoolean bindAPI = eglBindAPI(EGL_OPENGL_ES_API);
|
||||
if (!bindAPI) {
|
||||
std::cout << "eglBindAPI EGL_OPENGL_ES_API failed" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (_eglDisplay == EGL_NO_DISPLAY) {
|
||||
std::cout << "eglBindAPI EGL_OPENGL_ES_API failed" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
EGLint major, minor;
|
||||
EGLBoolean initialized = false;
|
||||
|
||||
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 (!initialized) {
|
||||
std::cout << "eglInitialize failed" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// glext::importGLESExtensionsEntryPoints();
|
||||
|
||||
EGLint configsCount;
|
||||
|
||||
EGLint configAttribs[] = {EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_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)) {
|
||||
std::cout << "Failed to find EGL config" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
auto ctx = eglCreateContext(_eglDisplay, _eglConfig, EGL_NO_CONTEXT,contextAttribs);
|
||||
_context = (void*)ctx;
|
||||
|
||||
if (_context == EGL_NO_CONTEXT) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
EGLTexture* ThermionEGLContext::CreateRenderingSurface(
|
||||
uint32_t width, uint32_t height,
|
||||
uint32_t left, uint32_t top
|
||||
) {
|
||||
|
||||
// glext::importGLESExtensionsEntryPoints();
|
||||
|
||||
if(left != 0 || top != 0) {
|
||||
std::cout << "ERROR Rendering with EGL uses a Texture render target/Flutter widget and does not need a window offset." << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//if (_active && _active.get()) {
|
||||
// // result->Error("ERROR",
|
||||
// // "Texture already exists. You must call destroyTexture before "
|
||||
// // "attempting to create a new one.");
|
||||
// return nullptr;
|
||||
//}
|
||||
|
||||
_active = std::make_unique<EGLTexture>(
|
||||
width, height,
|
||||
_D3D11Device, _D3D11DeviceContext, _eglConfig, _eglDisplay, _context,
|
||||
[=](size_t width, size_t height) {
|
||||
std::cout << "RESIZE" << std::endl;
|
||||
std::vector<int64_t> list;
|
||||
list.push_back((int64_t)width);
|
||||
list.push_back((int64_t)height);
|
||||
// auto val = std::make_unique<flutter::EncodableValue>(list);
|
||||
// this->_channel->InvokeMethod("resize", std::move(val), nullptr);
|
||||
});
|
||||
|
||||
return _active.get();
|
||||
}
|
||||
|
||||
void* ThermionEGLContext::GetSharedContext() {
|
||||
return (void*)_context;
|
||||
}
|
||||
|
||||
void ThermionEGLContext::ResizeRenderingSurface(uint32_t width, uint32_t height, uint32_t left, uint32_t top) {
|
||||
|
||||
}
|
||||
|
||||
void ThermionEGLContext::DestroyRenderingSurface() {
|
||||
|
||||
}
|
||||
|
||||
EGLTexture *ThermionEGLContext::GetActiveTexture() {
|
||||
return _active.get();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user