2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
23 #include "DllSwScale.h"
25 #include "WinRenderer.h"
26 #include "cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h"
27 #include "dialogs/GUIDialogKaiToast.h"
28 #include "filesystem/File.h"
29 #include "guilib/LocalizeStrings.h"
30 #include "guilib/Texture.h"
31 #include "settings/AdvancedSettings.h"
32 #include "settings/DisplaySettings.h"
33 #include "settings/MediaSettings.h"
34 #include "settings/Settings.h"
35 #include "threads/SingleLock.h"
36 #include "utils/log.h"
37 #include "utils/MathUtils.h"
38 #include "utils/SystemInfo.h"
39 #include "VideoShaders/WinVideoFilter.h"
40 #include "win32/WIN32Util.h"
41 #include "windowing/WindowingFactory.h"
48 static RenderMethodDetail RenderMethodDetails[] = {
49 { RENDER_SW , "Software" },
50 { RENDER_PS , "Pixel Shaders" },
51 { RENDER_DXVA , "DXVA" },
52 { RENDER_INVALID, NULL }
55 static RenderMethodDetail *FindRenderMethod(RenderMethod m)
57 for (unsigned i = 0; RenderMethodDetails[i].method != RENDER_INVALID; i++) {
58 if (RenderMethodDetails[i].method == m)
59 return &RenderMethodDetails[i];
64 CWinRenderer::CWinRenderer()
66 m_iYV12RenderBuffer = 0;
70 m_scalerShader = NULL;
71 m_extended_format = 0;
73 m_iRequestedMethod = RENDER_METHOD_AUTO;
75 m_renderMethod = RENDER_PS;
76 m_scalingMethod = VS_SCALINGMETHOD_LINEAR;
77 m_scalingMethodGui = (ESCALINGMETHOD)-1;
78 m_TextureFilter = D3DTEXF_POINT;
80 m_bUseHQScaler = false;
81 m_bFilterInitialized = false;
83 for (int i = 0; i<NUM_BUFFERS; i++)
84 m_VideoBuffers[i] = NULL;
86 m_sw_scale_ctx = NULL;
92 m_bConfigured = false;
94 m_format = RENDER_FMT_NONE;
99 CWinRenderer::~CWinRenderer()
104 static enum PixelFormat PixelFormatFromFormat(ERenderFormat format)
106 if (format == RENDER_FMT_YUV420P) return PIX_FMT_YUV420P;
107 else if (format == RENDER_FMT_YUV420P10) return PIX_FMT_YUV420P10;
108 else if (format == RENDER_FMT_YUV420P16) return PIX_FMT_YUV420P16;
109 else if (format == RENDER_FMT_NV12) return PIX_FMT_NV12;
110 else if (format == RENDER_FMT_UYVY422) return PIX_FMT_UYVY422;
111 else if (format == RENDER_FMT_YUYV422) return PIX_FMT_YUYV422;
112 else return PIX_FMT_NONE;
115 void CWinRenderer::ManageTextures()
117 if( m_NumYV12Buffers < m_neededBuffers )
119 for(int i = m_NumYV12Buffers; i<m_neededBuffers;i++)
120 CreateYV12Texture(i);
122 m_NumYV12Buffers = m_neededBuffers;
124 else if( m_NumYV12Buffers > m_neededBuffers )
126 m_NumYV12Buffers = m_neededBuffers;
127 m_iYV12RenderBuffer = m_iYV12RenderBuffer % m_NumYV12Buffers;
129 for(int i = m_NumYV12Buffers-1; i>=m_neededBuffers;i--)
130 DeleteYV12Texture(i);
134 void CWinRenderer::SelectRenderMethod()
136 // Set rendering to dxva before trying it, in order to open the correct processor immediately, when deinterlacing method is auto.
138 // Force dxva renderer after dxva decoding: PS and SW renderers have performance issues after dxva decode.
139 if (g_advancedSettings.m_DXVAForceProcessorRenderer && m_format == RENDER_FMT_DXVA)
141 CLog::Log(LOGNOTICE, "D3D: rendering method forced to DXVA processor");
142 m_renderMethod = RENDER_DXVA;
143 if (!m_processor->Open(m_sourceWidth, m_sourceHeight, m_iFlags, m_format, m_extended_format))
145 CLog::Log(LOGNOTICE, "D3D: unable to open DXVA processor");
146 m_processor->Close();
147 m_renderMethod = RENDER_INVALID;
152 CLog::Log(LOGDEBUG, __FUNCTION__": Requested render method: %d", m_iRequestedMethod);
154 switch(m_iRequestedMethod)
156 case RENDER_METHOD_DXVAHD:
157 case RENDER_METHOD_DXVA:
158 m_renderMethod = RENDER_DXVA;
159 if (m_processor->Open(m_sourceWidth, m_sourceHeight, m_iFlags, m_format, m_extended_format))
163 CLog::Log(LOGNOTICE, "D3D: unable to open DXVA processor");
164 m_processor->Close();
166 // Drop through to pixel shader
167 case RENDER_METHOD_AUTO:
168 case RENDER_METHOD_D3D_PS:
169 // Try the pixel shaders support
170 if (m_deviceCaps.PixelShaderVersion >= D3DPS_VERSION(2, 0))
175 m_renderMethod = RENDER_PS;
180 CLog::Log(LOGNOTICE, "D3D: unable to load test shader - D3D installation is most likely incomplete");
181 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, "DirectX", g_localizeStrings.Get(2101));
186 CLog::Log(LOGNOTICE, "D3D: graphics adapter does not support Pixel Shaders 2.0");
188 CLog::Log(LOGNOTICE, "D3D: falling back to SW mode");
189 // drop through to software
190 case RENDER_METHOD_SOFTWARE:
192 // So we'll do the color conversion in software.
193 m_renderMethod = RENDER_SW;
198 RenderMethodDetail *rmdet = FindRenderMethod(m_renderMethod);
199 CLog::Log(LOGDEBUG, __FUNCTION__": Selected render method %d: %s", m_renderMethod, rmdet != NULL ? rmdet->name : "unknown");
202 bool CWinRenderer::UpdateRenderMethod()
204 if (m_SWTarget.Get())
205 m_SWTarget.Release();
207 if (m_renderMethod == RENDER_SW)
209 m_dllSwScale = new DllSwScale();
211 if (!m_dllSwScale->Load())
212 CLog::Log(LOGERROR,"CDVDDemuxFFmpeg::Open - failed to load ffmpeg libraries");
214 if(!m_SWTarget.Create(m_sourceWidth, m_sourceHeight, 1, D3DUSAGE_DYNAMIC, D3DFMT_X8R8G8B8, D3DPOOL_DEFAULT))
216 CLog::Log(LOGNOTICE, __FUNCTION__": Failed to create sw render target.");
223 bool CWinRenderer::Configure(unsigned int width, unsigned int height, unsigned int d_width, unsigned int d_height, float fps, unsigned flags, ERenderFormat format, unsigned extended_format, unsigned int orientation)
225 if(m_sourceWidth != width
226 || m_sourceHeight != height)
228 m_sourceWidth = width;
229 m_sourceHeight = height;
230 // need to recreate textures
231 m_NumYV12Buffers = 0;
232 m_iYV12RenderBuffer = 0;
233 // reinitialize the filters/shaders
234 m_bFilterInitialized = false;
238 if (m_VideoBuffers[m_iYV12RenderBuffer] != NULL)
239 m_VideoBuffers[m_iYV12RenderBuffer]->StartDecode();
241 m_iYV12RenderBuffer = 0;
242 if (m_VideoBuffers[0] != NULL)
243 m_VideoBuffers[0]->StartRender();
249 m_extended_format = extended_format;
251 // calculate the input frame aspect ratio
252 CalculateFrameAspectRatio(d_width, d_height);
253 ChooseBestResolution(fps);
254 m_destWidth = g_graphicsContext.GetResInfo(m_resolution).iWidth;
255 m_destHeight = g_graphicsContext.GetResInfo(m_resolution).iHeight;
256 SetViewMode(CMediaSettings::Get().GetCurrentVideoSettings().m_ViewMode);
259 m_bConfigured = true;
261 SelectRenderMethod();
262 UpdateRenderMethod();
267 int CWinRenderer::NextYV12Texture()
270 return (m_iYV12RenderBuffer + 1) % m_NumYV12Buffers;
275 bool CWinRenderer::AddVideoPicture(DVDVideoPicture* picture, int index)
277 if (m_renderMethod == RENDER_DXVA)
280 if(source < 0 || NextYV12Texture() < 0)
283 DXVABuffer *buf = (DXVABuffer*)m_VideoBuffers[source];
284 buf->id = m_processor->Add(picture);
290 int CWinRenderer::GetImage(YV12Image *image, int source, bool readonly)
292 /* take next available buffer */
293 if( source == AUTOSOURCE )
294 source = NextYV12Texture();
296 if( source < 0 || NextYV12Texture() < 0)
299 YUVBuffer *buf = (YUVBuffer*)m_VideoBuffers[source];
303 image->height = m_sourceHeight;
304 image->width = m_sourceWidth;
306 if(m_format == RENDER_FMT_YUV420P10
307 || m_format == RENDER_FMT_YUV420P16)
314 image->stride[i] = buf->planes[i].rect.Pitch;
315 image->plane[i] = (BYTE*)buf->planes[i].rect.pBits;
321 void CWinRenderer::ReleaseImage(int source, bool preserve)
323 // no need to release anything here since we're using system memory
326 void CWinRenderer::Reset()
330 void CWinRenderer::Update()
332 if (!m_bConfigured) return;
336 void CWinRenderer::RenderUpdate(bool clear, DWORD flags, DWORD alpha)
338 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
341 g_graphicsContext.Clear(m_clearColour);
344 pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
346 pD3DDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
348 if (!m_bConfigured) return;
351 CSingleLock lock(g_graphicsContext);
358 void CWinRenderer::FlipPage(int source)
360 if(source == AUTOSOURCE)
361 source = NextYV12Texture();
363 if (m_VideoBuffers[m_iYV12RenderBuffer] != NULL)
364 m_VideoBuffers[m_iYV12RenderBuffer]->StartDecode();
366 if( source >= 0 && source < m_NumYV12Buffers )
367 m_iYV12RenderBuffer = source;
369 m_iYV12RenderBuffer = 0;
371 if (m_VideoBuffers[m_iYV12RenderBuffer] != NULL)
372 m_VideoBuffers[m_iYV12RenderBuffer]->StartRender();
374 #ifdef MP_DIRECTRENDERING
381 unsigned int CWinRenderer::PreInit()
383 CSingleLock lock(g_graphicsContext);
384 m_bConfigured = false;
386 m_resolution = CDisplaySettings::Get().GetCurrentResolution();
387 if ( m_resolution == RES_WINDOW )
388 m_resolution = RES_DESKTOP;
390 // setup the background colour
391 m_clearColour = (g_advancedSettings.m_videoBlackBarColour & 0xff) * 0x010101;
393 g_Windowing.Get3DDevice()->GetDeviceCaps(&m_deviceCaps);
396 m_formats.push_back(RENDER_FMT_YUV420P);
398 m_iRequestedMethod = CSettings::Get().GetInt("videoplayer.rendermethod");
400 if (g_advancedSettings.m_DXVAForceProcessorRenderer || m_iRequestedMethod == RENDER_METHOD_DXVA
401 || m_iRequestedMethod == RENDER_METHOD_DXVAHD)
403 if (m_iRequestedMethod != RENDER_METHOD_DXVA && CSysInfo::IsWindowsVersionAtLeast(CSysInfo::WindowsVersionWin7))
405 m_processor = new DXVA::CProcessorHD();
406 if (!m_processor->PreInit())
408 CLog::Log(LOGNOTICE, "CWinRenderer::Preinit - could not init DXVA-HD processor - skipping");
409 SAFE_DELETE(m_processor);
410 m_processor = new DXVA::CProcessor();
416 m_processor = new DXVA::CProcessor();
418 if (!m_processor->PreInit())
419 CLog::Log(LOGNOTICE, "CWinRenderer::Preinit - could not init DXVA2 processor - skipping");
424 if (g_Windowing.IsTextureFormatOk(D3DFMT_L16, 0))
426 m_formats.push_back(RENDER_FMT_YUV420P10);
427 m_formats.push_back(RENDER_FMT_YUV420P16);
429 m_formats.push_back(RENDER_FMT_NV12);
430 m_formats.push_back(RENDER_FMT_YUYV422);
431 m_formats.push_back(RENDER_FMT_UYVY422);
436 void CWinRenderer::UnInit()
438 CSingleLock lock(g_graphicsContext);
440 if (m_SWTarget.Get())
441 m_SWTarget.Release();
443 if (m_IntermediateTarget.Get())
444 m_IntermediateTarget.Release();
446 SAFE_DELETE(m_colorShader);
447 SAFE_DELETE(m_scalerShader);
449 m_bConfigured = false;
450 m_bFilterInitialized = false;
452 for(int i = 0; i < NUM_BUFFERS; i++)
453 DeleteYV12Texture(i);
455 m_NumYV12Buffers = 0;
459 m_dllSwScale->sws_freeContext(m_sw_scale_ctx);
460 m_sw_scale_ctx = NULL;
462 SAFE_DELETE(m_dllSwScale);
466 m_processor->UnInit();
467 SAFE_DELETE(m_processor);
471 bool CWinRenderer::CreateIntermediateRenderTarget(unsigned int width, unsigned int height)
473 // Initialize a render target for intermediate rendering
474 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
475 D3DFORMAT format = D3DFMT_X8R8G8B8;
476 DWORD usage = D3DUSAGE_RENDERTARGET;
478 if (m_renderMethod == RENDER_DXVA) format = D3DFMT_X8R8G8B8;
479 else if (g_Windowing.IsTextureFormatOk(D3DFMT_A2R10G10B10, usage)) format = D3DFMT_A2R10G10B10;
480 else if (g_Windowing.IsTextureFormatOk(D3DFMT_A2B10G10R10, usage)) format = D3DFMT_A2B10G10R10;
481 else if (g_Windowing.IsTextureFormatOk(D3DFMT_A8R8G8B8, usage)) format = D3DFMT_A8R8G8B8;
482 else if (g_Windowing.IsTextureFormatOk(D3DFMT_A8B8G8R8, usage)) format = D3DFMT_A8B8G8R8;
483 else if (g_Windowing.IsTextureFormatOk(D3DFMT_X8R8G8B8, usage)) format = D3DFMT_X8R8G8B8;
484 else if (g_Windowing.IsTextureFormatOk(D3DFMT_X8B8G8R8, usage)) format = D3DFMT_X8B8G8R8;
485 else if (g_Windowing.IsTextureFormatOk(D3DFMT_R8G8B8, usage)) format = D3DFMT_R8G8B8;
487 // don't create new one if it exists with requested size and format
488 if ( m_IntermediateTarget.Get() && m_IntermediateTarget.GetFormat() == format
489 && m_IntermediateTarget.GetWidth() == width && m_IntermediateTarget.GetHeight() == height)
492 if (m_IntermediateTarget.Get())
493 m_IntermediateTarget.Release();
495 CLog::Log(LOGDEBUG, __FUNCTION__": format %i", format);
497 if(!m_IntermediateTarget.Create(width, height, 1, usage, format, D3DPOOL_DEFAULT))
499 CLog::Log(LOGERROR, __FUNCTION__": intermediate render target creation failed.", format);
505 void CWinRenderer::SelectSWVideoFilter()
507 switch (m_scalingMethod)
509 case VS_SCALINGMETHOD_AUTO:
510 case VS_SCALINGMETHOD_LINEAR:
511 if (Supports(VS_SCALINGMETHOD_LINEAR))
513 m_TextureFilter = D3DTEXF_LINEAR;
516 // fall through for fallback
517 case VS_SCALINGMETHOD_NEAREST:
519 m_TextureFilter = D3DTEXF_POINT;
524 void CWinRenderer::SelectPSVideoFilter()
526 m_bUseHQScaler = false;
528 switch (m_scalingMethod)
530 case VS_SCALINGMETHOD_NEAREST:
531 case VS_SCALINGMETHOD_LINEAR:
534 case VS_SCALINGMETHOD_CUBIC:
535 case VS_SCALINGMETHOD_LANCZOS2:
536 case VS_SCALINGMETHOD_SPLINE36_FAST:
537 case VS_SCALINGMETHOD_LANCZOS3_FAST:
538 m_bUseHQScaler = true;
541 case VS_SCALINGMETHOD_SPLINE36:
542 case VS_SCALINGMETHOD_LANCZOS3:
543 m_bUseHQScaler = true;
546 case VS_SCALINGMETHOD_SINC8:
547 case VS_SCALINGMETHOD_NEDI:
548 CLog::Log(LOGERROR, "D3D: TODO: This scaler has not yet been implemented");
551 case VS_SCALINGMETHOD_BICUBIC_SOFTWARE:
552 case VS_SCALINGMETHOD_LANCZOS_SOFTWARE:
553 case VS_SCALINGMETHOD_SINC_SOFTWARE:
554 CLog::Log(LOGERROR, "D3D: TODO: Software scaling has not yet been implemented");
561 if (m_scalingMethod == VS_SCALINGMETHOD_AUTO)
563 bool scaleSD = m_sourceHeight < 720 && m_sourceWidth < 1280;
564 bool scaleUp = (int)m_sourceHeight < g_graphicsContext.GetHeight() && (int)m_sourceWidth < g_graphicsContext.GetWidth();
565 bool scaleFps = m_fps < (g_advancedSettings.m_videoAutoScaleMaxFps + 0.01f);
567 if (m_renderMethod == RENDER_DXVA)
569 m_scalingMethod = VS_SCALINGMETHOD_DXVA_HARDWARE;
570 m_bUseHQScaler = false;
572 else if (scaleSD && scaleUp && scaleFps && Supports(VS_SCALINGMETHOD_LANCZOS3_FAST))
574 m_scalingMethod = VS_SCALINGMETHOD_LANCZOS3_FAST;
575 m_bUseHQScaler = true;
580 void CWinRenderer::UpdatePSVideoFilter()
582 SAFE_DELETE(m_scalerShader);
586 // First try the more efficient two pass convolution scaler
587 m_scalerShader = new CConvolutionShaderSeparable();
589 if (!m_scalerShader->Create(m_scalingMethod))
591 SAFE_DELETE(m_scalerShader);
592 CLog::Log(LOGNOTICE, __FUNCTION__": two pass convolution shader init problem, falling back to one pass.");
595 // Fallback on the one pass version
596 if (m_scalerShader == NULL)
598 m_scalerShader = new CConvolutionShader1Pass();
600 if (!m_scalerShader->Create(m_scalingMethod))
602 SAFE_DELETE(m_scalerShader);
603 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(34400), g_localizeStrings.Get(34401));
604 m_bUseHQScaler = false;
609 if (m_bUseHQScaler && !CreateIntermediateRenderTarget(m_sourceWidth, m_sourceHeight))
611 SAFE_DELETE(m_scalerShader);
612 m_bUseHQScaler = false;
615 SAFE_DELETE(m_colorShader);
617 if (m_renderMethod == RENDER_DXVA)
619 // we'd use m_IntermediateTarget as rendering target for possible anaglyph stereo with dxva processor.
621 CreateIntermediateRenderTarget(m_destWidth, m_destHeight);
623 // When using DXVA, we are already setup at this point, color shader is not needed
629 m_colorShader = new CYUV2RGBShader();
630 if (!m_colorShader->Create(m_sourceWidth, m_sourceHeight, m_format))
632 // Try again after disabling the HQ scaler and freeing its resources
633 m_IntermediateTarget.Release();
634 SAFE_DELETE(m_scalerShader);
635 SAFE_DELETE(m_colorShader);
636 m_bUseHQScaler = false;
640 if (!m_bUseHQScaler) //fallback from HQ scalers and multipass creation above
642 m_colorShader = new CYUV2RGBShader();
643 if (!m_colorShader->Create(m_sourceWidth, m_sourceHeight, m_format))
644 SAFE_DELETE(m_colorShader);
645 // we're in big trouble - should fallback on D3D accelerated or sw method
649 void CWinRenderer::UpdateVideoFilter()
651 if (m_scalingMethodGui == CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod && m_bFilterInitialized)
654 m_bFilterInitialized = true;
656 m_scalingMethodGui = CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod;
657 m_scalingMethod = m_scalingMethodGui;
659 if (!Supports(m_scalingMethod))
661 CLog::Log(LOGWARNING, __FUNCTION__" - chosen scaling method %d is not supported by renderer", (int)m_scalingMethod);
662 m_scalingMethod = VS_SCALINGMETHOD_AUTO;
665 switch(m_renderMethod)
668 SelectSWVideoFilter();
673 SelectPSVideoFilter();
674 UpdatePSVideoFilter();
682 void CWinRenderer::Render(DWORD flags)
684 if (m_renderMethod == RENDER_DXVA)
688 g_Windowing.FlushGPU();
689 CWinRenderer::RenderProcessor(flags);
695 // Optimize later? we could get by with bilinear under some circumstances
697 || !g_graphicsContext.IsFullScreenVideo()
698 || g_graphicsContext.IsCalibrating()
699 || (m_destRect.Width() == m_sourceWidth && m_destRect.Height() == m_sourceHeight))
701 CSingleLock lock(g_graphicsContext);
703 // Don't need a stencil/depth buffer and a buffer smaller than the render target causes D3D complaints and nVidia issues
704 // Save & restore when we're done.
705 LPDIRECT3DSURFACE9 pZBuffer;
706 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
707 pD3DDevice->GetDepthStencilSurface(&pZBuffer);
708 pD3DDevice->SetDepthStencilSurface(NULL);
710 if (m_renderMethod == RENDER_SW)
712 else if (m_renderMethod == RENDER_PS)
715 pD3DDevice->SetDepthStencilSurface(pZBuffer);
719 void CWinRenderer::RenderSW()
721 enum PixelFormat format = PixelFormatFromFormat(m_format);
723 // 1. convert yuv to rgb
724 m_sw_scale_ctx = m_dllSwScale->sws_getCachedContext(m_sw_scale_ctx,
725 m_sourceWidth, m_sourceHeight, format,
726 m_sourceWidth, m_sourceHeight, PIX_FMT_BGRA,
727 SWS_FAST_BILINEAR | SwScaleCPUFlags(), NULL, NULL, NULL);
729 YUVBuffer* buf = (YUVBuffer*)m_VideoBuffers[m_iYV12RenderBuffer];
731 D3DLOCKED_RECT srclr[MAX_PLANES];
732 uint8_t *src[MAX_PLANES];
733 int srcStride[MAX_PLANES];
735 for (unsigned int idx = 0; idx < buf->GetActivePlanes(); idx++)
737 if(!(buf->planes[idx].texture.LockRect(0, &srclr[idx], NULL, D3DLOCK_READONLY)))
738 CLog::Log(LOGERROR, __FUNCTION__" - failed to lock yuv textures into memory");
741 src[idx] = (uint8_t*)srclr[idx].pBits;
742 srcStride[idx] = srclr[idx].Pitch;
746 D3DLOCKED_RECT destlr = {0,0};
747 if (!m_SWTarget.LockRect(0, &destlr, NULL, D3DLOCK_DISCARD))
748 CLog::Log(LOGERROR, __FUNCTION__" - failed to lock swtarget texture into memory");
750 uint8_t *dst[] = { (uint8_t*) destlr.pBits, 0, 0, 0 };
751 int dstStride[] = { destlr.Pitch, 0, 0, 0 };
753 m_dllSwScale->sws_scale(m_sw_scale_ctx, src, srcStride, 0, m_sourceHeight, dst, dstStride);
755 for (unsigned int idx = 0; idx < buf->GetActivePlanes(); idx++)
756 if(!(buf->planes[idx].texture.UnlockRect(0)))
757 CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock yuv textures");
759 if (!m_SWTarget.UnlockRect(0))
760 CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock swtarget texture");
762 // 2. scale to display
764 // Don't know where this martian comes from but it can happen in the initial frames of a video
765 if ((m_destRect.x1 < 0 && m_destRect.x2 < 0) || (m_destRect.y1 < 0 && m_destRect.y2 < 0))
768 ScaleFixedPipeline();
772 Code kept for reference, as a basis to re-enable StretchRect and
773 do the color conversion with it.
774 See IDirect3D9::CheckDeviceFormat() for support of non-standard fourcc textures
775 and IDirect3D9::CheckDeviceFormatConversion for color conversion support
777 void CWinRenderer::ScaleStretchRect()
779 // Test HW scaler support. StretchRect is slightly faster than drawing a quad.
780 // If linear filtering is not supported, drop back to quads, as most HW has linear filtering for quads.
781 //if(m_deviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES
782 //&& m_deviceCaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFLINEAR
783 //&& m_deviceCaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)
785 // m_StretchRectSupported = true;
788 CRect sourceRect = m_sourceRect;
789 CRect destRect = m_destRect;
791 D3DSURFACE_DESC desc;
792 if (FAILED(target->GetDesc(&desc)))
793 CLog::Log(LOGERROR, "CWinRenderer::Render - failed to get back buffer description");
794 CRect tgtRect(0, 0, desc.Width, desc.Height);
796 // Need to manipulate the coordinates since StretchRect doesn't accept off-screen coordinates.
797 CWIN32Util::CropSource(sourceRect, destRect, tgtRect);
799 RECT srcRect = { sourceRect.x1, sourceRect.y1, sourceRect.x2, sourceRect.y2 };
800 IDirect3DSurface9* source;
801 if(!m_SWTarget.GetSurfaceLevel(0, &source))
802 CLog::Log(LOGERROR, "CWinRenderer::Render - failed to get source");
804 RECT dstRect = { destRect.x1, destRect.y1, destRect.x2, destRect.y2 };
805 IDirect3DSurface9* target;
806 if(FAILED(g_Windowing.Get3DDevice()->GetRenderTarget(0, &target)))
807 CLog::Log(LOGERROR, "CWinRenderer::Render - failed to get back buffer");
810 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
812 if(FAILED(hr = pD3DDevice->StretchRect(source, &srcRect, target, &dstRect, m_TextureFilter)))
813 CLog::Log(LOGERROR, __FUNCTION__" - StretchRect failed (0x%08X)", hr);
820 void CWinRenderer::ScaleFixedPipeline()
823 IDirect3DDevice9 *pD3DDev = g_Windowing.Get3DDevice();
824 D3DSURFACE_DESC srcDesc;
825 if (FAILED(hr = m_SWTarget.Get()->GetLevelDesc(0, &srcDesc)))
826 CLog::Log(LOGERROR, __FUNCTION__": GetLevelDesc failed. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
828 float srcWidth = (float)srcDesc.Width;
829 float srcHeight = (float)srcDesc.Height;
831 bool cbcontrol = (CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast != 50.0f || CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness != 50.0f);
832 unsigned int contrast = (unsigned int)(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast *.01f * 255.0f); // we have to divide by two here/multiply by two later
833 unsigned int brightness = (unsigned int)(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * .01f * 255.0f);
835 D3DCOLOR diffuse = D3DCOLOR_ARGB(255, contrast, contrast, contrast);
836 D3DCOLOR specular = D3DCOLOR_ARGB(255, brightness, brightness, brightness);
846 // Vertex format ignores viewport offsets, so correct for that here
847 CRect dest = g_graphicsContext.StereoCorrection(m_destRect);
851 {dest.x1, dest.y1, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x1 / srcWidth, m_sourceRect.y1 / srcHeight},
852 {dest.x2, dest.y1, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x2 / srcWidth, m_sourceRect.y1 / srcHeight},
853 {dest.x2, dest.y2, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x2 / srcWidth, m_sourceRect.y2 / srcHeight},
854 {dest.x1, dest.y2, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x1 / srcWidth, m_sourceRect.y2 / srcHeight},
857 // Compensate for D3D coordinates system
858 for(int i = 0; i < sizeof(vertex)/sizeof(vertex[0]); i++)
864 pD3DDev->SetTexture(0, m_SWTarget.Get());
868 pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
869 pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
870 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
871 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
872 pD3DDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
873 pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
877 pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE2X );
878 pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
879 pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
880 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
881 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
883 pD3DDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_ADDSIGNED );
884 pD3DDev->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT );
885 pD3DDev->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_SPECULAR );
886 pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
887 pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
889 pD3DDev->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
890 pD3DDev->SetTextureStageState( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
893 pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
894 pD3DDev->SetRenderState(D3DRS_LIGHTING, FALSE);
895 pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
896 pD3DDev->SetRenderState(D3DRS_STENCILENABLE, FALSE);
897 pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
898 pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
899 pD3DDev->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
901 pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, m_TextureFilter);
902 pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, m_TextureFilter);
903 pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
904 pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
906 pD3DDev->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1);
908 if (FAILED(hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, vertex, sizeof(VERTEX))))
909 CLog::Log(LOGERROR, __FUNCTION__": DrawPrimitiveUP failed. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
911 pD3DDev->SetTexture(0, NULL);
914 void CWinRenderer::RenderPS()
927 void CWinRenderer::Stage1()
931 m_colorShader->Render(m_sourceRect, g_graphicsContext.StereoCorrection(m_destRect),
932 CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast,
933 CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness,
935 (YUVBuffer*)m_VideoBuffers[m_iYV12RenderBuffer]);
939 // Switch the render target to the temporary destination
940 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
941 LPDIRECT3DSURFACE9 newRT, oldRT;
942 m_IntermediateTarget.GetSurfaceLevel(0, &newRT);
943 pD3DDevice->GetRenderTarget(0, &oldRT);
944 pD3DDevice->SetRenderTarget(0, newRT);
946 CRect srcRect(0.0f, 0.0f, m_sourceWidth, m_sourceHeight);
947 CRect rtRect(0.0f, 0.0f, m_sourceWidth, m_sourceHeight);
949 m_colorShader->Render(srcRect, rtRect,
950 CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast,
951 CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness,
953 (YUVBuffer*)m_VideoBuffers[m_iYV12RenderBuffer]);
955 // Restore the render target
956 pD3DDevice->SetRenderTarget(0, oldRT);
958 // MSDN says: Setting a new render target will cause the viewport
959 // to be set to the full size of the new render target.
960 // So we need restore our viewport
961 g_Windowing.RestoreViewPort();
968 void CWinRenderer::Stage2()
972 // fixup stereo+dxva+hq scaling issue
973 if (m_renderMethod == RENDER_DXVA)
975 sourceRect.y1 = 0.0f;
976 sourceRect.y2 = m_sourceHeight;
977 sourceRect.x1 = 0.0f;
978 sourceRect.x2 = m_sourceWidth;
981 sourceRect = m_sourceRect;
983 m_scalerShader->Render(m_IntermediateTarget, m_sourceWidth, m_sourceHeight, m_destWidth, m_destHeight, sourceRect, g_graphicsContext.StereoCorrection(m_destRect));
986 void CWinRenderer::RenderProcessor(DWORD flags)
988 CSingleLock lock(g_graphicsContext);
995 destRect.y2 = m_sourceHeight;
997 destRect.x2 = m_sourceWidth;
1000 destRect = g_graphicsContext.StereoCorrection(m_destRect);
1002 DXVABuffer *image = (DXVABuffer*)m_VideoBuffers[m_iYV12RenderBuffer];
1004 IDirect3DSurface9* target;
1006 || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN
1007 || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA)
1009 m_IntermediateTarget.GetSurfaceLevel(0, &target);
1013 if(FAILED(hr = g_Windowing.Get3DDevice()->GetRenderTarget(0, &target)))
1015 CLog::Log(LOGERROR, "CWinRenderer::RenderSurface - failed to get render target. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
1020 m_processor->Render(m_sourceRect, destRect, target, image->id, flags);
1028 else if ( g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN
1029 || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA)
1031 IDirect3DDevice9 *pD3DDev = g_Windowing.Get3DDevice();
1041 {destRect.x1 - 0.5f, destRect.y1 - 0.5f, 0.0f, m_destRect.x1 / m_destWidth, m_destRect.y1 / m_destHeight},
1042 {destRect.x2 - 0.5f, destRect.y1 - 0.5f, 0.0f, m_destRect.x2 / m_destWidth, m_destRect.y1 / m_destHeight},
1043 {destRect.x2 - 0.5f, destRect.y2 - 0.5f, 0.0f, m_destRect.x2 / m_destWidth, m_destRect.y2 / m_destHeight},
1044 {destRect.x1 - 0.5f, destRect.y2 - 0.5f, 0.0f, m_destRect.x1 / m_destWidth, m_destRect.y2 / m_destHeight},
1047 pD3DDev->SetTexture(0, m_IntermediateTarget.Get());
1049 pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
1050 pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
1051 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
1052 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
1053 pD3DDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
1054 pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
1056 pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1057 pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1059 pD3DDev->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1);
1061 if (FAILED(hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, vertex, sizeof(VERTEX))))
1062 CLog::Log(LOGERROR, __FUNCTION__": DrawPrimitiveUP failed. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
1064 pD3DDev->SetTexture(0, NULL);
1068 bool CWinRenderer::RenderCapture(CRenderCapture* capture)
1070 if (!m_bConfigured || m_NumYV12Buffers == 0)
1073 bool succeeded = false;
1075 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
1077 CRect saveSize = m_destRect;
1078 saveRotatedCoords();//backup current m_rotatedDestCoords
1080 m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight());
1081 syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords
1083 LPDIRECT3DSURFACE9 oldSurface;
1084 pD3DDevice->GetRenderTarget(0, &oldSurface);
1086 capture->BeginRender();
1087 if (capture->GetState() != CAPTURESTATE_FAILED)
1089 pD3DDevice->BeginScene();
1091 pD3DDevice->EndScene();
1092 capture->EndRender();
1096 pD3DDevice->SetRenderTarget(0, oldSurface);
1097 oldSurface->Release();
1099 m_destRect = saveSize;
1100 restoreRotatedCoords();//restores the previous state of the rotated dest coords
1105 //********************************************************************************************************
1106 // YV12 Texture creation, deletion, copying + clearing
1107 //********************************************************************************************************
1108 void CWinRenderer::DeleteYV12Texture(int index)
1110 CSingleLock lock(g_graphicsContext);
1111 if (m_VideoBuffers[index] != NULL)
1112 SAFE_DELETE(m_VideoBuffers[index]);
1113 m_NumYV12Buffers = 0;
1116 bool CWinRenderer::CreateYV12Texture(int index)
1118 CSingleLock lock(g_graphicsContext);
1119 DeleteYV12Texture(index);
1121 if (m_renderMethod == RENDER_DXVA)
1123 m_VideoBuffers[index] = new DXVABuffer();
1127 YUVBuffer *buf = new YUVBuffer();
1129 if (!buf->Create(m_format, m_sourceWidth, m_sourceHeight))
1131 CLog::Log(LOGERROR, __FUNCTION__" - Unable to create YV12 video texture %i", index);
1134 m_VideoBuffers[index] = buf;
1137 SVideoBuffer *buf = m_VideoBuffers[index];
1142 if(index == m_iYV12RenderBuffer)
1145 CLog::Log(LOGDEBUG, "created video buffer %i", index);
1149 bool CWinRenderer::Supports(EDEINTERLACEMODE mode)
1151 if(mode == VS_DEINTERLACEMODE_OFF
1152 || mode == VS_DEINTERLACEMODE_AUTO
1153 || mode == VS_DEINTERLACEMODE_FORCE)
1159 bool CWinRenderer::Supports(EINTERLACEMETHOD method)
1161 if(method == VS_INTERLACEMETHOD_AUTO)
1164 if (m_renderMethod == RENDER_DXVA)
1166 if(method == VS_INTERLACEMETHOD_DXVA_BOB
1167 || method == VS_INTERLACEMETHOD_DXVA_BEST)
1171 if(m_format != RENDER_FMT_DXVA
1172 && ( method == VS_INTERLACEMETHOD_DEINTERLACE
1173 || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
1174 || method == VS_INTERLACEMETHOD_SW_BLEND))
1180 bool CWinRenderer::Supports(ERENDERFEATURE feature)
1182 if(feature == RENDERFEATURE_BRIGHTNESS)
1185 if(feature == RENDERFEATURE_CONTRAST)
1188 if (feature == RENDERFEATURE_STRETCH ||
1189 feature == RENDERFEATURE_NONLINSTRETCH ||
1190 feature == RENDERFEATURE_CROP ||
1191 feature == RENDERFEATURE_ZOOM ||
1192 feature == RENDERFEATURE_VERTICAL_SHIFT ||
1193 feature == RENDERFEATURE_PIXEL_RATIO ||
1194 feature == RENDERFEATURE_POSTPROCESS)
1201 bool CWinRenderer::Supports(ESCALINGMETHOD method)
1203 if (m_renderMethod == RENDER_PS || m_renderMethod == RENDER_DXVA)
1205 if(m_renderMethod == RENDER_DXVA && method == VS_SCALINGMETHOD_DXVA_HARDWARE)
1208 if(m_deviceCaps.PixelShaderVersion >= D3DPS_VERSION(2, 0)
1209 && ( method == VS_SCALINGMETHOD_AUTO
1210 || (method == VS_SCALINGMETHOD_LINEAR && m_renderMethod == RENDER_PS) ))
1213 if(m_deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
1215 if(method == VS_SCALINGMETHOD_CUBIC
1216 || method == VS_SCALINGMETHOD_LANCZOS2
1217 || method == VS_SCALINGMETHOD_SPLINE36_FAST
1218 || method == VS_SCALINGMETHOD_LANCZOS3_FAST
1219 || method == VS_SCALINGMETHOD_SPLINE36
1220 || method == VS_SCALINGMETHOD_LANCZOS3)
1222 // if scaling is below level, avoid hq scaling
1223 float scaleX = fabs(((float)m_sourceWidth - m_destRect.Width())/m_sourceWidth)*100;
1224 float scaleY = fabs(((float)m_sourceHeight - m_destRect.Height())/m_sourceHeight)*100;
1225 int minScale = CSettings::Get().GetInt("videoplayer.hqscalers");
1226 if (scaleX < minScale && scaleY < minScale)
1232 else if(m_renderMethod == RENDER_SW)
1234 if(method == VS_SCALINGMETHOD_AUTO
1235 || method == VS_SCALINGMETHOD_NEAREST)
1237 if(method == VS_SCALINGMETHOD_LINEAR
1238 && m_deviceCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR
1239 && m_deviceCaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)
1245 EINTERLACEMETHOD CWinRenderer::AutoInterlaceMethod()
1247 if (m_renderMethod == RENDER_DXVA)
1248 return VS_INTERLACEMETHOD_DXVA_BOB;
1250 return VS_INTERLACEMETHOD_DEINTERLACE_HALF;
1253 unsigned int CWinRenderer::GetProcessorSize()
1255 if (m_format == RENDER_FMT_DXVA && m_processor)
1256 return m_processor->Size();
1261 //============================================
1263 YUVBuffer::~YUVBuffer()
1268 bool YUVBuffer::Create(ERenderFormat format, unsigned int width, unsigned int height)
1274 // Create the buffers in system memory and copy to D3DPOOL_DEFAULT:
1275 // - helps with lost devices. A buffer can be locked for dvdplayer without interfering.
1276 // - Dynamic + D3DPOOL_DEFAULT caused trouble for Intel i3 and some IGP. Bad sync/locking in the driver I suppose
1277 // and Present failed every second time for the second video played.
1278 // - this is what D3D9 does behind the scenes anyway
1281 case RENDER_FMT_YUV420P10:
1282 case RENDER_FMT_YUV420P16:
1284 if ( !planes[PLANE_Y].texture.Create(m_width , m_height , 1, 0, D3DFMT_L16, D3DPOOL_SYSTEMMEM)
1285 || !planes[PLANE_U].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L16, D3DPOOL_SYSTEMMEM)
1286 || !planes[PLANE_V].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L16, D3DPOOL_SYSTEMMEM))
1291 case RENDER_FMT_YUV420P:
1293 if ( !planes[PLANE_Y].texture.Create(m_width , m_height , 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM)
1294 || !planes[PLANE_U].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM)
1295 || !planes[PLANE_V].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM))
1300 case RENDER_FMT_NV12:
1302 if ( !planes[PLANE_Y].texture.Create(m_width , m_height , 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM)
1303 || !planes[PLANE_UV].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_A8L8, D3DPOOL_SYSTEMMEM))
1308 case RENDER_FMT_YUYV422:
1310 if ( !planes[PLANE_Y].texture.Create(m_width >> 1 , m_height , 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM))
1315 case RENDER_FMT_UYVY422:
1317 if ( !planes[PLANE_Y].texture.Create(m_width >> 1 , m_height , 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM))
1330 void YUVBuffer::Release()
1332 for(unsigned i = 0; i < m_activeplanes; i++)
1334 planes[i].texture.Release();
1335 memset(&planes[i].rect, 0, sizeof(planes[i].rect));
1339 void YUVBuffer::StartRender()
1341 for(unsigned i = 0; i < m_activeplanes; i++)
1343 if(planes[i].texture.Get() && planes[i].rect.pBits)
1344 if (!planes[i].texture.UnlockRect(0))
1345 CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock texture %d", i);
1346 memset(&planes[i].rect, 0, sizeof(planes[i].rect));
1350 void YUVBuffer::StartDecode()
1352 for(unsigned i = 0; i < m_activeplanes; i++)
1354 if(planes[i].texture.Get()
1355 && planes[i].texture.LockRect(0, &planes[i].rect, NULL, D3DLOCK_DISCARD) == false)
1357 memset(&planes[i].rect, 0, sizeof(planes[i].rect));
1358 CLog::Log(LOGERROR, __FUNCTION__" - failed to lock texture %d into memory", i);
1363 void YUVBuffer::Clear()
1365 // Set Y to 0 and U,V to 128 (RGB 0,0,0) to avoid visual artifacts at the start of playback
1369 case RENDER_FMT_YUV420P16:
1371 wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height / 2);
1372 wmemset((wchar_t*)planes[PLANE_U].rect.pBits, 32768, planes[PLANE_U].rect.Pitch * (m_height/2) / 2);
1373 wmemset((wchar_t*)planes[PLANE_V].rect.pBits, 32768, planes[PLANE_V].rect.Pitch * (m_height/2) / 2);
1376 case RENDER_FMT_YUV420P10:
1378 wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height / 2);
1379 wmemset((wchar_t*)planes[PLANE_U].rect.pBits, 512, planes[PLANE_U].rect.Pitch * (m_height/2) / 2);
1380 wmemset((wchar_t*)planes[PLANE_V].rect.pBits, 512, planes[PLANE_V].rect.Pitch * (m_height/2) / 2);
1383 case RENDER_FMT_YUV420P:
1385 memset(planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height);
1386 memset(planes[PLANE_U].rect.pBits, 128, planes[PLANE_U].rect.Pitch * (m_height/2));
1387 memset(planes[PLANE_V].rect.pBits, 128, planes[PLANE_V].rect.Pitch * (m_height/2));
1390 case RENDER_FMT_NV12:
1392 memset(planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height);
1393 memset(planes[PLANE_UV].rect.pBits, 128, planes[PLANE_U].rect.Pitch * (m_height/2));
1396 // YUY2, UYVY: wmemset to set a 16bit pattern, byte-swapped because x86 is LE
1397 case RENDER_FMT_YUYV422:
1399 wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0x8000, planes[PLANE_Y].rect.Pitch / 2 * m_height);
1402 case RENDER_FMT_UYVY422:
1404 wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0x0080, planes[PLANE_Y].rect.Pitch / 2 * m_height);
1412 //==================================
1414 DXVABuffer::~DXVABuffer()
1419 void DXVABuffer::Release()
1424 void DXVABuffer::StartDecode()