Commit 6aa50b0d authored by Jérémy VIGNELLES's avatar Jérémy VIGNELLES
Browse files

Removed the struct in favor of an all c++ class

parent fe813e2b
......@@ -25,78 +25,96 @@
#define BORDER_TOP ( 0.95f)
#define BORDER_BOTTOM (-0.90f)
struct render_context
class RenderAPI_D3D11 : public RenderAPI
{
/* resources shared by VLC */
ID3D11Device *d3deviceVLC;
ID3D11DeviceContext *d3dctxVLC;
ID3D11Texture2D *textureVLC; // shared between VLC and the app
HANDLE sharedHandled; // handle of the texture used by VLC and the app
ID3D11RenderTargetView *textureRenderTarget;
public:
virtual void setVlcContext(libvlc_media_player_t *mp) override;
virtual void ProcessDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces* interfaces) override;
void* getVideoFrame(bool* out_updated) override;
/* Direct3D11 device/context */
ID3D11Device *d3device;
ID3D11DeviceContext *d3dctx;
/* VLC callbacks */
bool UpdateOutput( const libvlc_video_direct3d_cfg_t *cfg, libvlc_video_output_cfg_t *out );
void Swap();
bool StartRendering(bool enter, const libvlc_video_direct3d_hdr10_metadata_t *hdr10 );
bool SelectPlane(size_t plane );
bool Setup(const libvlc_video_direct3d_device_cfg_t *cfg, libvlc_video_direct3d_device_setup_t *out );
void Cleanup();
void Resize(void (*report_size_change)(void *report_opaque, unsigned width, unsigned height), void *report_opaque );
UINT vertexBufferStride;
ID3D11Buffer *pVertexBuffer;
private:
void CreateResources(ID3D11Device *d3device, ID3D11DeviceContext *d3dctx);
void ReleaseResources();
void DebugInUnity(LPCSTR message);
void Update(UINT width, UINT height);
UINT quadIndexCount;
/* Unity side resources */
ID3D11Device *m_d3deviceUnity = nullptr;
ID3D11DeviceContext *m_d3dctxUnity = nullptr;
ID3D11Texture2D *m_textureUnity = nullptr;
ID3D11ShaderResourceView *m_textureShaderInput = nullptr;
HANDLE m_sharedHandle = nullptr; // handle of the texture used by VLC and the app
/* texture VLC renders into */
ID3D11Texture2D *texture;
ID3D11ShaderResourceView *textureShaderInput;
/* VLC side resources */
ID3D11Device *m_d3deviceVLC = nullptr;
ID3D11DeviceContext *m_d3dctxVLC = nullptr;
ID3D11Texture2D *m_textureVLC = nullptr; // shared between VLC and the app
ID3D11RenderTargetView *m_textureRenderTarget = nullptr;
CRITICAL_SECTION sizeLock; // the ReportSize callback cannot be called during/after the Cleanup_cb is called
unsigned width, height;
void (*ReportSize)(void *ReportOpaque, unsigned width, unsigned height);
void *ReportOpaque;
CRITICAL_SECTION m_sizeLock; // the ReportSize callback cannot be called during/after the Cleanup_cb is called
unsigned m_width = 0;
unsigned m_height = 0;
void (*m_ReportSize)(void *ReportOpaque, unsigned width, unsigned height) = nullptr;
void *m_reportOpaque = nullptr;
bool updated;
CRITICAL_SECTION outputLock; // the ReportSize callback cannot be called during/after the Cleanup_cb is called
ID3D11Texture2D *outputTexture;
bool m_updated = false;
CRITICAL_SECTION m_outputLock; // the ReportSize callback cannot be called during/after the Cleanup_cb is called
ID3D11Texture2D *m_outputTexture = nullptr;
bool m_initialized = false;
};
class RenderAPI_D3D11 : public RenderAPI
// VLC C-style callbacks
bool UpdateOutput_cb( void *opaque, const libvlc_video_direct3d_cfg_t *cfg, libvlc_video_output_cfg_t *out )
{
public:
RenderAPI_D3D11();
virtual ~RenderAPI_D3D11() { }
virtual void setVlcContext(libvlc_media_player_t *mp) override;
virtual void ProcessDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces* interfaces);
void* getVideoFrame(bool* out_updated) override;
return ((RenderAPI_D3D11*)opaque)->UpdateOutput(cfg, out);
}
private:
void CreateResources(struct render_context *ctx, ID3D11Device *d3device, ID3D11DeviceContext *d3dctx);
void ReleaseResources(struct render_context *ctx);
void DebugInUnity(LPCSTR message);
void Swap_cb( void* opaque )
{
((RenderAPI_D3D11*)opaque)->Swap();
}
private:
ID3D11Device* m_Device;
render_context Context;
bool initialized;
};
bool StartRendering_cb( void *opaque, bool enter, const libvlc_video_direct3d_hdr10_metadata_t *hdr10 )
{
return ((RenderAPI_D3D11*)opaque)->StartRendering(enter, hdr10);
}
bool SelectPlane_cb( void *opaque, size_t plane )
{
return ((RenderAPI_D3D11*)opaque)->SelectPlane(plane);
}
bool Setup_cb( void **opaque, const libvlc_video_direct3d_device_cfg_t *cfg, libvlc_video_direct3d_device_setup_t *out )
{
return ((RenderAPI_D3D11*)*opaque)->Setup(cfg, out);
}
void Cleanup_cb( void *opaque )
{
((RenderAPI_D3D11*)opaque)->Cleanup();
}
// d3d11 callbacks
bool UpdateOutput_cb( void *opaque, const libvlc_video_direct3d_cfg_t *cfg, libvlc_video_output_cfg_t *out );
void Swap_cb( void* opaque );
bool StartRendering_cb( void *opaque, bool enter, const libvlc_video_direct3d_hdr10_metadata_t *hdr10 );
bool SelectPlane_cb( void *opaque, size_t plane );
bool Setup_cb( void **opaque, const libvlc_video_direct3d_device_cfg_t *cfg, libvlc_video_direct3d_device_setup_t *out );
void Cleanup_cb( void *opaque );
void Resize_cb( void *opaque,
void (*report_size_change)(void *report_opaque, unsigned width, unsigned height),
void *report_opaque );
RenderAPI* CreateRenderAPI_D3D11()
void *report_opaque )
{
return new RenderAPI_D3D11();
((RenderAPI_D3D11*)opaque)->Resize(report_size_change, report_opaque);
}
RenderAPI_D3D11::RenderAPI_D3D11()
: m_Device(NULL)
RenderAPI* CreateRenderAPI_D3D11()
{
return new RenderAPI_D3D11();
}
void RenderAPI_D3D11::setVlcContext(libvlc_media_player_t *mp)
......@@ -106,7 +124,7 @@ void RenderAPI_D3D11::setVlcContext(libvlc_media_player_t *mp)
libvlc_video_direct3d_set_callbacks( mp, libvlc_video_direct3d_engine_d3d11,
Setup_cb, Cleanup_cb, Resize_cb, UpdateOutput_cb,
Swap_cb, StartRendering_cb, SelectPlane_cb,
&Context );
this);
}
void RenderAPI_D3D11::ProcessDeviceEvent(UnityGfxDeviceEventType type, IUnityInterfaces* interfaces)
......@@ -136,12 +154,12 @@ void RenderAPI_D3D11::ProcessDeviceEvent(UnityGfxDeviceEventType type, IUnityInt
DEBUG("Could not retrieve d3dctx \n");
return;
}
CreateResources(&Context, d3device, d3dctx);
CreateResources(d3device, d3dctx);
break;
}
case kUnityGfxDeviceEventShutdown:
{
ReleaseResources(&Context);
ReleaseResources();
break;
}
case kUnityGfxDeviceEventAfterReset:
......@@ -155,29 +173,29 @@ void RenderAPI_D3D11::ProcessDeviceEvent(UnityGfxDeviceEventType type, IUnityInt
}
}
void Update(render_context* ctx, UINT width, UINT height)
void RenderAPI_D3D11::Update(UINT width, UINT height)
{
DXGI_FORMAT renderFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
HRESULT hr;
DEBUG("start releasing d3d objects.\n");
EnterCriticalSection(&ctx->outputLock);
EnterCriticalSection(&m_outputLock);
ctx->width = width;
ctx->height = height;
if (ctx->texture)
m_width = width;
m_height = height;
if (m_textureUnity)
{
ctx->texture->Release();
ctx->texture = NULL;
m_textureUnity->Release();
m_textureUnity = NULL;
}
if (ctx->textureShaderInput)
if (m_textureShaderInput)
{
ctx->textureShaderInput->Release();
ctx->textureShaderInput = NULL;
m_textureShaderInput->Release();
m_textureShaderInput = NULL;
}
if (ctx->textureRenderTarget)
if (m_textureRenderTarget)
{
ctx->textureRenderTarget->Release();
ctx->textureRenderTarget = NULL;
m_textureRenderTarget->Release();
m_textureRenderTarget = NULL;
}
DEBUG("Done releasing d3d objects.\n");
......@@ -194,7 +212,7 @@ void Update(render_context* ctx, UINT width, UINT height)
texDesc.Height = height;
texDesc.Width = width;
hr = ctx->d3device->CreateTexture2D( &texDesc, NULL, &ctx->outputTexture );
hr = m_d3deviceUnity->CreateTexture2D( &texDesc, NULL, &m_outputTexture );
if (FAILED(hr))
{
DEBUG("Create output Texture2D FAILED \n");
......@@ -206,7 +224,7 @@ void Update(render_context* ctx, UINT width, UINT height)
texDesc.MiscFlags = D3D11_RESOURCE_MISC_SHARED | D3D11_RESOURCE_MISC_SHARED_NTHANDLE;
hr = ctx->d3device->CreateTexture2D( &texDesc, NULL, &ctx->texture );
hr = m_d3deviceUnity->CreateTexture2D( &texDesc, NULL, &m_textureUnity );
if (FAILED(hr))
{
DEBUG("CreateTexture2D FAILED \n");
......@@ -218,14 +236,14 @@ void Update(render_context* ctx, UINT width, UINT height)
IDXGIResource1* sharedResource = NULL;
hr = ctx->texture->QueryInterface(&sharedResource);
hr = m_textureUnity->QueryInterface(&sharedResource);
if(FAILED(hr))
{
DEBUG("get IDXGIResource1 FAILED \n");
abort();
}
hr = sharedResource->CreateSharedHandle(NULL, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, NULL, &ctx->sharedHandled);
hr = sharedResource->CreateSharedHandle(NULL, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE, NULL, &m_sharedHandle);
if(FAILED(hr))
{
_com_error error(hr);
......@@ -236,7 +254,7 @@ void Update(render_context* ctx, UINT width, UINT height)
sharedResource->Release();
ID3D11Device1* d3d11VLC1;
hr = ctx->d3deviceVLC->QueryInterface(&d3d11VLC1);
hr = m_d3deviceVLC->QueryInterface(&d3d11VLC1);
if(FAILED(hr))
{
_com_error error(hr);
......@@ -244,7 +262,7 @@ void Update(render_context* ctx, UINT width, UINT height)
abort();
}
hr = d3d11VLC1->OpenSharedResource1(ctx->sharedHandled, __uuidof(ID3D11Texture2D), (void**)&ctx->textureVLC);
hr = d3d11VLC1->OpenSharedResource1(m_sharedHandle, __uuidof(ID3D11Texture2D), (void**)&m_textureVLC);
if(FAILED(hr))
{
_com_error error(hr);
......@@ -259,7 +277,7 @@ void Update(render_context* ctx, UINT width, UINT height)
resviewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
resviewDesc.Texture2D.MipLevels = 1;
resviewDesc.Format = texDesc.Format;
hr = ctx->d3device->CreateShaderResourceView(ctx->outputTexture, &resviewDesc, &ctx->textureShaderInput );
hr = m_d3deviceUnity->CreateShaderResourceView(m_outputTexture, &resviewDesc, &m_textureShaderInput );
if (FAILED(hr))
{
DEBUG("CreateShaderResourceView FAILED \n");
......@@ -274,33 +292,27 @@ void Update(render_context* ctx, UINT width, UINT height)
renderTargetViewDesc.Format = texDesc.Format;
renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
//*
hr = ctx->d3deviceVLC->CreateRenderTargetView(ctx->textureVLC, &renderTargetViewDesc, &ctx->textureRenderTarget);
/*/
hr = ctx->d3device->CreateRenderTargetView(ctx->texture, &renderTargetViewDesc, &ctx->textureRenderTarget);
//*/
hr = m_d3deviceVLC->CreateRenderTargetView(m_textureVLC, &renderTargetViewDesc, &m_textureRenderTarget);
if (FAILED(hr))
{
DEBUG("CreateRenderTargetView FAILED \n");
}
LeaveCriticalSection(&ctx->outputLock);
LeaveCriticalSection(&m_outputLock);
}
void RenderAPI_D3D11::CreateResources(struct render_context *ctx, ID3D11Device *d3device, ID3D11DeviceContext *d3dctx)
void RenderAPI_D3D11::CreateResources(ID3D11Device *d3device, ID3D11DeviceContext *d3dctx)
{
DEBUG("Entering CreateResources \n");
HRESULT hr;
assert(ctx != nullptr);
ZeroMemory(ctx, sizeof(*ctx));
ZeroMemory(&m_sizeLock, sizeof(CRITICAL_SECTION));
InitializeCriticalSection(&m_sizeLock);
ZeroMemory(&m_outputLock, sizeof(CRITICAL_SECTION));
InitializeCriticalSection(&m_outputLock);
InitializeCriticalSection(&ctx->sizeLock);
InitializeCriticalSection(&ctx->outputLock);
ctx->d3device = d3device;
ctx->d3dctx = d3dctx;
m_d3deviceUnity = d3device;
m_d3dctxUnity = d3dctx;
UINT creationFlags = D3D11_CREATE_DEVICE_VIDEO_SUPPORT; /* needed for hardware decoding */
creationFlags |= D3D11_CREATE_DEVICE_DEBUG; //TODO: remove for release mode
......@@ -312,9 +324,10 @@ void RenderAPI_D3D11::CreateResources(struct render_context *ctx, ID3D11Device *
NULL,
NULL,
D3D11_SDK_VERSION,
&ctx->d3deviceVLC,
&m_d3deviceVLC,
NULL,
&ctx->d3dctxVLC);
&m_d3dctxVLC);
DEBUG("CreateResources m_d3dctxVLC = %p this = %p", m_d3dctxVLC, this);
if(FAILED(hr))
{
......@@ -326,54 +339,63 @@ void RenderAPI_D3D11::CreateResources(struct render_context *ctx, ID3D11Device *
/* The ID3D11Device must have multithread protection */
ID3D10Multithread *pMultithread;
hr = ctx->d3device->QueryInterface(&pMultithread);
hr = m_d3deviceUnity->QueryInterface(&pMultithread);
if (SUCCEEDED(hr)) {
pMultithread->SetMultithreadProtected(TRUE);
pMultithread->Release();
}
ctx->quadIndexCount = 6;
Update(ctx, SCREEN_WIDTH, SCREEN_HEIGHT);
Update(SCREEN_WIDTH, SCREEN_HEIGHT);
DEBUG("Exiting CreateResources.\n");
}
void RenderAPI_D3D11::ReleaseResources(struct render_context *ctx)
void RenderAPI_D3D11::ReleaseResources()
{
DEBUG("Entering ReleaseResources.\n");
if(ctx->d3deviceVLC)
ctx->d3deviceVLC->Release();
if(m_d3deviceVLC)
{
m_d3deviceVLC->Release();
m_d3deviceVLC = nullptr;
}
if(ctx->d3dctxVLC)
ctx->d3dctxVLC->Release();
if(m_d3dctxVLC)
{
m_d3dctxVLC->Release();
m_d3deviceVLC = nullptr;
}
if(ctx->textureRenderTarget)
ctx->textureRenderTarget->Release();
if(m_textureRenderTarget)
{
m_textureRenderTarget->Release();
m_textureRenderTarget = nullptr;
}
if(ctx->textureShaderInput)
ctx->textureShaderInput->Release();
if(m_textureShaderInput)
{
m_textureShaderInput->Release();
m_textureShaderInput = nullptr;
}
if(ctx->texture)
ctx->texture->Release();
if(m_textureUnity)
{
m_textureUnity->Release();
m_textureUnity = nullptr;
}
if(ctx->outputTexture)
ctx->outputTexture->Release();
if(ctx->pVertexBuffer)
ctx->pVertexBuffer->Release();
if(m_outputTexture)
{
m_outputTexture->Release();
m_outputTexture = nullptr;
}
}
bool UpdateOutput_cb( void *opaque, const libvlc_video_direct3d_cfg_t *cfg, libvlc_video_output_cfg_t *out )
bool RenderAPI_D3D11::UpdateOutput( const libvlc_video_direct3d_cfg_t *cfg, libvlc_video_output_cfg_t *out )
{
DEBUG("Entering UpdateOutput_cb.\n");
struct render_context *ctx = static_cast<struct render_context *>( opaque );
assert(ctx != nullptr);
DXGI_FORMAT renderFormat = DXGI_FORMAT_R8G8B8A8_UNORM;
Update(ctx, cfg->width, cfg->height);
DEBUG("Done \n");
Update(cfg->width, cfg->height);
out->surface_format = renderFormat;
out->full_range = true;
......@@ -386,96 +408,87 @@ bool UpdateOutput_cb( void *opaque, const libvlc_video_direct3d_cfg_t *cfg, libv
return true;
}
void Swap_cb( void* opaque )
void RenderAPI_D3D11::Swap()
{
struct render_context *ctx = static_cast<struct render_context *>( opaque );
ctx->d3dctxVLC->Flush();
ctx->updated = true;
m_d3dctxVLC->Flush();
m_updated = true;
}
bool StartRendering_cb( void *opaque, bool enter, const libvlc_video_direct3d_hdr10_metadata_t *hdr10 )
bool RenderAPI_D3D11::StartRendering( bool enter, const libvlc_video_direct3d_hdr10_metadata_t *hdr10 )
{
struct render_context *ctx = static_cast<struct render_context *>( opaque );
if ( enter )
{
EnterCriticalSection(&ctx->outputLock);
EnterCriticalSection(&m_outputLock);
static const FLOAT blackRGBA[4] = {0.0f, 0.0f, 0.0f, 1.0f};
ctx->d3dctxVLC->OMSetRenderTargets(1, &ctx->textureRenderTarget, NULL);
ctx->d3dctxVLC->ClearRenderTargetView( ctx->textureRenderTarget, blackRGBA);
m_d3dctxVLC->OMSetRenderTargets(1, &m_textureRenderTarget, NULL);
m_d3dctxVLC->ClearRenderTargetView( m_textureRenderTarget, blackRGBA);
return true;
}
LeaveCriticalSection(&ctx->outputLock);
LeaveCriticalSection(&m_outputLock);
return true;
}
bool SelectPlane_cb( void *opaque, size_t plane )
bool RenderAPI_D3D11::SelectPlane( size_t plane )
{
struct render_context *ctx = static_cast<struct render_context *>( opaque );
if ( plane != 0 ) // we only support one packed RGBA plane (DXGI_FORMAT_R8G8B8A8_UNORM)
return false;
ctx->d3dctxVLC->OMSetRenderTargets( 1, &ctx->textureRenderTarget, NULL );
m_d3dctxVLC->OMSetRenderTargets( 1, &m_textureRenderTarget, NULL );
return true;
}
bool Setup_cb( void **opaque, const libvlc_video_direct3d_device_cfg_t *cfg, libvlc_video_direct3d_device_setup_t *out )
bool RenderAPI_D3D11::Setup( const libvlc_video_direct3d_device_cfg_t *cfg, libvlc_video_direct3d_device_setup_t *out )
{
struct render_context *ctx = static_cast<struct render_context *>(*opaque);
out->device_context = ctx->d3dctxVLC;
DEBUG("Setup m_d3dctxVLC = %p this = %p", m_d3dctxVLC, this);
out->device_context = m_d3dctxVLC;
return true;
}
void Cleanup_cb( void *opaque )
void RenderAPI_D3D11::Cleanup()
{
// here we can release all things Direct3D11 for good (if playing only one file)
struct render_context *ctx = static_cast<struct render_context *>( opaque );
}
void Resize_cb( void *opaque,
void (*report_size_change)(void *report_opaque, unsigned width, unsigned height),
void RenderAPI_D3D11::Resize(void (*report_size_change)(void *report_opaque, unsigned width, unsigned height),
void *report_opaque )
{
DEBUG("Resize_cb called \n");
EnterCriticalSection(&m_sizeLock);
m_ReportSize = report_size_change;
m_reportOpaque = report_opaque;
struct render_context *ctx = static_cast<struct render_context *>( opaque );
DEBUG("ctx ptr => %p \n", ctx);
EnterCriticalSection(&ctx->sizeLock);
ctx->ReportSize = report_size_change;
ctx->ReportOpaque = report_opaque;
if (ctx->ReportSize != nullptr)
if (m_ReportSize != nullptr)
{
DEBUG("Invoking ctx->ReportSize(ctx->ReportOpaque, ctx->width, ctx->height) with width=%u and height=%u \n", ctx->width, ctx->height);
DEBUG("Invoking m_ReportSize(m_reportOpaque, m_width, m_height) with width=%u and height=%u \n", m_width, m_height);
/* report our initial size */
ctx->ReportSize(ctx->ReportOpaque, ctx->width, ctx->height);
m_ReportSize(m_reportOpaque, m_width, m_height);
}
LeaveCriticalSection(&ctx->sizeLock);
LeaveCriticalSection(&m_sizeLock);
DEBUG("Exiting Resize_cb");
}
void* RenderAPI_D3D11::getVideoFrame(bool* out_updated)
{
EnterCriticalSection(&Context.outputLock);
*out_updated = Context.updated;
if(Context.updated)
EnterCriticalSection(&m_outputLock);
*out_updated = m_updated;
if(m_updated)
{
Context.updated = false;
m_updated = false;
D3D11_BOX box = {
.top = 0,
.bottom = Context.height,
.bottom = m_height,
.left = 0,
.right = Context.width,
.right = m_width,
.back = 1,
};
Context.d3dctx->CopySubresourceRegion(Context.outputTexture, 0, 0, 0, 0, Context.texture, 0, &box);
m_d3dctxUnity->CopySubresourceRegion(m_outputTexture, 0, 0, 0, 0, m_textureUnity, 0, &box);
}
LeaveCriticalSection(&Context.outputLock);
return Context.textureShaderInput;
LeaveCriticalSection(&m_outputLock);
return m_textureShaderInput;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment