diff options
author | CrystalP <CrystalP@xbmc.org> | 2011-02-06 21:16:15 -0500 |
---|---|---|
committer | CrystalP <CrystalP@xbmc.org> | 2011-02-06 21:16:15 -0500 |
commit | ed71ae3bcd60088623ce8adb12be1507606f9c43 (patch) | |
tree | 05090a375aa888efc3d13c680aacccc205f672fa | |
parent | 6e2c48f4f4677ed7ae22aa2a8b0edaade9a80fee (diff) | |
parent | 40bdfa138fc76cd30f4eb7ba0a66da6493412252 (diff) |
Merge Windows renderer support for the NV12 and UVYV formats used natively by the CrystalHD cards.
-rw-r--r-- | system/shaders/yuv2rgb_d3d.fx | 54 | ||||
-rw-r--r-- | xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.cpp | 95 | ||||
-rw-r--r-- | xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.h | 5 | ||||
-rw-r--r-- | xbmc/cores/VideoRenderers/WinRenderer.cpp | 142 | ||||
-rw-r--r-- | xbmc/cores/VideoRenderers/WinRenderer.h | 15 | ||||
-rw-r--r-- | xbmc/guilib/D3DResource.h | 4 |
6 files changed, 244 insertions, 71 deletions
diff --git a/system/shaders/yuv2rgb_d3d.fx b/system/shaders/yuv2rgb_d3d.fx index 833bbadd43..610e12bd92 100644 --- a/system/shaders/yuv2rgb_d3d.fx +++ b/system/shaders/yuv2rgb_d3d.fx @@ -23,10 +23,7 @@ texture g_YTexture; texture g_UTexture; texture g_VTexture; float4x4 g_ColorMatrix; - -#ifdef SINGLEPASS - -// Color conversion + bilinear resize in one pass +float2 g_StepXY; sampler YSampler = sampler_state { @@ -37,21 +34,6 @@ sampler YSampler = MagFilter = LINEAR; }; -#else - -// Color conversion only - -sampler YSampler = - sampler_state { - Texture = <g_YTexture>; - AddressU = CLAMP; - AddressV = CLAMP; - MinFilter = POINT; - MagFilter = POINT; - }; - -#endif - sampler USampler = sampler_state { Texture = <g_UTexture>; @@ -87,10 +69,44 @@ struct PS_OUTPUT PS_OUTPUT YUV2RGB( VS_OUTPUT In) { PS_OUTPUT OUT; +#if defined(XBMC_YV12) float4 YUV = float4(tex2D (YSampler, In.TextureY).x , tex2D (USampler, In.TextureU).x , tex2D (VSampler, In.TextureV).x , 1.0); +#elif defined(XBMC_NV12) + float4 YUV = float4(tex2D (YSampler, In.TextureY).x + , tex2D (USampler, In.TextureU).ra + , 1.0); +#elif defined(XBMC_YUY2) || defined(XBMC_UYVY) + // The HLSL compiler is smart enough to optimize away these redundant assignments. + // That way the code is almost identical to the OGL shader. + float2 stepxy = g_StepXY; + float2 pos = In.TextureY; + pos = float2(pos.x - (stepxy.x * 0.25), pos.y); + float2 f = frac(pos / stepxy); + + //y axis will be correctly interpolated by opengl + //x axis will not, so we grab two pixels at the center of two columns and interpolate ourselves + float4 c1 = tex2D(YSampler, float2(pos.x + ((0.5 - f.x) * stepxy.x), pos.y)); + float4 c2 = tex2D(YSampler, float2(pos.x + ((1.5 - f.x) * stepxy.x), pos.y)); + + /* each pixel has two Y subpixels and one UV subpixel + YUV Y YUV + check if we're left or right of the middle Y subpixel and interpolate accordingly*/ + #if defined(XBMC_YUY2) // BGRA = YUYV + float leftY = lerp(c1.b, c1.r, f.x * 2.0); + float rightY = lerp(c1.r, c2.b, f.x * 2.0 - 1.0); + float2 outUV = lerp(c1.ga, c2.ga, f.x); + #elif defined(XBMC_UYVY) // BGRA = UYVY + float leftY = lerp(c1.g, c1.a, f.x * 2.0); + float rightY = lerp(c1.a, c2.g, f.x * 2.0 - 1.0); + float2 outUV = lerp(c1.br, c2.br, f.x); + #endif + float outY = lerp(leftY, rightY, step(0.5, f.x)); + float4 YUV = float4(outY, outUV, 1.0); +#endif + OUT.RGBColor = mul(YUV, g_ColorMatrix); OUT.RGBColor.a = 1.0; return OUT; diff --git a/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.cpp b/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.cpp index 5a29583e55..f5542fa42a 100644 --- a/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.cpp +++ b/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.cpp @@ -192,32 +192,77 @@ bool CWinShader::Execute() //================================================================================== -bool CYUV2RGBShader::Create(bool singlepass, unsigned int sourceWidth, unsigned int sourceHeight) +bool CYUV2RGBShader::Create(unsigned int sourceWidth, unsigned int sourceHeight, BufferFormat fmt) { ReleaseInternal(); CWinShader::CreateVertexBuffer(D3DFVF_XYZRHW | D3DFVF_TEX3, 4, sizeof(CUSTOMVERTEX), 2); + m_sourceWidth = sourceWidth; + m_sourceHeight = sourceHeight; + + unsigned int texWidth; + DefinesMap defines; - if (singlepass) - defines["SINGLEPASS"] = ""; - CStdString effectString = "special://xbmc/system/shaders/yuv2rgb_d3d.fx"; + if (fmt == YV12) + { + defines["XBMC_YV12"] = ""; + texWidth = sourceWidth; - if(!LoadEffect(effectString, &defines)) + if(!m_YUVPlanes[0].Create(texWidth , m_sourceHeight , 1, 0, D3DFMT_L8, D3DPOOL_DEFAULT) + || !m_YUVPlanes[1].Create(texWidth / 2, m_sourceHeight / 2, 1, 0, D3DFMT_L8, D3DPOOL_DEFAULT) + || !m_YUVPlanes[2].Create(texWidth / 2, m_sourceHeight / 2, 1, 0, D3DFMT_L8, D3DPOOL_DEFAULT)) + { + CLog::Log(LOGERROR, __FUNCTION__": Failed to create YV12 planes."); + return false; + } + } + else if (fmt == NV12) { - CLog::Log(LOGERROR, __FUNCTION__": Failed to load shader %s.", effectString.c_str()); - return false; + defines["XBMC_NV12"] = ""; + texWidth = sourceWidth; + + if(!m_YUVPlanes[0].Create(texWidth , m_sourceHeight , 1, 0, D3DFMT_L8, D3DPOOL_DEFAULT) + || !m_YUVPlanes[1].Create(texWidth / 2, m_sourceHeight / 2, 1, 0, D3DFMT_A8L8, D3DPOOL_DEFAULT)) + { + CLog::Log(LOGERROR, __FUNCTION__": Failed to create NV12 planes."); + return false; + } } + else if (fmt == YUY2) + { + defines["XBMC_YUY2"] = ""; + texWidth = sourceWidth >> 1; - m_sourceWidth = sourceWidth; - m_sourceHeight = sourceHeight; + if(!m_YUVPlanes[0].Create(texWidth , m_sourceHeight , 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT)) + { + CLog::Log(LOGERROR, __FUNCTION__": Failed to create YUY2 planes."); + return false; + } + } + else if (fmt == UYVY) + { + defines["XBMC_UYVY"] = ""; + texWidth = sourceWidth >> 1; + + if(!m_YUVPlanes[0].Create(texWidth , m_sourceHeight , 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT)) + { + CLog::Log(LOGERROR, __FUNCTION__": Failed to create UYVY planes."); + return false; + } + } + else + return false; + + m_texSteps[0] = 1.0f/(float)texWidth; + m_texSteps[1] = 1.0f/(float)sourceHeight; - if(!m_YUVPlanes[0].Create(m_sourceWidth , m_sourceHeight , 1, 0, D3DFMT_L8, D3DPOOL_DEFAULT) - || !m_YUVPlanes[1].Create(m_sourceWidth / 2, m_sourceHeight / 2, 1, 0, D3DFMT_L8, D3DPOOL_DEFAULT) - || !m_YUVPlanes[2].Create(m_sourceWidth / 2, m_sourceHeight / 2, 1, 0, D3DFMT_L8, D3DPOOL_DEFAULT)) + CStdString effectString = "special://xbmc/system/shaders/yuv2rgb_d3d.fx"; + + if(!LoadEffect(effectString, &defines)) { - CLog::Log(LOGERROR, __FUNCTION__": Failed to create YUV planes."); + CLog::Log(LOGERROR, __FUNCTION__": Failed to load shader %s.", effectString.c_str()); return false; } @@ -233,7 +278,7 @@ void CYUV2RGBShader::Render(CRect sourceRect, CRect destRect, PrepareParameters(sourceRect, destRect, contrast, brightness, flags); UploadToGPU(YUVbuf); - SetShaderParameters(); + SetShaderParameters(YUVbuf); Execute(); } @@ -299,13 +344,16 @@ void CYUV2RGBShader::PrepareParameters(CRect sourceRect, flags); } -void CYUV2RGBShader::SetShaderParameters() +void CYUV2RGBShader::SetShaderParameters(YUVBuffer* YUVbuf) { - m_effect.SetMatrix( "g_ColorMatrix", m_matrix.Matrix()); - m_effect.SetTechnique( "YUV2RGB_T" ); - m_effect.SetTexture( "g_YTexture", m_YUVPlanes[0] ) ; - m_effect.SetTexture( "g_UTexture", m_YUVPlanes[1] ) ; - m_effect.SetTexture( "g_VTexture", m_YUVPlanes[2] ) ; + m_effect.SetMatrix("g_ColorMatrix", m_matrix.Matrix()); + m_effect.SetTechnique("YUV2RGB_T"); + m_effect.SetTexture("g_YTexture", m_YUVPlanes[0]); + if (YUVbuf->GetActivePlanes() > 1) + m_effect.SetTexture("g_UTexture", m_YUVPlanes[1]); + if (YUVbuf->GetActivePlanes() > 2) + m_effect.SetTexture("g_VTexture", m_YUVPlanes[2]); + m_effect.SetFloatArray("g_StepXY", m_texSteps, sizeof(m_texSteps)/sizeof(m_texSteps[0])); } void CYUV2RGBShader::ReleaseInternal() @@ -319,19 +367,18 @@ void CYUV2RGBShader::ReleaseInternal() bool CYUV2RGBShader::UploadToGPU(YUVBuffer* YUVbuf) { - const RECT rect = { 0, 0, m_sourceWidth, m_sourceHeight }; - const RECT recthalf = { 0, 0, m_sourceWidth / 2, m_sourceHeight / 2}; const POINT point = { 0, 0 }; - for (int i = 0; i<3; i++) + for (unsigned int i = 0; i<YUVbuf->GetActivePlanes(); i++) { + const RECT rect = { 0, 0, YUVbuf->planes[i].texture.GetWidth(), YUVbuf->planes[i].texture.GetHeight() }; IDirect3DSurface9 *src, *dest; if(FAILED(YUVbuf->planes[i].texture.Get()->GetSurfaceLevel(0, &src))) CLog::Log(LOGERROR, __FUNCTION__": Failed to retrieve level 0 surface for source YUV plane %d", i); if (FAILED(m_YUVPlanes[i].Get()->GetSurfaceLevel(0, &dest))) CLog::Log(LOGERROR, __FUNCTION__": Failed to retrieve level 0 surface for destination YUV plane %d", i); - if (FAILED(g_Windowing.Get3DDevice()->UpdateSurface(src, i == 0 ? &rect : &recthalf, dest, &point))) + if (FAILED(g_Windowing.Get3DDevice()->UpdateSurface(src, &rect, dest, &point))) { CLog::Log(LOGERROR, __FUNCTION__": Failed to copy plane %d from sysmem to vidmem.", i); src->Release(); diff --git a/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.h b/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.h index d74fad4bbb..046acba481 100644 --- a/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.h +++ b/xbmc/cores/VideoRenderers/VideoShaders/WinVideoFilter.h @@ -76,7 +76,7 @@ private: class CYUV2RGBShader : public CWinShader { public: - virtual bool Create(bool singlepass, unsigned int sourceWidth, unsigned int sourceHeight); + virtual bool Create(unsigned int sourceWidth, unsigned int sourceHeight, BufferFormat fmt); virtual void Render(CRect sourceRect, CRect destRect, float contrast, @@ -90,7 +90,7 @@ protected: float contrast, float brightness, unsigned int flags); - virtual void SetShaderParameters(); + virtual void SetShaderParameters(YUVBuffer* YUVbuf); virtual void ReleaseInternal(); virtual bool UploadToGPU(YUVBuffer* YUVbuf); @@ -99,6 +99,7 @@ private: unsigned int m_sourceWidth, m_sourceHeight; CRect m_sourceRect, m_destRect; CD3DTexture m_YUVPlanes[3]; + float m_texSteps[2]; struct CUSTOMVERTEX { FLOAT x, y, z; diff --git a/xbmc/cores/VideoRenderers/WinRenderer.cpp b/xbmc/cores/VideoRenderers/WinRenderer.cpp index 104d283437..356ac4b668 100644 --- a/xbmc/cores/VideoRenderers/WinRenderer.cpp +++ b/xbmc/cores/VideoRenderers/WinRenderer.cpp @@ -87,6 +87,24 @@ CWinRenderer::~CWinRenderer() UnInit(); } +static BufferFormat BufferFormatFromFlags(unsigned int flags) +{ + if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_YV12) return YV12; + else if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_NV12) return NV12; + else if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_YUY2) return YUY2; + else if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_UYVY) return UYVY; + else return Invalid; +} + +static enum PixelFormat PixelFormatFromFlags(unsigned int flags) +{ + if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_YV12) return PIX_FMT_YUV420P; + else if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_NV12) return PIX_FMT_NV12; + else if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_UYVY) return PIX_FMT_UYVY422; + else if (CONF_FLAGS_FORMAT_MASK(flags) == CONF_FLAGS_FORMAT_YUY2) return PIX_FMT_YUYV422; + else return PIX_FMT_NONE; +} + void CWinRenderer::ManageTextures() { int neededbuffers = 2; @@ -549,11 +567,14 @@ void CWinRenderer::UpdatePSVideoFilter() SAFE_RELEASE(m_colorShader) + BufferFormat format = BufferFormatFromFlags(m_flags); + if (m_bUseHQScaler) { m_colorShader = new CYUV2RGBShader(); - if (!m_colorShader->Create(false, m_sourceWidth, m_sourceHeight)) + if (!m_colorShader->Create(m_sourceWidth, m_sourceHeight, format)) { + // Try again after disabling the HQ scaler and freeing its resources m_IntermediateTarget.Release(); SAFE_RELEASE(m_scalerShader) SAFE_RELEASE(m_colorShader); @@ -564,7 +585,7 @@ void CWinRenderer::UpdatePSVideoFilter() if (!m_bUseHQScaler) //fallback from HQ scalers and multipass creation above { m_colorShader = new CYUV2RGBShader(); - if (!m_colorShader->Create(true, m_sourceWidth, m_sourceHeight)) + if (!m_colorShader->Create(m_sourceWidth, m_sourceHeight, format)) SAFE_RELEASE(m_colorShader); // we're in big trouble - should fallback on D3D accelerated or sw method } @@ -674,35 +695,43 @@ void CWinRenderer::Render(DWORD flags) void CWinRenderer::RenderSW() { + enum PixelFormat format = PixelFormatFromFlags(m_flags); + // 1. convert yuv to rgb m_sw_scale_ctx = m_dllSwScale->sws_getCachedContext(m_sw_scale_ctx, - m_sourceWidth, m_sourceHeight, PIX_FMT_YUV420P, + m_sourceWidth, m_sourceHeight, format, m_sourceWidth, m_sourceHeight, PIX_FMT_BGRA, SWS_FAST_BILINEAR | SwScaleCPUFlags(), NULL, NULL, NULL); YUVBuffer* buf = (YUVBuffer*)m_VideoBuffers[m_iYV12RenderBuffer]; - D3DLOCKED_RECT srclr[3]; - if(!(buf->planes[0].texture.LockRect(0, &srclr[0], NULL, D3DLOCK_READONLY)) - || !(buf->planes[1].texture.LockRect(0, &srclr[1], NULL, D3DLOCK_READONLY)) - || !(buf->planes[2].texture.LockRect(0, &srclr[2], NULL, D3DLOCK_READONLY))) - CLog::Log(LOGERROR, __FUNCTION__" - failed to lock yuv textures into memory"); + D3DLOCKED_RECT srclr[MAX_PLANES]; + uint8_t *src[MAX_PLANES]; + int srcStride[MAX_PLANES]; + + for (unsigned int idx = 0; idx < buf->GetActivePlanes(); idx++) + { + if(!(buf->planes[idx].texture.LockRect(0, &srclr[idx], NULL, D3DLOCK_READONLY))) + CLog::Log(LOGERROR, __FUNCTION__" - failed to lock yuv textures into memory"); + else + { + src[idx] = (uint8_t*)srclr[idx].pBits; + srcStride[idx] = srclr[idx].Pitch; + } + } D3DLOCKED_RECT destlr = {0,0}; if (!m_SWTarget.LockRect(0, &destlr, NULL, D3DLOCK_DISCARD)) CLog::Log(LOGERROR, __FUNCTION__" - failed to lock swtarget texture into memory"); - uint8_t *src[] = { (uint8_t*)srclr[0].pBits, (uint8_t*)srclr[1].pBits, (uint8_t*)srclr[2].pBits, 0 }; - int srcStride[] = { srclr[0].Pitch, srclr[1].Pitch, srclr[2].Pitch, 0 }; uint8_t *dst[] = { (uint8_t*) destlr.pBits, 0, 0, 0 }; int dstStride[] = { destlr.Pitch, 0, 0, 0 }; m_dllSwScale->sws_scale(m_sw_scale_ctx, src, srcStride, 0, m_sourceHeight, dst, dstStride); - if(!(buf->planes[0].texture.UnlockRect(0)) - || !(buf->planes[1].texture.UnlockRect(0)) - || !(buf->planes[2].texture.UnlockRect(0))) - CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock yuv textures"); + for (unsigned int idx = 0; idx < buf->GetActivePlanes(); idx++) + if(!(buf->planes[idx].texture.UnlockRect(0))) + CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock yuv textures"); if (!m_SWTarget.UnlockRect(0)) CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock swtarget texture"); @@ -990,7 +1019,9 @@ bool CWinRenderer::CreateYV12Texture(int index) { YUVBuffer *buf = new YUVBuffer(); - if (!buf->Create(m_sourceWidth, m_sourceHeight)) + BufferFormat format = BufferFormatFromFlags(m_flags); + + if (!buf->Create(format, m_sourceWidth, m_sourceHeight)) { CLog::Log(LOGERROR, __FUNCTION__" - Unable to create YV12 video texture %i", index); return false; @@ -1085,8 +1116,9 @@ YUVBuffer::~YUVBuffer() Release(); } -bool YUVBuffer::Create(unsigned int width, unsigned int height) +bool YUVBuffer::Create(BufferFormat format, unsigned int width, unsigned int height) { + m_format = format; m_width = width; m_height = height; @@ -1095,17 +1127,50 @@ bool YUVBuffer::Create(unsigned int width, unsigned int height) // - Dynamic + D3DPOOL_DEFAULT caused trouble for Intel i3 and some IGP. Bad sync/locking in the driver I suppose // and Present failed every second time for the second video played. // - this is what D3D9 does behind the scenes anyway - if ( !planes[PLANE_Y].texture.Create(m_width , m_height , 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM) - || !planes[PLANE_U].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM) - || !planes[PLANE_V].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM)) + switch(m_format) + { + case YV12: + { + if ( !planes[PLANE_Y].texture.Create(m_width , m_height , 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM) + || !planes[PLANE_U].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM) + || !planes[PLANE_V].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM)) + return false; + m_activeplanes = 3; + break; + } + case NV12: + { + if ( !planes[PLANE_Y].texture.Create(m_width , m_height , 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM) + || !planes[PLANE_UV].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_A8L8, D3DPOOL_SYSTEMMEM)) + return false; + m_activeplanes = 2; + break; + } + case YUY2: + { + if ( !planes[PLANE_Y].texture.Create(m_width >> 1 , m_height , 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM)) + return false; + m_activeplanes = 1; + break; + } + case UYVY: + { + if ( !planes[PLANE_Y].texture.Create(m_width >> 1 , m_height , 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM)) + return false; + m_activeplanes = 1; + break; + } + default: + m_activeplanes = 0; return false; + } return true; } void YUVBuffer::Release() { - for(unsigned i = 0; i < MAX_PLANES; i++) + for(unsigned i = 0; i < m_activeplanes; i++) { planes[i].texture.Release(); memset(&planes[i].rect, 0, sizeof(planes[i].rect)); @@ -1114,7 +1179,7 @@ void YUVBuffer::Release() void YUVBuffer::StartRender() { - for(unsigned i = 0; i < MAX_PLANES; i++) + for(unsigned i = 0; i < m_activeplanes; i++) { if(planes[i].texture.Get() && planes[i].rect.pBits) if (!planes[i].texture.UnlockRect(0)) @@ -1125,7 +1190,7 @@ void YUVBuffer::StartRender() void YUVBuffer::StartDecode() { - for(unsigned i = 0; i < MAX_PLANES; i++) + for(unsigned i = 0; i < m_activeplanes; i++) { if(planes[i].texture.Get() && planes[i].texture.LockRect(0, &planes[i].rect, NULL, D3DLOCK_DISCARD) == false) @@ -1138,9 +1203,36 @@ void YUVBuffer::StartDecode() void YUVBuffer::Clear() { - memset(planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height); - memset(planes[PLANE_U].rect.pBits, 128, planes[PLANE_U].rect.Pitch * (m_height/2)); - memset(planes[PLANE_V].rect.pBits, 128, planes[PLANE_V].rect.Pitch * (m_height/2)); + // Set Y to 0 and U,V to 128 (RGB 0,0,0) to avoid visual artifacts at the start of playback + + switch(m_format) + { + case YV12: + { + memset(planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height); + memset(planes[PLANE_U].rect.pBits, 128, planes[PLANE_U].rect.Pitch * (m_height/2)); + memset(planes[PLANE_V].rect.pBits, 128, planes[PLANE_V].rect.Pitch * (m_height/2)); + break; + } + case NV12: + { + memset(planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height); + memset(planes[PLANE_UV].rect.pBits, 128, planes[PLANE_U].rect.Pitch * (m_height/2)); + break; + } + // YUY2, UYVY: wmemset to set a 16bit pattern, byte-swapped because x86 is LE + case YUY2: + { + wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0x8000, planes[PLANE_Y].rect.Pitch / 2 * m_height); + break; + } + case UYVY: + { + wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0x0080, planes[PLANE_Y].rect.Pitch / 2 * m_height); + break; + } + + } } //================================== diff --git a/xbmc/cores/VideoRenderers/WinRenderer.h b/xbmc/cores/VideoRenderers/WinRenderer.h index 28c2f15a1d..7ea068e2f5 100644 --- a/xbmc/cores/VideoRenderers/WinRenderer.h +++ b/xbmc/cores/VideoRenderers/WinRenderer.h @@ -115,11 +115,21 @@ enum RenderMethod #define PLANE_Y 0 #define PLANE_U 1 #define PLANE_V 2 +#define PLANE_UV 1 #define FIELD_FULL 0 #define FIELD_TOP 1 #define FIELD_BOT 2 +enum BufferFormat +{ + Invalid, + YV12, + NV12, + YUY2, + UYVY +}; + struct SVideoBuffer { virtual ~SVideoBuffer() {} @@ -139,17 +149,20 @@ struct SVideoPlane struct YUVBuffer : SVideoBuffer { ~YUVBuffer(); - bool Create(unsigned int width, unsigned int height); + bool Create(BufferFormat format, unsigned int width, unsigned int height); virtual void Release(); virtual void StartDecode(); virtual void StartRender(); virtual void Clear(); + unsigned int GetActivePlanes() { return m_activeplanes; } SVideoPlane planes[MAX_PLANES]; private: unsigned int m_width; unsigned int m_height; + BufferFormat m_format; + unsigned int m_activeplanes; }; struct DXVABuffer : SVideoBuffer diff --git a/xbmc/guilib/D3DResource.h b/xbmc/guilib/D3DResource.h index 7da5287c48..828f45eda9 100644 --- a/xbmc/guilib/D3DResource.h +++ b/xbmc/guilib/D3DResource.h @@ -49,13 +49,17 @@ public: bool GetLevelDesc(UINT level, D3DSURFACE_DESC *desc); bool GetSurfaceLevel(UINT level, LPDIRECT3DSURFACE9 *surface); + // Accessors LPDIRECT3DTEXTURE9 Get() const { return m_texture; }; + UINT GetWidth() { return m_width; } + UINT GetHeight() { return m_height; } virtual void OnDestroyDevice(); virtual void OnCreateDevice(); virtual void OnLostDevice(); virtual void OnResetDevice(); + private: unsigned int GetMemoryUsage(unsigned int pitch) const; |