libobs/graphics: Add texture sharing functions
This commit is contained in:
@@ -736,8 +736,7 @@ gs_texture_t *device_texture_create(gs_device_t *device, uint32_t width,
|
||||
gs_texture *texture = NULL;
|
||||
try {
|
||||
texture = new gs_texture_2d(device, width, height, color_format,
|
||||
levels, data, flags, GS_TEXTURE_2D, false,
|
||||
false);
|
||||
levels, data, flags, GS_TEXTURE_2D, false);
|
||||
} catch (HRError error) {
|
||||
blog(LOG_ERROR, "device_texture_create (D3D11): %s (%08lX)",
|
||||
error.str, error.hr);
|
||||
@@ -756,8 +755,7 @@ gs_texture_t *device_cubetexture_create(gs_device_t *device, uint32_t size,
|
||||
gs_texture *texture = NULL;
|
||||
try {
|
||||
texture = new gs_texture_2d(device, size, size, color_format,
|
||||
levels, data, flags, GS_TEXTURE_CUBE, false,
|
||||
false);
|
||||
levels, data, flags, GS_TEXTURE_CUBE, false);
|
||||
} catch (HRError error) {
|
||||
blog(LOG_ERROR, "device_cubetexture_create (D3D11): %s "
|
||||
"(%08lX)",
|
||||
@@ -2063,7 +2061,7 @@ extern "C" EXPORT gs_texture_t *device_texture_create_gdi(gs_device_t *device,
|
||||
try {
|
||||
texture = new gs_texture_2d(device, width, height, GS_BGRA,
|
||||
1, nullptr, GS_RENDER_TARGET, GS_TEXTURE_2D,
|
||||
true, false);
|
||||
true);
|
||||
} catch (HRError error) {
|
||||
blog(LOG_ERROR, "device_texture_create_gdi (D3D11): %s (%08lX)",
|
||||
error.str, error.hr);
|
||||
@@ -2132,3 +2130,47 @@ extern "C" EXPORT gs_texture_t *device_texture_open_shared(gs_device_t *device,
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
extern "C" EXPORT uint32_t device_texture_get_shared_handle(gs_texture_t *tex)
|
||||
{
|
||||
gs_texture_2d *tex2d = reinterpret_cast<gs_texture_2d *>(tex);
|
||||
if (tex->type != GS_TEXTURE_2D)
|
||||
return GS_INVALID_HANDLE;
|
||||
|
||||
return tex2d->isShared ? tex2d->sharedHandle : GS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
extern "C" EXPORT int device_texture_acquire_sync(gs_texture_t *tex,
|
||||
uint64_t key, uint32_t ms)
|
||||
{
|
||||
gs_texture_2d *tex2d = reinterpret_cast<gs_texture_2d *>(tex);
|
||||
if (tex->type != GS_TEXTURE_2D)
|
||||
return -1;
|
||||
|
||||
ComQIPtr<IDXGIKeyedMutex> keyedMutex(tex2d->texture);
|
||||
if (!keyedMutex)
|
||||
return -1;
|
||||
|
||||
HRESULT hr = keyedMutex->AcquireSync(key, ms);
|
||||
if (hr == S_OK)
|
||||
return 0;
|
||||
else if (hr == WAIT_TIMEOUT)
|
||||
return ETIMEDOUT;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" EXPORT int device_texture_release_sync(gs_texture_t *tex,
|
||||
uint64_t key)
|
||||
{
|
||||
gs_texture_2d *tex2d = reinterpret_cast<gs_texture_2d *>(tex);
|
||||
if (tex->type != GS_TEXTURE_2D)
|
||||
return -1;
|
||||
|
||||
ComQIPtr<IDXGIKeyedMutex> keyedMutex(tex2d->texture);
|
||||
if (!keyedMutex)
|
||||
return -1;
|
||||
|
||||
HRESULT hr = keyedMutex->ReleaseSync(key);
|
||||
return hr == S_OK ? 0 : -1;
|
||||
}
|
||||
|
@@ -344,13 +344,14 @@ struct gs_texture_2d : gs_texture {
|
||||
ComPtr<IDXGISurface1> gdiSurface;
|
||||
|
||||
uint32_t width = 0, height = 0;
|
||||
uint32_t flags = 0;
|
||||
DXGI_FORMAT dxgiFormat = DXGI_FORMAT_UNKNOWN;
|
||||
bool isRenderTarget = false;
|
||||
bool isGDICompatible = false;
|
||||
bool isDynamic = false;
|
||||
bool isShared = false;
|
||||
bool genMipmaps = false;
|
||||
uint32_t sharedHandle = 0;
|
||||
uint32_t sharedHandle = GS_INVALID_HANDLE;
|
||||
|
||||
vector<vector<uint8_t>> data;
|
||||
vector<D3D11_SUBRESOURCE_DATA> srd;
|
||||
@@ -382,7 +383,7 @@ struct gs_texture_2d : gs_texture {
|
||||
gs_texture_2d(gs_device_t *device, uint32_t width, uint32_t height,
|
||||
gs_color_format colorFormat, uint32_t levels,
|
||||
const uint8_t **data, uint32_t flags,
|
||||
gs_texture_type type, bool gdiCompatible, bool shared);
|
||||
gs_texture_type type, bool gdiCompatible);
|
||||
|
||||
gs_texture_2d(gs_device_t *device, uint32_t handle);
|
||||
};
|
||||
|
@@ -96,6 +96,11 @@ void gs_texture_2d::InitTexture(const uint8_t **data)
|
||||
if (isGDICompatible)
|
||||
td.MiscFlags |= D3D11_RESOURCE_MISC_GDI_COMPATIBLE;
|
||||
|
||||
if ((flags & GS_SHARED_KM_TEX) != 0)
|
||||
td.MiscFlags |= D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX;
|
||||
else if ((flags & GS_SHARED_TEX) != 0)
|
||||
td.MiscFlags |= D3D11_RESOURCE_MISC_SHARED;
|
||||
|
||||
if (data) {
|
||||
BackupTexture(data);
|
||||
InitSRD(srd);
|
||||
@@ -112,6 +117,42 @@ void gs_texture_2d::InitTexture(const uint8_t **data)
|
||||
if (FAILED(hr))
|
||||
throw HRError("Failed to create GDI surface", hr);
|
||||
}
|
||||
|
||||
if (isShared) {
|
||||
ComPtr<IDXGIResource> dxgi_res;
|
||||
|
||||
texture->SetEvictionPriority(DXGI_RESOURCE_PRIORITY_MAXIMUM);
|
||||
|
||||
hr = texture->QueryInterface(__uuidof(IDXGIResource),
|
||||
(void**)&dxgi_res);
|
||||
if (FAILED(hr)) {
|
||||
blog(LOG_WARNING, "InitTexture: Failed to query "
|
||||
"interface: %08lX", hr);
|
||||
} else {
|
||||
HANDLE handle;
|
||||
hr = dxgi_res->GetSharedHandle(&handle);
|
||||
if (FAILED(hr)) {
|
||||
blog(LOG_WARNING, "InitTexture: Failed to "
|
||||
"get shared handle: %08lX", hr);
|
||||
} else {
|
||||
sharedHandle = (uint32_t)(uintptr_t)handle;
|
||||
}
|
||||
|
||||
if (flags & GS_SHARED_KM_TEX) {
|
||||
ComPtr<IDXGIKeyedMutex> km;
|
||||
hr = texture->QueryInterface(
|
||||
__uuidof(IDXGIKeyedMutex),
|
||||
(void**)&km);
|
||||
if (FAILED(hr)) {
|
||||
throw HRError("Failed to query "
|
||||
"IDXGIKeyedMutex",
|
||||
hr);
|
||||
}
|
||||
|
||||
km->AcquireSync(0, INFINITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gs_texture_2d::InitResourceView()
|
||||
@@ -164,20 +205,24 @@ void gs_texture_2d::InitRenderTargets()
|
||||
}
|
||||
}
|
||||
|
||||
#define SHARED_FLAGS (GS_SHARED_TEX | GS_SHARED_KM_TEX)
|
||||
|
||||
gs_texture_2d::gs_texture_2d(gs_device_t *device, uint32_t width,
|
||||
uint32_t height, gs_color_format colorFormat, uint32_t levels,
|
||||
const uint8_t **data, uint32_t flags, gs_texture_type type,
|
||||
bool gdiCompatible, bool shared)
|
||||
const uint8_t **data, uint32_t flags_, gs_texture_type type,
|
||||
bool gdiCompatible)
|
||||
: gs_texture (device, gs_type::gs_texture_2d, type, levels,
|
||||
colorFormat),
|
||||
width (width),
|
||||
height (height),
|
||||
flags (flags_),
|
||||
dxgiFormat (ConvertGSTextureFormat(format)),
|
||||
isRenderTarget ((flags & GS_RENDER_TARGET) != 0),
|
||||
isRenderTarget ((flags_ & GS_RENDER_TARGET) != 0),
|
||||
isGDICompatible (gdiCompatible),
|
||||
isDynamic ((flags & GS_DYNAMIC) != 0),
|
||||
isShared (shared),
|
||||
genMipmaps ((flags & GS_BUILD_MIPMAPS) != 0)
|
||||
isDynamic ((flags_ & GS_DYNAMIC) != 0),
|
||||
isShared ((flags_ & SHARED_FLAGS) != 0),
|
||||
genMipmaps ((flags_ & GS_BUILD_MIPMAPS) != 0),
|
||||
sharedHandle (GS_INVALID_HANDLE)
|
||||
{
|
||||
InitTexture(data);
|
||||
InitResourceView();
|
||||
|
Reference in New Issue
Block a user