Sfoglia il codice sorgente

Add support for shared textures to graphics API

jp9000 11 anni fa
parent
commit
caa32cb6d1

+ 21 - 0
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;
+}

+ 5 - 1
libobs-d3d11/d3d11-subsystem.hpp

@@ -234,6 +234,8 @@ struct gs_texture {
 
 	ComPtr<ID3D11ShaderResourceView> 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<D3D11_SUBRESOURCE_DATA> &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 {

+ 64 - 2
libobs-d3d11/d3d11-texture2d.cpp

@@ -25,7 +25,7 @@ void gs_texture_2d::InitSRD(vector<D3D11_SUBRESOURCE_DATA> &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<D3D11_SUBRESOURCE_DATA> &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);
+}

+ 5 - 0
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;
+}

+ 2 - 0
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;

+ 5 - 0
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
 };
 

+ 20 - 0
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

+ 3 - 0
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 */