From e515cdc8dd36d1b1a4cef2980388e2f278c419a9 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Sat, 28 Jul 2018 06:15:55 +1000 Subject: [PATCH] [host] added YUV420 output support --- common/KVMFR.h | 2 +- host/Capture/DXGI.cpp | 203 ++++++++++++++---------- host/Capture/DXGI.h | 8 +- host/Shaders/BGRAtoNV12.hlsl | 26 --- host/Shaders/Pixel.hlsl | 13 ++ host/Shaders/RGBtoYUV.hlsl | 31 ++++ host/TextureConverter.cpp | 193 ++++++++++++++++------ host/TextureConverter.h | 22 ++- host/looking-glass-host.vcxproj | 11 +- host/looking-glass-host.vcxproj.filters | 7 +- 10 files changed, 339 insertions(+), 177 deletions(-) delete mode 100644 host/Shaders/BGRAtoNV12.hlsl create mode 100644 host/Shaders/Pixel.hlsl create mode 100644 host/Shaders/RGBtoYUV.hlsl diff --git a/common/KVMFR.h b/common/KVMFR.h index a884206f..9f19ad9c 100644 --- a/common/KVMFR.h +++ b/common/KVMFR.h @@ -27,7 +27,7 @@ typedef enum FrameType { FRAME_TYPE_INVALID , FRAME_TYPE_ARGB , // ABGR interleaved: A,R,G,B 32bpp - FRAME_TYPE_NV12 , // NV12 + FRAME_TYPE_YUV420 , // YUV420 FRAME_TYPE_H264 , // H264 compressed FRAME_TYPE_MAX , // sentinel value } diff --git a/host/Capture/DXGI.cpp b/host/Capture/DXGI.cpp index 8c4d191c..6615f281 100644 --- a/host/Capture/DXGI.cpp +++ b/host/Capture/DXGI.cpp @@ -30,7 +30,6 @@ DXGI::DXGI() : m_device(), m_deviceContext(), m_dup(), - m_texture(), m_pointer(NULL) { } @@ -152,8 +151,8 @@ bool DXGI::Initialize(CaptureOptions * options) m_frameType = FRAME_TYPE_ARGB; for(CaptureOptions::const_iterator it = m_options->cbegin(); it != m_options->cend(); ++it) { - if (_stricmp(*it, "h264") == 0) m_frameType = FRAME_TYPE_H264; - if (_stricmp(*it, "nv12") == 0) m_frameType = FRAME_TYPE_NV12; + if (_stricmp(*it, "h264" ) == 0) m_frameType = FRAME_TYPE_H264; + if (_stricmp(*it, "yuv420") == 0) m_frameType = FRAME_TYPE_YUV420; } if (m_frameType == FRAME_TYPE_H264) @@ -162,9 +161,9 @@ bool DXGI::Initialize(CaptureOptions * options) bool ok = false; switch (m_frameType) { - case FRAME_TYPE_ARGB: ok = InitRawCapture (); break; - case FRAME_TYPE_NV12: ok = InitNV12Capture(); break; - case FRAME_TYPE_H264: ok = InitH264Capture(); break; + case FRAME_TYPE_ARGB : ok = InitRawCapture (); break; + case FRAME_TYPE_YUV420: ok = InitYUV420Capture(); break; + case FRAME_TYPE_H264 : ok = InitH264Capture (); break; } if (!ok) @@ -221,7 +220,7 @@ bool DXGI::InitRawCapture() texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; texDesc.MiscFlags = 0; - HRESULT status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture); + HRESULT status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture[0]); if (FAILED(status)) { DEBUG_WINERROR("Failed to create texture", status); @@ -231,9 +230,11 @@ bool DXGI::InitRawCapture() return true; } -bool DXGI::InitNV12Capture() +bool DXGI::InitYUV420Capture() { + HRESULT status; D3D11_TEXTURE2D_DESC texDesc; + ZeroMemory(&texDesc, sizeof(texDesc)); texDesc.Width = m_width; texDesc.Height = m_height; @@ -242,12 +243,29 @@ bool DXGI::InitNV12Capture() texDesc.SampleDesc.Count = 1; texDesc.SampleDesc.Quality = 0; texDesc.Usage = D3D11_USAGE_STAGING; - texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; + texDesc.Format = DXGI_FORMAT_R8_UNORM; texDesc.BindFlags = 0; texDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; texDesc.MiscFlags = 0; - HRESULT status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture); + status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture[0]); + if (FAILED(status)) + { + DEBUG_WINERROR("Failed to create texture", status); + return false; + } + + texDesc.Width /= 2; + texDesc.Height /= 2; + + status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture[1]); + if (FAILED(status)) + { + DEBUG_WINERROR("Failed to create texture", status); + return false; + } + + status = m_device->CreateTexture2D(&texDesc, NULL, &m_texture[2]); if (FAILED(status)) { DEBUG_WINERROR("Failed to create texture", status); @@ -255,7 +273,7 @@ bool DXGI::InitNV12Capture() } m_textureConverter = new TextureConverter(); - if (!m_textureConverter->Initialize(m_deviceContext, m_device, m_width, m_height, DXGI_FORMAT_NV12)) + if (!m_textureConverter->Initialize(m_deviceContext, m_device, m_width, m_height, FRAME_TYPE_YUV420)) return false; return true; @@ -264,7 +282,7 @@ bool DXGI::InitNV12Capture() bool DXGI::InitH264Capture() { m_textureConverter = new TextureConverter(); - if (!m_textureConverter->Initialize(m_deviceContext, m_device, m_width, m_height, DXGI_FORMAT_NV12)) + if (!m_textureConverter->Initialize(m_deviceContext, m_device, m_width, m_height, FRAME_TYPE_YUV420)) return false; m_h264 = new MFT::H264(); @@ -297,13 +315,9 @@ void DXGI::DeInitialize() m_pointerBufSize = 0; } - if (m_surfaceMapped) - { - m_deviceContext->Unmap(m_texture, 0); - m_surfaceMapped = false; - } - - SafeRelease(&m_texture); + SafeRelease(&m_texture[0]); + SafeRelease(&m_texture[1]); + SafeRelease(&m_texture[2]); SafeRelease(&m_dup); SafeRelease(&m_output); SafeRelease(&m_deviceContext); @@ -493,54 +507,10 @@ GrabStatus Capture::DXGI::ReleaseFrame() GrabStatus Capture::DXGI::GrabFrameRaw(FrameInfo & frame, struct CursorInfo & cursor) { - GrabStatus result; - ID3D11Texture2DPtr src; - bool timeout; - - result = GrabFrameTexture(frame, cursor, src, timeout); - if (timeout) - return GRAB_STATUS_TIMEOUT; - - if (result != GRAB_STATUS_OK) - return result; - - if (m_surfaceMapped) - { - m_deviceContext->Unmap(m_texture, 0); - m_surfaceMapped = false; - } - - m_deviceContext->CopyResource(m_texture, src); - SafeRelease(&src); - - result = ReleaseFrame(); - if (result != GRAB_STATUS_OK) - return result; - - HRESULT status; - status = m_deviceContext->Map(m_texture, 0, D3D11_MAP_READ, 0, &m_mapping); - if (FAILED(status)) - { - DEBUG_WINERROR("Failed to map the texture", status); - DeInitialize(); - return GRAB_STATUS_ERROR; - } - m_surfaceMapped = true; - - frame.pitch = m_mapping.RowPitch; - frame.stride = m_mapping.RowPitch >> 2; - - const unsigned int size = m_height * m_mapping.RowPitch; - memcpySSE(frame.buffer, m_mapping.pData, LG_MIN(size, frame.bufferSize)); - - return GRAB_STATUS_OK; -} - -GrabStatus Capture::DXGI::GrabFrameNV12(struct FrameInfo & frame, struct CursorInfo & cursor) -{ - GrabStatus result; - ID3D11Texture2DPtr texture; - bool timeout; + GrabStatus result; + ID3D11Texture2DPtr texture; + bool timeout; + D3D11_MAPPED_SUBRESOURCE mapping; result = GrabFrameTexture(frame, cursor, texture, timeout); if (timeout) @@ -549,19 +519,7 @@ GrabStatus Capture::DXGI::GrabFrameNV12(struct FrameInfo & frame, struct CursorI if (result != GRAB_STATUS_OK) return result; - if (!m_textureConverter->Convert(texture)) - { - SafeRelease(&texture); - return GRAB_STATUS_ERROR; - } - - if (m_surfaceMapped) - { - m_deviceContext->Unmap(m_texture, 0); - m_surfaceMapped = false; - } - - m_deviceContext->CopyResource(m_texture, texture); + m_deviceContext->CopyResource(m_texture[0], texture); SafeRelease(&texture); result = ReleaseFrame(); @@ -569,26 +527,94 @@ GrabStatus Capture::DXGI::GrabFrameNV12(struct FrameInfo & frame, struct CursorI return result; HRESULT status; - status = m_deviceContext->Map(m_texture, 0, D3D11_MAP_READ, 0, &m_mapping); + status = m_deviceContext->Map(m_texture[0], 0, D3D11_MAP_READ, 0, &mapping); if (FAILED(status)) { DEBUG_WINERROR("Failed to map the texture", status); DeInitialize(); return GRAB_STATUS_ERROR; } - m_surfaceMapped = true; - frame.pitch = m_mapping.RowPitch; - frame.stride = m_mapping.RowPitch >> 2; + frame.pitch = mapping.RowPitch; + frame.stride = mapping.RowPitch >> 2; - const unsigned int size = m_height * m_mapping.RowPitch; - memcpySSE(frame.buffer, m_mapping.pData, LG_MIN(size, frame.bufferSize)); + const unsigned int size = m_height * mapping.RowPitch; + memcpySSE(frame.buffer, mapping.pData, LG_MIN(size, frame.bufferSize)); + m_deviceContext->Unmap(m_texture[0], 0); return GRAB_STATUS_OK; } +GrabStatus Capture::DXGI::GrabFrameYUV420(struct FrameInfo & frame, struct CursorInfo & cursor) +{ + GrabStatus result; + ID3D11Texture2DPtr texture; + bool timeout; + + result = GrabFrameTexture(frame, cursor, texture, timeout); + if (timeout) + return GRAB_STATUS_TIMEOUT; + + if (result != GRAB_STATUS_OK) + return result; + + TextureList planes; + if (!m_textureConverter->Convert(texture, planes)) + { + SafeRelease(&texture); + return GRAB_STATUS_ERROR; + } + SafeRelease(&texture); + + for(int i = 0; i < 3; ++i) + { + ID3D11Texture2DPtr t = planes.at(i); + m_deviceContext->CopyResource(m_texture[i], planes.at(i)); + SafeRelease(&t); + } + + result = ReleaseFrame(); + if (result != GRAB_STATUS_OK) + return result; + + uint8_t * data = (uint8_t *)frame.buffer; + size_t remain = frame.bufferSize; + for(int i = 0; i < 3; ++i) + { + HRESULT status; + D3D11_MAPPED_SUBRESOURCE mapping; + + status = m_deviceContext->Map(m_texture[i], 0, D3D11_MAP_READ, 0, &mapping); + if (FAILED(status)) + { + DEBUG_WINERROR("Failed to map the texture", status); + DeInitialize(); + return GRAB_STATUS_ERROR; + } + + const unsigned int size = m_height * mapping.RowPitch; + if (size > remain) + { + m_deviceContext->Unmap(m_texture[i], 0); + DEBUG_ERROR("Too much data to fit in buffer"); + return GRAB_STATUS_ERROR; + } + + memcpySSE(data, mapping.pData, size); + data += size; + remain -= size; + m_deviceContext->Unmap(m_texture[i], 0); + } + + frame.pitch = m_width; + frame.stride = m_width; + return GRAB_STATUS_OK; +} + GrabStatus Capture::DXGI::GrabFrameH264(struct FrameInfo & frame, struct CursorInfo & cursor) { + return GRAB_STATUS_ERROR; + #if 0 while(true) { unsigned int events = m_h264->Process(); @@ -631,6 +657,7 @@ GrabStatus Capture::DXGI::GrabFrameH264(struct FrameInfo & frame, struct CursorI return GRAB_STATUS_OK; } } + #endif } GrabStatus DXGI::GrabFrame(struct FrameInfo & frame, struct CursorInfo & cursor) @@ -640,8 +667,8 @@ GrabStatus DXGI::GrabFrame(struct FrameInfo & frame, struct CursorInfo & cursor) switch (m_frameType) { - case FRAME_TYPE_NV12: return GrabFrameNV12(frame, cursor); - case FRAME_TYPE_H264: return GrabFrameH264(frame, cursor); + case FRAME_TYPE_YUV420: return GrabFrameYUV420(frame, cursor); + case FRAME_TYPE_H264 : return GrabFrameH264 (frame, cursor); } return GrabFrameRaw(frame, cursor); diff --git a/host/Capture/DXGI.h b/host/Capture/DXGI.h index 452e47b1..45471f85 100644 --- a/host/Capture/DXGI.h +++ b/host/Capture/DXGI.h @@ -60,13 +60,13 @@ namespace Capture private: bool InitRawCapture(); - bool InitNV12Capture(); + bool InitYUV420Capture(); bool InitH264Capture(); GrabStatus GrabFrameTexture(struct FrameInfo & frame, struct CursorInfo & cursor, ID3D11Texture2DPtr & texture, bool & timeout); GrabStatus ReleaseFrame(); GrabStatus GrabFrameRaw (struct FrameInfo & frame, struct CursorInfo & cursor); - GrabStatus GrabFrameNV12 (struct FrameInfo & frame, struct CursorInfo & cursor); + GrabStatus GrabFrameYUV420 (struct FrameInfo & frame, struct CursorInfo & cursor); GrabStatus GrabFrameH264 (struct FrameInfo & frame, struct CursorInfo & cursor); CaptureOptions * m_options; @@ -83,9 +83,7 @@ namespace Capture IDXGIOutput1Ptr m_output; IDXGIOutputDuplicationPtr m_dup; bool m_releaseFrame; - ID3D11Texture2DPtr m_texture; - D3D11_MAPPED_SUBRESOURCE m_mapping; - bool m_surfaceMapped; + ID3D11Texture2DPtr m_texture[3]; TextureConverter * m_textureConverter; MFT::H264 * m_h264; diff --git a/host/Shaders/BGRAtoNV12.hlsl b/host/Shaders/BGRAtoNV12.hlsl deleted file mode 100644 index 88dce5cd..00000000 --- a/host/Shaders/BGRAtoNV12.hlsl +++ /dev/null @@ -1,26 +0,0 @@ -Texture2D texTexture; -SamplerState texSampler; - -struct VS -{ - float4 pos : SV_Position; - float2 tex : TEXCOORD; -}; - -float4 RGBtoYUV(float4 rgba) -{ - float4 yuva; - yuva.r = rgba.r * 0.2126 + 0.7152 * rgba.g + 0.0722 * rgba.b; - yuva.g = (rgba.b - yuva.r) / 1.8556; - yuva.b = (rgba.r - yuva.r) / 1.5748; - yuva.a = rgba.a; - yuva.gb += 0.5; - return yuva; -} - -float4 main(VS input) : SV_TARGET -{ - const float4 rgba = texTexture.Sample(texSampler, input.tex); - const float4 yuva = RGBtoYUV(rgba); - return yuva; -} \ No newline at end of file diff --git a/host/Shaders/Pixel.hlsl b/host/Shaders/Pixel.hlsl new file mode 100644 index 00000000..a8cb1489 --- /dev/null +++ b/host/Shaders/Pixel.hlsl @@ -0,0 +1,13 @@ +Texture2D texTexture; +SamplerState texSampler; + +struct VS +{ + float4 pos : SV_Position; + float2 tex : TEXCOORD; +}; + +float4 main(VS input): SV_Target +{ + return texTexture.Sample(texSampler, input.tex); +} \ No newline at end of file diff --git a/host/Shaders/RGBtoYUV.hlsl b/host/Shaders/RGBtoYUV.hlsl new file mode 100644 index 00000000..a6ce5288 --- /dev/null +++ b/host/Shaders/RGBtoYUV.hlsl @@ -0,0 +1,31 @@ +Texture2D texTexture; +SamplerState texSampler; + +struct VS +{ + float4 pos : SV_Position; + float2 tex : TEXCOORD; +}; + +struct OUT +{ + float4 y: SV_TARGET0; + float4 u: SV_TARGET1; + float4 v: SV_TARGET2; +}; + +OUT main(VS input) +{ + OUT o; + const float4 rgba = texTexture.Sample(texSampler, input.tex); + + o.y.gba = 0.0f; + o.u.gba = 0.0f; + o.v.gba = 0.0f; + + o.y.r = rgba.r * 0.2126 + 0.7152 * rgba.g + 0.0722 * rgba.b; + o.u.r = (rgba.b - o.y.r) / 1.8556; + o.v.r = (rgba.r - o.y.r) / 1.5748; + + return o; +} \ No newline at end of file diff --git a/host/TextureConverter.cpp b/host/TextureConverter.cpp index a6384545..e6fae790 100644 --- a/host/TextureConverter.cpp +++ b/host/TextureConverter.cpp @@ -21,7 +21,8 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include "common\debug.h" #include "Shaders\Vertex.h" -#include "Shaders\BGRAtoNV12.h" +#include "Shaders\Pixel.h" +#include "Shaders\RGBtoYUV.h" TextureConverter::TextureConverter() { @@ -37,12 +38,12 @@ bool TextureConverter::Initialize( ID3D11DevicePtr device, const unsigned int width, const unsigned int height, - DXGI_FORMAT format + FrameType format ) { HRESULT result; D3D11_TEXTURE2D_DESC texDesc; - D3D11_RENDER_TARGET_VIEW_DESC viewDesc; + D3D11_RENDER_TARGET_VIEW_DESC targetDesc; D3D11_SHADER_RESOURCE_VIEW_DESC shaderDesc; D3D11_SAMPLER_DESC samplerDesc; @@ -52,10 +53,21 @@ bool TextureConverter::Initialize( m_height = height; m_format = format; + result = device->CreatePixelShader(g_Pixel, sizeof(g_Pixel), NULL, &m_psCopy); + if (FAILED(result)) + { + DeInitialize(); + DEBUG_ERROR("Failed to create the copy pixel shader"); + return false; + } + switch (format) { - case DXGI_FORMAT_NV12: - result = device->CreatePixelShader(g_BGRAtoNV12, sizeof(g_BGRAtoNV12), NULL, &m_pixelShader); + case FRAME_TYPE_YUV420: + result = device->CreatePixelShader(g_RGBtoYUV, sizeof(g_RGBtoYUV), NULL, &m_psConversion); + m_texFormats[0] = DXGI_FORMAT_R8_UNORM; m_scaleFormats[0] = 1.0f; + m_texFormats[1] = DXGI_FORMAT_R8_UNORM; m_scaleFormats[1] = 0.5f; + m_texFormats[2] = DXGI_FORMAT_R8_UNORM; m_scaleFormats[2] = 0.5f; break; default: @@ -93,7 +105,7 @@ bool TextureConverter::Initialize( } ZeroMemory(&texDesc , sizeof(texDesc )); - ZeroMemory(&viewDesc , sizeof(viewDesc )); + ZeroMemory(&targetDesc , sizeof(targetDesc )); ZeroMemory(&shaderDesc , sizeof(shaderDesc )); ZeroMemory(&samplerDesc, sizeof(samplerDesc)); @@ -105,25 +117,45 @@ bool TextureConverter::Initialize( texDesc.Usage = D3D11_USAGE_DEFAULT; texDesc.CPUAccessFlags = 0; texDesc.MiscFlags = 0; - texDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; texDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE; - result = device->CreateTexture2D(&texDesc, NULL, &m_targetTexture); - if (FAILED(result)) - { - DeInitialize(); - DEBUG_ERROR("Failed to create the render texture"); - return false; - } - viewDesc.Format = texDesc.Format; - viewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - viewDesc.Texture2D.MipSlice = 0; - result = device->CreateRenderTargetView(m_targetTexture, &viewDesc, &m_renderView); - if (FAILED(result)) + targetDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + + shaderDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + shaderDesc.Texture2D.MipLevels = 1; + + for(int i = 0; i < _countof(m_targetTexture); ++i) { - DeInitialize(); - DEBUG_ERROR("Failed to create the render view"); - return false; + if (m_texFormats[i] == DXGI_FORMAT_UNKNOWN) + continue; + + texDesc .Format = m_texFormats[i]; + targetDesc.Format = m_texFormats[i]; + shaderDesc.Format = m_texFormats[i]; + + result = device->CreateTexture2D(&texDesc, NULL, &m_targetTexture[i]); + if (FAILED(result)) + { + DeInitialize(); + DEBUG_ERROR("Failed to create the render texture"); + return false; + } + + result = device->CreateRenderTargetView(m_targetTexture[i], &targetDesc, &m_renderView[i]); + if (FAILED(result)) + { + DeInitialize(); + DEBUG_ERROR("Failed to create the render view"); + return false; + } + + result = device->CreateShaderResourceView(m_targetTexture[i], &shaderDesc, &m_shaderView[i]); + if (FAILED(result)) + { + DeInitialize(); + DEBUG_ERROR("Failed to create the resource view"); + return false; + } } samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; @@ -242,14 +274,21 @@ void TextureConverter::DeInitialize() SafeRelease(&m_samplerState ); SafeRelease(&m_indexBuffer ); SafeRelease(&m_vertexBuffer ); - SafeRelease(&m_renderView ); - SafeRelease(&m_targetTexture); - SafeRelease(&m_vertexShader ); - SafeRelease(&m_pixelShader ); - SafeRelease(&m_layout ); + + for(int i = 0; i < _countof(m_targetTexture); ++i) + { + SafeRelease(&m_shaderView [i]); + SafeRelease(&m_renderView [i]); + SafeRelease(&m_targetTexture[i]); + } + + SafeRelease(&m_vertexShader); + SafeRelease(&m_psConversion); + SafeRelease(&m_layout ); + SafeRelease(&m_psCopy ); } -bool TextureConverter::Convert(ID3D11Texture2DPtr &texture) +bool TextureConverter::Convert(ID3D11Texture2DPtr texture, TextureList & output) { unsigned int stride; unsigned int offset; @@ -257,35 +296,46 @@ bool TextureConverter::Convert(ID3D11Texture2DPtr &texture) HRESULT result; D3D11_TEXTURE2D_DESC texDesc; - D3D11_SHADER_RESOURCE_VIEW_DESC shaderDesc; + D3D11_SHADER_RESOURCE_VIEW_DESC viewDesc; ID3D11ShaderResourceViewPtr textureView; texture->GetDesc(&texDesc); - shaderDesc.Format = texDesc.Format; - shaderDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - shaderDesc.Texture2D.MostDetailedMip = 0; - shaderDesc.Texture2D.MipLevels = 1; + viewDesc.Format = texDesc.Format; + viewDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + viewDesc.Texture2D.MostDetailedMip = 0; + viewDesc.Texture2D.MipLevels = 1; - result = m_device->CreateShaderResourceView(texture, &shaderDesc, &textureView); + result = m_device->CreateShaderResourceView(texture, &viewDesc, &textureView); if (FAILED(result)) { DeInitialize(); DEBUG_ERROR("Failed to create shader resource view"); return false; } - ID3D11Buffer *buffers [] = { m_vertexBuffer.GetInterfacePtr() }; - ID3D11RenderTargetView *renderViews [] = { m_renderView .GetInterfacePtr() }; ID3D11SamplerState *samplerStates[] = { m_samplerState.GetInterfacePtr() }; ID3D11ShaderResourceView *shaderViews [] = { textureView .GetInterfacePtr() }; D3D11_VIEWPORT viewPorts [] = { { - 0.0f, 0.0f, + 0.0f , 0.0f, (float)m_width, (float)m_height, - 0.0f, 1.0f + 0.0f , 1.0f } }; - m_deviceContext->OMSetRenderTargets(1, renderViews, NULL); - m_deviceContext->ClearRenderTargetView(m_renderView, color); + int targetCount = 0; + ID3D11RenderTargetView **renderViews = new ID3D11RenderTargetView*[_countof(m_renderView)]; + for(int i = 0; i < _countof(m_renderView); ++i) + { + if (m_texFormats[i] == DXGI_FORMAT_UNKNOWN) + continue; + + m_deviceContext->ClearRenderTargetView(m_renderView[i], color); + renderViews[i] = m_renderView[i].GetInterfacePtr(); + ++targetCount; + } + + m_deviceContext->PSSetShaderResources(0, _countof(shaderViews), shaderViews); + m_deviceContext->OMSetRenderTargets(targetCount, renderViews, NULL); + delete [] renderViews; stride = sizeof(VS_INPUT); offset = 0; @@ -296,14 +346,67 @@ bool TextureConverter::Convert(ID3D11Texture2DPtr &texture) m_deviceContext->IASetIndexBuffer (m_indexBuffer, DXGI_FORMAT_R32_UINT, 0); m_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP); m_deviceContext->VSSetShader (m_vertexShader, NULL, 0); + m_deviceContext->PSSetSamplers (0, _countof(samplerStates), samplerStates); - m_deviceContext->PSSetShaderResources (0, _countof(shaderViews ), shaderViews ); - m_deviceContext->PSSetShader (m_pixelShader , NULL, 0); + m_deviceContext->PSSetShader (m_psConversion, NULL, 0); m_deviceContext->DrawIndexed(m_indexCount, 0, 0); - SafeRelease(&textureView); - SafeRelease(&texture); - texture = m_targetTexture; + + D3D11_RENDER_TARGET_VIEW_DESC targetDesc; + ZeroMemory(&targetDesc, sizeof(targetDesc)); + targetDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + m_deviceContext->PSSetShader(m_psCopy, NULL, 0); + + renderViews = new ID3D11RenderTargetView*[1]; + for (int i = 0; i < _countof(m_renderView); ++i) + { + if (m_texFormats[i] == DXGI_FORMAT_UNKNOWN) + continue; + + ID3D11Texture2DPtr src = m_targetTexture[i]; + ID3D11Texture2DPtr dest; + ID3D11RenderTargetViewPtr view; + D3D11_TEXTURE2D_DESC srcDesc; + + src->GetDesc(&srcDesc); + srcDesc.Width *= m_scaleFormats[i]; + srcDesc.Height *= m_scaleFormats[i]; + viewPorts[0].Width = srcDesc.Width; + viewPorts[0].Height = srcDesc.Height; + + result = m_device->CreateTexture2D(&srcDesc, NULL, &dest); + if (FAILED(result)) + { + delete[] renderViews; + DeInitialize(); + DEBUG_ERROR("Failed to create the target texture"); + return false; + } + + targetDesc.Format = srcDesc.Format; + result = m_device->CreateRenderTargetView(dest, &targetDesc, &view); + if (FAILED(result)) + { + SafeRelease(&dest); + delete[] renderViews; + DeInitialize(); + DEBUG_ERROR("Failed to create the target view"); + return false; + } + + renderViews[0] = view.GetInterfacePtr(); + shaderViews[0] = m_shaderView[i].GetInterfacePtr(); + + m_deviceContext->OMSetRenderTargets(1, renderViews, NULL); + m_deviceContext->RSSetViewports(_countof(viewPorts), viewPorts); + m_deviceContext->PSSetShaderResources(0, 1, shaderViews); + m_deviceContext->DrawIndexed(m_indexCount, 0, 0); + + output.push_back(dest); + SafeRelease(&view); + } + + delete[] renderViews; return true; } diff --git a/host/TextureConverter.h b/host/TextureConverter.h index f3e3caa5..9559d1dd 100644 --- a/host/TextureConverter.h +++ b/host/TextureConverter.h @@ -20,8 +20,12 @@ Place, Suite 330, Boston, MA 02111-1307 USA #pragma once #include "Com.h" +#include "common\KVMFR.h" #include +#include + +typedef std::vector TextureList; class TextureConverter { @@ -34,12 +38,12 @@ public: ID3D11DevicePtr device, const unsigned int width, const unsigned int height, - DXGI_FORMAT format + FrameType format ); void DeInitialize(); - bool Convert(ID3D11Texture2DPtr &texture); + bool Convert(ID3D11Texture2DPtr texture, TextureList & output); private: struct VS_INPUT @@ -53,13 +57,19 @@ private: ID3D11DeviceContextPtr m_deviceContext; ID3D11DevicePtr m_device; unsigned int m_width, m_height; - DXGI_FORMAT m_format; + FrameType m_format; + + DXGI_FORMAT m_texFormats [3]; + float m_scaleFormats [3]; + + ID3D11Texture2DPtr m_targetTexture[3]; + ID3D11RenderTargetViewPtr m_renderView [3]; + ID3D11ShaderResourceViewPtr m_shaderView [3]; - ID3D11Texture2DPtr m_targetTexture; - ID3D11RenderTargetViewPtr m_renderView; ID3D11InputLayoutPtr m_layout; ID3D11VertexShaderPtr m_vertexShader; - ID3D11PixelShaderPtr m_pixelShader; + ID3D11PixelShaderPtr m_psCopy; + ID3D11PixelShaderPtr m_psConversion; ID3D11SamplerStatePtr m_samplerState; ID3D11BufferPtr m_vertexBuffer; diff --git a/host/looking-glass-host.vcxproj b/host/looking-glass-host.vcxproj index aa45f046..a0ee4e0f 100644 --- a/host/looking-glass-host.vcxproj +++ b/host/looking-glass-host.vcxproj @@ -359,11 +359,16 @@ - + + Pixel + g_Pixel + Shaders\Pixel.h + + HLSL Pixel - g_BGRAtoNV12 - Shaders\BGRAtoNV12.h + g_RGBtoYUV + Shaders\RGBtoYUV.h Vertex diff --git a/host/looking-glass-host.vcxproj.filters b/host/looking-glass-host.vcxproj.filters index e17a89fb..57470995 100644 --- a/host/looking-glass-host.vcxproj.filters +++ b/host/looking-glass-host.vcxproj.filters @@ -105,11 +105,12 @@ - - Source Files\Shaders - Source Files\Shaders + + Source Files\Shaders + + \ No newline at end of file