diff --git a/libobs-d3d11/d3d11-subsystem.cpp b/libobs-d3d11/d3d11-subsystem.cpp index 35de8a648..30083c0e2 100644 --- a/libobs-d3d11/d3d11-subsystem.cpp +++ b/libobs-d3d11/d3d11-subsystem.cpp @@ -1805,6 +1805,11 @@ extern "C" EXPORT bool device_gdi_texture_available(void) return true; } +extern "C" EXPORT bool device_shared_texture_available(void) +{ + return true; +} + extern "C" EXPORT gs_texture_t *device_texture_create_gdi(gs_device_t *device, uint32_t width, uint32_t height) { @@ -1860,3 +1865,19 @@ extern "C" EXPORT void gs_texture_release_dc(gs_texture_t *tex) tex2d->gdiSurface->ReleaseDC(nullptr); } + +extern "C" EXPORT gs_texture_t *device_texture_open_shared(gs_device_t *device, + uint32_t handle) +{ + gs_texture *texture = nullptr; + try { + texture = new gs_texture_2d(device, handle); + } catch (HRError error) { + blog(LOG_ERROR, "gs_texture_open_shared (D3D11): %s (%08lX)", + error.str, error.hr); + } catch (const char *error) { + blog(LOG_ERROR, "gs_texture_open_shared (D3D11): %s", error); + } + + return texture; +} diff --git a/libobs-d3d11/d3d11-subsystem.hpp b/libobs-d3d11/d3d11-subsystem.hpp index 237649304..8c0ca7d18 100644 --- a/libobs-d3d11/d3d11-subsystem.hpp +++ b/libobs-d3d11/d3d11-subsystem.hpp @@ -234,6 +234,8 @@ struct gs_texture { ComPtr shaderRes; + inline gs_texture() {} + inline gs_texture(gs_device *device, gs_texture_type type, uint32_t levels, gs_color_format format) : device (device), @@ -258,7 +260,7 @@ struct gs_texture_2d : gs_texture { bool isDynamic; bool isShared; bool genMipmaps; - HANDLE sharedHandle; + uint32_t sharedHandle; void InitSRD(vector &srd, const uint8_t **data); void InitTexture(const uint8_t **data); @@ -283,6 +285,8 @@ struct gs_texture_2d : gs_texture { gs_color_format colorFormat, uint32_t levels, const uint8_t **data, uint32_t flags, gs_texture_type type, bool gdiCompatible, bool shared); + + gs_texture_2d(gs_device_t *device, uint32_t handle); }; struct gs_zstencil_buffer { diff --git a/libobs-d3d11/d3d11-texture2d.cpp b/libobs-d3d11/d3d11-texture2d.cpp index 757c8443d..ddeb364e3 100644 --- a/libobs-d3d11/d3d11-texture2d.cpp +++ b/libobs-d3d11/d3d11-texture2d.cpp @@ -25,7 +25,7 @@ void gs_texture_2d::InitSRD(vector &srd, uint32_t texSizeBytes = height * rowSizeBytes / 8; size_t textures = type == GS_TEXTURE_2D ? 1 : 6; uint32_t actual_levels = levels; - + if (!actual_levels) actual_levels = gs_get_total_levels(width, height); @@ -38,7 +38,7 @@ void gs_texture_2d::InitSRD(vector &srd, for (uint32_t j = 0; j < actual_levels; j++) { D3D11_SUBRESOURCE_DATA newSRD; newSRD.pSysMem = *data; - newSRD.SysMemPitch = newRowSize; + newSRD.SysMemPitch = newRowSize; newSRD.SysMemSlicePitch = newTexSize; srd.push_back(newSRD); @@ -161,3 +161,65 @@ gs_texture_2d::gs_texture_2d(gs_device_t *device, uint32_t width, if (isRenderTarget) InitRenderTargets(); } + +static inline gs_color_format ConvertDXGITextureFormat(DXGI_FORMAT format) +{ + switch (format) { + case DXGI_FORMAT_A8_UNORM: return GS_A8; + case DXGI_FORMAT_R8_UNORM: return GS_R8; + case DXGI_FORMAT_R8G8B8A8_UNORM: return GS_RGBA; + case DXGI_FORMAT_B8G8R8X8_UNORM: return GS_BGRX; + case DXGI_FORMAT_B8G8R8A8_UNORM: return GS_BGRA; + case DXGI_FORMAT_R10G10B10A2_UNORM: return GS_R10G10B10A2; + case DXGI_FORMAT_R16G16B16A16_UNORM: return GS_RGBA16; + case DXGI_FORMAT_R16_UNORM: return GS_R16; + case DXGI_FORMAT_R16G16B16A16_FLOAT: return GS_RGBA16F; + case DXGI_FORMAT_R32G32B32A32_FLOAT: return GS_RGBA32F; + case DXGI_FORMAT_R16G16_FLOAT: return GS_RG16F; + case DXGI_FORMAT_R32G32_FLOAT: return GS_RG32F; + case DXGI_FORMAT_R16_FLOAT: return GS_R16F; + case DXGI_FORMAT_R32_FLOAT: return GS_R32F; + case DXGI_FORMAT_BC1_UNORM: return GS_DXT1; + case DXGI_FORMAT_BC2_UNORM: return GS_DXT3; + case DXGI_FORMAT_BC3_UNORM: return GS_DXT5; + } + + return GS_UNKNOWN; +} + +gs_texture_2d::gs_texture_2d(gs_device_t *device, uint32_t handle) + : isRenderTarget (false), + isGDICompatible (false), + isDynamic (false), + isShared (true), + genMipmaps (false), + sharedHandle (handle) +{ + HRESULT hr; + hr = device->device->OpenSharedResource((HANDLE)handle, + __uuidof(ID3D11Texture2D), (void**)texture.Assign()); + if (FAILED(hr)) + throw HRError("Failed to open resource", hr); + + D3D11_TEXTURE2D_DESC desc; + texture->GetDesc(&desc); + + this->type = GS_TEXTURE_2D; + this->format = ConvertDXGITextureFormat(desc.Format); + this->levels = 1; + this->device = device; + + this->width = desc.Width; + this->height = desc.Height; + this->dxgiFormat = desc.Format; + + D3D11_SHADER_RESOURCE_VIEW_DESC resourceDesc = {}; + resourceDesc.Format = desc.Format; + resourceDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + resourceDesc.Texture2D.MipLevels = 1; + + hr = device->device->CreateShaderResourceView(texture, &resourceDesc, + shaderRes.Assign()); + if (FAILED(hr)) + throw HRError("Failed to create shader resource view", hr); +} diff --git a/libobs-opengl/gl-windows.c b/libobs-opengl/gl-windows.c index 994a51144..b03c78d9c 100644 --- a/libobs-opengl/gl-windows.c +++ b/libobs-opengl/gl-windows.c @@ -532,3 +532,8 @@ EXPORT bool device_gdi_texture_available(void) { return false; } + +EXPORT bool device_shared_texture_available(void) +{ + return false; +} diff --git a/libobs/graphics/graphics-imports.c b/libobs/graphics/graphics-imports.c index 40b75bcac..fc8c8fd02 100644 --- a/libobs/graphics/graphics-imports.c +++ b/libobs/graphics/graphics-imports.c @@ -174,9 +174,11 @@ bool load_graphics_imports(struct gs_exports *exports, void *module, /* win32 specific functions */ #elif _WIN32 GRAPHICS_IMPORT(device_gdi_texture_available); + GRAPHICS_IMPORT(device_shared_texture_available); GRAPHICS_IMPORT_OPTIONAL(device_texture_create_gdi); GRAPHICS_IMPORT_OPTIONAL(gs_texture_get_dc); GRAPHICS_IMPORT_OPTIONAL(gs_texture_release_dc); + GRAPHICS_IMPORT_OPTIONAL(device_texture_open_shared); #endif return success; diff --git a/libobs/graphics/graphics-internal.h b/libobs/graphics/graphics-internal.h index 9fa080e6a..305292a7e 100644 --- a/libobs/graphics/graphics-internal.h +++ b/libobs/graphics/graphics-internal.h @@ -230,11 +230,16 @@ struct gs_exports { #elif _WIN32 bool (*device_gdi_texture_available)(void); + bool (*device_shared_texture_available)(void); + gs_texture_t *(*device_texture_create_gdi)(gs_device_t *device, uint32_t width, uint32_t height); void *(*gs_texture_get_dc)(gs_texture_t *gdi_tex); void (*gs_texture_release_dc)(gs_texture_t *gdi_tex); + + gs_texture_t *(*device_texture_open_shared)(gs_device_t *device, + uint32_t handle); #endif }; diff --git a/libobs/graphics/graphics.c b/libobs/graphics/graphics.c index e4ceb25d9..aae2e439e 100644 --- a/libobs/graphics/graphics.c +++ b/libobs/graphics/graphics.c @@ -1959,6 +1959,14 @@ bool gs_gdi_texture_available(void) return thread_graphics->exports.device_gdi_texture_available(); } +bool gs_shared_texture_available(void) +{ + if (!thread_graphics) + return false; + + return thread_graphics->exports.device_shared_texture_available(); +} + /** creates a windows GDI-lockable texture */ gs_texture_t *gs_texture_create_gdi(uint32_t width, uint32_t height) { @@ -1990,4 +1998,16 @@ void gs_texture_release_dc(gs_texture_t *gdi_tex) thread_graphics->exports.gs_texture_release_dc(gdi_tex); } +gs_texture_t *gs_texture_open_shared(uint32_t handle) +{ + graphics_t *graphics = thread_graphics; + if (!graphics) + return NULL; + + if (graphics->exports.device_texture_open_shared) + return graphics->exports.device_texture_open_shared( + graphics->device, handle); + return NULL; +} + #endif diff --git a/libobs/graphics/graphics.h b/libobs/graphics/graphics.h index 3aa178995..3f1a6766f 100644 --- a/libobs/graphics/graphics.h +++ b/libobs/graphics/graphics.h @@ -702,6 +702,7 @@ EXPORT bool gs_texture_rebind_iosurface(gs_texture_t *texture, #elif _WIN32 EXPORT bool gs_gdi_texture_available(void); +EXPORT bool gs_shared_texture_available(void); /** creates a windows GDI-lockable texture */ EXPORT gs_texture_t *gs_texture_create_gdi(uint32_t width, uint32_t height); @@ -709,6 +710,8 @@ EXPORT gs_texture_t *gs_texture_create_gdi(uint32_t width, uint32_t height); EXPORT void *gs_texture_get_dc(gs_texture_t *gdi_tex); EXPORT void gs_texture_release_dc(gs_texture_t *gdi_tex); +/** creates a windows shared texture from a texture handle */ +EXPORT gs_texture_t *gs_texture_open_shared(uint32_t handle); #endif /* inline functions used by modules */