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);
395 m_formats.push_back(RENDER_FMT_YUV420P);
396 if(g_Windowing.IsTextureFormatOk(D3DFMT_L16, 0))
398 m_formats.push_back(RENDER_FMT_YUV420P10);
399 m_formats.push_back(RENDER_FMT_YUV420P16);
401 m_formats.push_back(RENDER_FMT_NV12);
402 m_formats.push_back(RENDER_FMT_YUYV422);
403 m_formats.push_back(RENDER_FMT_UYVY422);
405 m_iRequestedMethod = CSettings::Get().GetInt("videoplayer.rendermethod");
407 if (g_advancedSettings.m_DXVAForceProcessorRenderer || m_iRequestedMethod == RENDER_METHOD_DXVA
408 || m_iRequestedMethod == RENDER_METHOD_DXVAHD)
410 if (m_iRequestedMethod != RENDER_METHOD_DXVA && CSysInfo::IsWindowsVersionAtLeast(CSysInfo::WindowsVersionWin7))
412 m_processor = new DXVA::CProcessorHD();
413 if (!m_processor->PreInit())
415 CLog::Log(LOGNOTICE, "CWinRenderer::Preinit - could not init DXVA-HD processor - skipping");
416 SAFE_DELETE(m_processor);
417 m_processor = new DXVA::CProcessor();
423 m_processor = new DXVA::CProcessor();
425 if (!m_processor->PreInit())
426 CLog::Log(LOGNOTICE, "CWinRenderer::Preinit - could not init DXVA2 processor - skipping");
432 void CWinRenderer::UnInit()
434 CSingleLock lock(g_graphicsContext);
436 if (m_SWTarget.Get())
437 m_SWTarget.Release();
439 if (m_IntermediateTarget.Get())
440 m_IntermediateTarget.Release();
442 SAFE_DELETE(m_colorShader);
443 SAFE_DELETE(m_scalerShader);
445 m_bConfigured = false;
446 m_bFilterInitialized = false;
448 for(int i = 0; i < NUM_BUFFERS; i++)
449 DeleteYV12Texture(i);
451 m_NumYV12Buffers = 0;
455 m_dllSwScale->sws_freeContext(m_sw_scale_ctx);
456 m_sw_scale_ctx = NULL;
458 SAFE_DELETE(m_dllSwScale);
462 m_processor->UnInit();
463 SAFE_DELETE(m_processor);
467 bool CWinRenderer::CreateIntermediateRenderTarget(unsigned int width, unsigned int height)
469 // Initialize a render target for intermediate rendering
470 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
471 D3DFORMAT format = D3DFMT_X8R8G8B8;
472 DWORD usage = D3DUSAGE_RENDERTARGET;
474 if (m_renderMethod == RENDER_DXVA) format = D3DFMT_X8R8G8B8;
475 else if (g_Windowing.IsTextureFormatOk(D3DFMT_A2R10G10B10, usage)) format = D3DFMT_A2R10G10B10;
476 else if (g_Windowing.IsTextureFormatOk(D3DFMT_A2B10G10R10, usage)) format = D3DFMT_A2B10G10R10;
477 else if (g_Windowing.IsTextureFormatOk(D3DFMT_A8R8G8B8, usage)) format = D3DFMT_A8R8G8B8;
478 else if (g_Windowing.IsTextureFormatOk(D3DFMT_A8B8G8R8, usage)) format = D3DFMT_A8B8G8R8;
479 else if (g_Windowing.IsTextureFormatOk(D3DFMT_X8R8G8B8, usage)) format = D3DFMT_X8R8G8B8;
480 else if (g_Windowing.IsTextureFormatOk(D3DFMT_X8B8G8R8, usage)) format = D3DFMT_X8B8G8R8;
481 else if (g_Windowing.IsTextureFormatOk(D3DFMT_R8G8B8, usage)) format = D3DFMT_R8G8B8;
483 // don't create new one if it exists with requested size and format
484 if ( m_IntermediateTarget.Get() && m_IntermediateTarget.GetFormat() == format
485 && m_IntermediateTarget.GetWidth() == width && m_IntermediateTarget.GetHeight() == height)
488 if (m_IntermediateTarget.Get())
489 m_IntermediateTarget.Release();
491 CLog::Log(LOGDEBUG, __FUNCTION__": format %i", format);
493 if(!m_IntermediateTarget.Create(width, height, 1, usage, format, D3DPOOL_DEFAULT))
495 CLog::Log(LOGERROR, __FUNCTION__": intermediate render target creation failed.", format);
501 void CWinRenderer::SelectSWVideoFilter()
503 switch (m_scalingMethod)
505 case VS_SCALINGMETHOD_AUTO:
506 case VS_SCALINGMETHOD_LINEAR:
507 if (Supports(VS_SCALINGMETHOD_LINEAR))
509 m_TextureFilter = D3DTEXF_LINEAR;
512 // fall through for fallback
513 case VS_SCALINGMETHOD_NEAREST:
515 m_TextureFilter = D3DTEXF_POINT;
520 void CWinRenderer::SelectPSVideoFilter()
522 m_bUseHQScaler = false;
524 switch (m_scalingMethod)
526 case VS_SCALINGMETHOD_NEAREST:
527 case VS_SCALINGMETHOD_LINEAR:
530 case VS_SCALINGMETHOD_CUBIC:
531 case VS_SCALINGMETHOD_LANCZOS2:
532 case VS_SCALINGMETHOD_SPLINE36_FAST:
533 case VS_SCALINGMETHOD_LANCZOS3_FAST:
534 m_bUseHQScaler = true;
537 case VS_SCALINGMETHOD_SPLINE36:
538 case VS_SCALINGMETHOD_LANCZOS3:
539 m_bUseHQScaler = true;
542 case VS_SCALINGMETHOD_SINC8:
543 case VS_SCALINGMETHOD_NEDI:
544 CLog::Log(LOGERROR, "D3D: TODO: This scaler has not yet been implemented");
547 case VS_SCALINGMETHOD_BICUBIC_SOFTWARE:
548 case VS_SCALINGMETHOD_LANCZOS_SOFTWARE:
549 case VS_SCALINGMETHOD_SINC_SOFTWARE:
550 CLog::Log(LOGERROR, "D3D: TODO: Software scaling has not yet been implemented");
557 if (m_scalingMethod == VS_SCALINGMETHOD_AUTO)
559 bool scaleSD = m_sourceHeight < 720 && m_sourceWidth < 1280;
560 bool scaleUp = (int)m_sourceHeight < g_graphicsContext.GetHeight() && (int)m_sourceWidth < g_graphicsContext.GetWidth();
561 bool scaleFps = m_fps < (g_advancedSettings.m_videoAutoScaleMaxFps + 0.01f);
563 if (m_renderMethod == RENDER_DXVA)
565 m_scalingMethod = VS_SCALINGMETHOD_DXVA_HARDWARE;
566 m_bUseHQScaler = false;
568 else if (scaleSD && scaleUp && scaleFps && Supports(VS_SCALINGMETHOD_LANCZOS3_FAST))
570 m_scalingMethod = VS_SCALINGMETHOD_LANCZOS3_FAST;
571 m_bUseHQScaler = true;
576 void CWinRenderer::UpdatePSVideoFilter()
578 SAFE_DELETE(m_scalerShader);
582 // First try the more efficient two pass convolution scaler
583 m_scalerShader = new CConvolutionShaderSeparable();
585 if (!m_scalerShader->Create(m_scalingMethod))
587 SAFE_DELETE(m_scalerShader);
588 CLog::Log(LOGNOTICE, __FUNCTION__": two pass convolution shader init problem, falling back to one pass.");
591 // Fallback on the one pass version
592 if (m_scalerShader == NULL)
594 m_scalerShader = new CConvolutionShader1Pass();
596 if (!m_scalerShader->Create(m_scalingMethod))
598 SAFE_DELETE(m_scalerShader);
599 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(34400), g_localizeStrings.Get(34401));
600 m_bUseHQScaler = false;
605 if (m_bUseHQScaler && !CreateIntermediateRenderTarget(m_sourceWidth, m_sourceHeight))
607 SAFE_DELETE(m_scalerShader);
608 m_bUseHQScaler = false;
611 SAFE_DELETE(m_colorShader);
613 if (m_renderMethod == RENDER_DXVA)
615 // we'd use m_IntermediateTarget as rendering target for possible anaglyph stereo with dxva processor.
617 CreateIntermediateRenderTarget(m_destWidth, m_destHeight);
619 // When using DXVA, we are already setup at this point, color shader is not needed
625 m_colorShader = new CYUV2RGBShader();
626 if (!m_colorShader->Create(m_sourceWidth, m_sourceHeight, m_format))
628 // Try again after disabling the HQ scaler and freeing its resources
629 m_IntermediateTarget.Release();
630 SAFE_DELETE(m_scalerShader);
631 SAFE_DELETE(m_colorShader);
632 m_bUseHQScaler = false;
636 if (!m_bUseHQScaler) //fallback from HQ scalers and multipass creation above
638 m_colorShader = new CYUV2RGBShader();
639 if (!m_colorShader->Create(m_sourceWidth, m_sourceHeight, m_format))
640 SAFE_DELETE(m_colorShader);
641 // we're in big trouble - should fallback on D3D accelerated or sw method
645 void CWinRenderer::UpdateVideoFilter()
647 if (m_scalingMethodGui == CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod && m_bFilterInitialized)
650 m_bFilterInitialized = true;
652 m_scalingMethodGui = CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod;
653 m_scalingMethod = m_scalingMethodGui;
655 if (!Supports(m_scalingMethod))
657 CLog::Log(LOGWARNING, __FUNCTION__" - chosen scaling method %d is not supported by renderer", (int)m_scalingMethod);
658 m_scalingMethod = VS_SCALINGMETHOD_AUTO;
661 switch(m_renderMethod)
664 SelectSWVideoFilter();
669 SelectPSVideoFilter();
670 UpdatePSVideoFilter();
678 void CWinRenderer::Render(DWORD flags)
680 if (m_renderMethod == RENDER_DXVA)
684 g_Windowing.FlushGPU();
685 CWinRenderer::RenderProcessor(flags);
691 // Optimize later? we could get by with bilinear under some circumstances
693 || !g_graphicsContext.IsFullScreenVideo()
694 || g_graphicsContext.IsCalibrating()
695 || (m_destRect.Width() == m_sourceWidth && m_destRect.Height() == m_sourceHeight))
697 CSingleLock lock(g_graphicsContext);
699 // Don't need a stencil/depth buffer and a buffer smaller than the render target causes D3D complaints and nVidia issues
700 // Save & restore when we're done.
701 LPDIRECT3DSURFACE9 pZBuffer;
702 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
703 pD3DDevice->GetDepthStencilSurface(&pZBuffer);
704 pD3DDevice->SetDepthStencilSurface(NULL);
706 if (m_renderMethod == RENDER_SW)
708 else if (m_renderMethod == RENDER_PS)
711 pD3DDevice->SetDepthStencilSurface(pZBuffer);
715 void CWinRenderer::RenderSW()
717 enum PixelFormat format = PixelFormatFromFormat(m_format);
719 // 1. convert yuv to rgb
720 m_sw_scale_ctx = m_dllSwScale->sws_getCachedContext(m_sw_scale_ctx,
721 m_sourceWidth, m_sourceHeight, format,
722 m_sourceWidth, m_sourceHeight, PIX_FMT_BGRA,
723 SWS_FAST_BILINEAR | SwScaleCPUFlags(), NULL, NULL, NULL);
725 YUVBuffer* buf = (YUVBuffer*)m_VideoBuffers[m_iYV12RenderBuffer];
727 D3DLOCKED_RECT srclr[MAX_PLANES];
728 uint8_t *src[MAX_PLANES];
729 int srcStride[MAX_PLANES];
731 for (unsigned int idx = 0; idx < buf->GetActivePlanes(); idx++)
733 if(!(buf->planes[idx].texture.LockRect(0, &srclr[idx], NULL, D3DLOCK_READONLY)))
734 CLog::Log(LOGERROR, __FUNCTION__" - failed to lock yuv textures into memory");
737 src[idx] = (uint8_t*)srclr[idx].pBits;
738 srcStride[idx] = srclr[idx].Pitch;
742 D3DLOCKED_RECT destlr = {0,0};
743 if (!m_SWTarget.LockRect(0, &destlr, NULL, D3DLOCK_DISCARD))
744 CLog::Log(LOGERROR, __FUNCTION__" - failed to lock swtarget texture into memory");
746 uint8_t *dst[] = { (uint8_t*) destlr.pBits, 0, 0, 0 };
747 int dstStride[] = { destlr.Pitch, 0, 0, 0 };
749 m_dllSwScale->sws_scale(m_sw_scale_ctx, src, srcStride, 0, m_sourceHeight, dst, dstStride);
751 for (unsigned int idx = 0; idx < buf->GetActivePlanes(); idx++)
752 if(!(buf->planes[idx].texture.UnlockRect(0)))
753 CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock yuv textures");
755 if (!m_SWTarget.UnlockRect(0))
756 CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock swtarget texture");
758 // 2. scale to display
760 // Don't know where this martian comes from but it can happen in the initial frames of a video
761 if ((m_destRect.x1 < 0 && m_destRect.x2 < 0) || (m_destRect.y1 < 0 && m_destRect.y2 < 0))
764 ScaleFixedPipeline();
768 Code kept for reference, as a basis to re-enable StretchRect and
769 do the color conversion with it.
770 See IDirect3D9::CheckDeviceFormat() for support of non-standard fourcc textures
771 and IDirect3D9::CheckDeviceFormatConversion for color conversion support
773 void CWinRenderer::ScaleStretchRect()
775 // Test HW scaler support. StretchRect is slightly faster than drawing a quad.
776 // If linear filtering is not supported, drop back to quads, as most HW has linear filtering for quads.
777 //if(m_deviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES
778 //&& m_deviceCaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFLINEAR
779 //&& m_deviceCaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)
781 // m_StretchRectSupported = true;
784 CRect sourceRect = m_sourceRect;
785 CRect destRect = m_destRect;
787 D3DSURFACE_DESC desc;
788 if (FAILED(target->GetDesc(&desc)))
789 CLog::Log(LOGERROR, "CWinRenderer::Render - failed to get back buffer description");
790 CRect tgtRect(0, 0, desc.Width, desc.Height);
792 // Need to manipulate the coordinates since StretchRect doesn't accept off-screen coordinates.
793 CWIN32Util::CropSource(sourceRect, destRect, tgtRect);
795 RECT srcRect = { sourceRect.x1, sourceRect.y1, sourceRect.x2, sourceRect.y2 };
796 IDirect3DSurface9* source;
797 if(!m_SWTarget.GetSurfaceLevel(0, &source))
798 CLog::Log(LOGERROR, "CWinRenderer::Render - failed to get source");
800 RECT dstRect = { destRect.x1, destRect.y1, destRect.x2, destRect.y2 };
801 IDirect3DSurface9* target;
802 if(FAILED(g_Windowing.Get3DDevice()->GetRenderTarget(0, &target)))
803 CLog::Log(LOGERROR, "CWinRenderer::Render - failed to get back buffer");
806 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
808 if(FAILED(hr = pD3DDevice->StretchRect(source, &srcRect, target, &dstRect, m_TextureFilter)))
809 CLog::Log(LOGERROR, __FUNCTION__" - StretchRect failed (0x%08X)", hr);
816 void CWinRenderer::ScaleFixedPipeline()
819 IDirect3DDevice9 *pD3DDev = g_Windowing.Get3DDevice();
820 D3DSURFACE_DESC srcDesc;
821 if (FAILED(hr = m_SWTarget.Get()->GetLevelDesc(0, &srcDesc)))
822 CLog::Log(LOGERROR, __FUNCTION__": GetLevelDesc failed. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
824 float srcWidth = (float)srcDesc.Width;
825 float srcHeight = (float)srcDesc.Height;
827 bool cbcontrol = (CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast != 50.0f || CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness != 50.0f);
828 unsigned int contrast = (unsigned int)(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast *.01f * 255.0f); // we have to divide by two here/multiply by two later
829 unsigned int brightness = (unsigned int)(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * .01f * 255.0f);
831 D3DCOLOR diffuse = D3DCOLOR_ARGB(255, contrast, contrast, contrast);
832 D3DCOLOR specular = D3DCOLOR_ARGB(255, brightness, brightness, brightness);
842 // Vertex format ignores viewport offsets, so correct for that here
843 CRect dest = g_graphicsContext.StereoCorrection(m_destRect);
847 {dest.x1, dest.y1, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x1 / srcWidth, m_sourceRect.y1 / srcHeight},
848 {dest.x2, dest.y1, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x2 / srcWidth, m_sourceRect.y1 / srcHeight},
849 {dest.x2, dest.y2, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x2 / srcWidth, m_sourceRect.y2 / srcHeight},
850 {dest.x1, dest.y2, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x1 / srcWidth, m_sourceRect.y2 / srcHeight},
853 // Compensate for D3D coordinates system
854 for(int i = 0; i < sizeof(vertex)/sizeof(vertex[0]); i++)
860 pD3DDev->SetTexture(0, m_SWTarget.Get());
864 pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
865 pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
866 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
867 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
868 pD3DDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
869 pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
873 pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE2X );
874 pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
875 pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
876 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
877 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
879 pD3DDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_ADDSIGNED );
880 pD3DDev->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT );
881 pD3DDev->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_SPECULAR );
882 pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
883 pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
885 pD3DDev->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
886 pD3DDev->SetTextureStageState( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
889 pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
890 pD3DDev->SetRenderState(D3DRS_LIGHTING, FALSE);
891 pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
892 pD3DDev->SetRenderState(D3DRS_STENCILENABLE, FALSE);
893 pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
894 pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
895 pD3DDev->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
897 pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, m_TextureFilter);
898 pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, m_TextureFilter);
899 pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
900 pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
902 pD3DDev->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1);
904 if (FAILED(hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, vertex, sizeof(VERTEX))))
905 CLog::Log(LOGERROR, __FUNCTION__": DrawPrimitiveUP failed. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
907 pD3DDev->SetTexture(0, NULL);
910 void CWinRenderer::RenderPS()
923 void CWinRenderer::Stage1()
927 m_colorShader->Render(m_sourceRect, g_graphicsContext.StereoCorrection(m_destRect),
928 CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast,
929 CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness,
931 (YUVBuffer*)m_VideoBuffers[m_iYV12RenderBuffer]);
935 // Switch the render target to the temporary destination
936 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
937 LPDIRECT3DSURFACE9 newRT, oldRT;
938 m_IntermediateTarget.GetSurfaceLevel(0, &newRT);
939 pD3DDevice->GetRenderTarget(0, &oldRT);
940 pD3DDevice->SetRenderTarget(0, newRT);
942 CRect srcRect(0.0f, 0.0f, m_sourceWidth, m_sourceHeight);
943 CRect rtRect(0.0f, 0.0f, m_sourceWidth, m_sourceHeight);
945 m_colorShader->Render(srcRect, rtRect,
946 CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast,
947 CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness,
949 (YUVBuffer*)m_VideoBuffers[m_iYV12RenderBuffer]);
951 // Restore the render target
952 pD3DDevice->SetRenderTarget(0, oldRT);
959 void CWinRenderer::Stage2()
963 // fixup stereo+dxva+hq scaling issue
964 if (m_renderMethod == RENDER_DXVA)
966 sourceRect.y1 = 0.0f;
967 sourceRect.y2 = m_sourceHeight;
968 sourceRect.x1 = 0.0f;
969 sourceRect.x2 = m_sourceWidth;
972 sourceRect = m_sourceRect;
974 m_scalerShader->Render(m_IntermediateTarget, m_sourceWidth, m_sourceHeight, m_destWidth, m_destHeight, sourceRect, g_graphicsContext.StereoCorrection(m_destRect));
977 void CWinRenderer::RenderProcessor(DWORD flags)
979 CSingleLock lock(g_graphicsContext);
986 destRect.y2 = m_sourceHeight;
988 destRect.x2 = m_sourceWidth;
991 destRect = g_graphicsContext.StereoCorrection(m_destRect);
993 DXVABuffer *image = (DXVABuffer*)m_VideoBuffers[m_iYV12RenderBuffer];
995 IDirect3DSurface9* target;
997 || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN
998 || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA)
1000 m_IntermediateTarget.GetSurfaceLevel(0, &target);
1004 if(FAILED(hr = g_Windowing.Get3DDevice()->GetRenderTarget(0, &target)))
1006 CLog::Log(LOGERROR, "CWinRenderer::RenderSurface - failed to get render target. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
1011 m_processor->Render(m_sourceRect, destRect, target, image->id, flags);
1019 else if ( g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN
1020 || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA)
1022 IDirect3DDevice9 *pD3DDev = g_Windowing.Get3DDevice();
1032 {destRect.x1 - 0.5f, destRect.y1 - 0.5f, 0.0f, m_destRect.x1 / m_destWidth, m_destRect.y1 / m_destHeight},
1033 {destRect.x2 - 0.5f, destRect.y1 - 0.5f, 0.0f, m_destRect.x2 / m_destWidth, m_destRect.y1 / m_destHeight},
1034 {destRect.x2 - 0.5f, destRect.y2 - 0.5f, 0.0f, m_destRect.x2 / m_destWidth, m_destRect.y2 / m_destHeight},
1035 {destRect.x1 - 0.5f, destRect.y2 - 0.5f, 0.0f, m_destRect.x1 / m_destWidth, m_destRect.y2 / m_destHeight},
1038 pD3DDev->SetTexture(0, m_IntermediateTarget.Get());
1040 pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
1041 pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
1042 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
1043 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
1044 pD3DDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
1045 pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
1047 pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1048 pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1050 pD3DDev->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1);
1052 if (FAILED(hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, vertex, sizeof(VERTEX))))
1053 CLog::Log(LOGERROR, __FUNCTION__": DrawPrimitiveUP failed. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
1055 pD3DDev->SetTexture(0, NULL);
1059 bool CWinRenderer::RenderCapture(CRenderCapture* capture)
1061 if (!m_bConfigured || m_NumYV12Buffers == 0)
1064 bool succeeded = false;
1066 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
1068 CRect saveSize = m_destRect;
1069 saveRotatedCoords();//backup current m_rotatedDestCoords
1071 m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight());
1072 syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords
1074 LPDIRECT3DSURFACE9 oldSurface;
1075 pD3DDevice->GetRenderTarget(0, &oldSurface);
1077 capture->BeginRender();
1078 if (capture->GetState() != CAPTURESTATE_FAILED)
1080 pD3DDevice->BeginScene();
1082 pD3DDevice->EndScene();
1083 capture->EndRender();
1087 pD3DDevice->SetRenderTarget(0, oldSurface);
1088 oldSurface->Release();
1090 m_destRect = saveSize;
1091 restoreRotatedCoords();//restores the previous state of the rotated dest coords
1096 //********************************************************************************************************
1097 // YV12 Texture creation, deletion, copying + clearing
1098 //********************************************************************************************************
1099 void CWinRenderer::DeleteYV12Texture(int index)
1101 CSingleLock lock(g_graphicsContext);
1102 if (m_VideoBuffers[index] != NULL)
1103 SAFE_DELETE(m_VideoBuffers[index]);
1104 m_NumYV12Buffers = 0;
1107 bool CWinRenderer::CreateYV12Texture(int index)
1109 CSingleLock lock(g_graphicsContext);
1110 DeleteYV12Texture(index);
1112 if (m_renderMethod == RENDER_DXVA)
1114 m_VideoBuffers[index] = new DXVABuffer();
1118 YUVBuffer *buf = new YUVBuffer();
1120 if (!buf->Create(m_format, m_sourceWidth, m_sourceHeight))
1122 CLog::Log(LOGERROR, __FUNCTION__" - Unable to create YV12 video texture %i", index);
1125 m_VideoBuffers[index] = buf;
1128 SVideoBuffer *buf = m_VideoBuffers[index];
1133 if(index == m_iYV12RenderBuffer)
1136 CLog::Log(LOGDEBUG, "created video buffer %i", index);
1140 bool CWinRenderer::Supports(EDEINTERLACEMODE mode)
1142 if(mode == VS_DEINTERLACEMODE_OFF
1143 || mode == VS_DEINTERLACEMODE_AUTO
1144 || mode == VS_DEINTERLACEMODE_FORCE)
1150 bool CWinRenderer::Supports(EINTERLACEMETHOD method)
1152 if(method == VS_INTERLACEMETHOD_AUTO)
1155 if (m_renderMethod == RENDER_DXVA)
1157 if(method == VS_INTERLACEMETHOD_DXVA_BOB
1158 || method == VS_INTERLACEMETHOD_DXVA_BEST)
1162 if(m_format != RENDER_FMT_DXVA
1163 && ( method == VS_INTERLACEMETHOD_DEINTERLACE
1164 || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
1165 || method == VS_INTERLACEMETHOD_SW_BLEND))
1171 bool CWinRenderer::Supports(ERENDERFEATURE feature)
1173 if(feature == RENDERFEATURE_BRIGHTNESS)
1176 if(feature == RENDERFEATURE_CONTRAST)
1179 if (feature == RENDERFEATURE_STRETCH ||
1180 feature == RENDERFEATURE_NONLINSTRETCH ||
1181 feature == RENDERFEATURE_CROP ||
1182 feature == RENDERFEATURE_ZOOM ||
1183 feature == RENDERFEATURE_VERTICAL_SHIFT ||
1184 feature == RENDERFEATURE_PIXEL_RATIO ||
1185 feature == RENDERFEATURE_POSTPROCESS)
1192 bool CWinRenderer::Supports(ESCALINGMETHOD method)
1194 if (m_renderMethod == RENDER_PS || m_renderMethod == RENDER_DXVA)
1196 if(m_renderMethod == RENDER_DXVA && method == VS_SCALINGMETHOD_DXVA_HARDWARE)
1199 if(m_deviceCaps.PixelShaderVersion >= D3DPS_VERSION(2, 0)
1200 && ( method == VS_SCALINGMETHOD_AUTO
1201 || (method == VS_SCALINGMETHOD_LINEAR && m_renderMethod == RENDER_PS) ))
1204 if(m_deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
1206 if(method == VS_SCALINGMETHOD_CUBIC
1207 || method == VS_SCALINGMETHOD_LANCZOS2
1208 || method == VS_SCALINGMETHOD_SPLINE36_FAST
1209 || method == VS_SCALINGMETHOD_LANCZOS3_FAST
1210 || method == VS_SCALINGMETHOD_SPLINE36
1211 || method == VS_SCALINGMETHOD_LANCZOS3)
1213 // if scaling is below level, avoid hq scaling
1214 float scaleX = fabs(((float)m_sourceWidth - m_destRect.Width())/m_sourceWidth)*100;
1215 float scaleY = fabs(((float)m_sourceHeight - m_destRect.Height())/m_sourceHeight)*100;
1216 int minScale = CSettings::Get().GetInt("videoplayer.hqscalers");
1217 if (scaleX < minScale && scaleY < minScale)
1223 else if(m_renderMethod == RENDER_SW)
1225 if(method == VS_SCALINGMETHOD_AUTO
1226 || method == VS_SCALINGMETHOD_NEAREST)
1228 if(method == VS_SCALINGMETHOD_LINEAR
1229 && m_deviceCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR
1230 && m_deviceCaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)
1236 EINTERLACEMETHOD CWinRenderer::AutoInterlaceMethod()
1238 if (m_renderMethod == RENDER_DXVA)
1239 return VS_INTERLACEMETHOD_DXVA_BOB;
1241 return VS_INTERLACEMETHOD_DEINTERLACE_HALF;
1244 unsigned int CWinRenderer::GetProcessorSize()
1246 if (m_format == RENDER_FMT_DXVA && m_processor)
1247 return m_processor->Size();
1252 //============================================
1254 YUVBuffer::~YUVBuffer()
1259 bool YUVBuffer::Create(ERenderFormat format, unsigned int width, unsigned int height)
1265 // Create the buffers in system memory and copy to D3DPOOL_DEFAULT:
1266 // - helps with lost devices. A buffer can be locked for dvdplayer without interfering.
1267 // - Dynamic + D3DPOOL_DEFAULT caused trouble for Intel i3 and some IGP. Bad sync/locking in the driver I suppose
1268 // and Present failed every second time for the second video played.
1269 // - this is what D3D9 does behind the scenes anyway
1272 case RENDER_FMT_YUV420P10:
1273 case RENDER_FMT_YUV420P16:
1275 if ( !planes[PLANE_Y].texture.Create(m_width , m_height , 1, 0, D3DFMT_L16, D3DPOOL_SYSTEMMEM)
1276 || !planes[PLANE_U].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L16, D3DPOOL_SYSTEMMEM)
1277 || !planes[PLANE_V].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L16, D3DPOOL_SYSTEMMEM))
1282 case RENDER_FMT_YUV420P:
1284 if ( !planes[PLANE_Y].texture.Create(m_width , m_height , 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM)
1285 || !planes[PLANE_U].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM)
1286 || !planes[PLANE_V].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM))
1291 case RENDER_FMT_NV12:
1293 if ( !planes[PLANE_Y].texture.Create(m_width , m_height , 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM)
1294 || !planes[PLANE_UV].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_A8L8, D3DPOOL_SYSTEMMEM))
1299 case RENDER_FMT_YUYV422:
1301 if ( !planes[PLANE_Y].texture.Create(m_width >> 1 , m_height , 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM))
1306 case RENDER_FMT_UYVY422:
1308 if ( !planes[PLANE_Y].texture.Create(m_width >> 1 , m_height , 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM))
1321 void YUVBuffer::Release()
1323 for(unsigned i = 0; i < m_activeplanes; i++)
1325 planes[i].texture.Release();
1326 memset(&planes[i].rect, 0, sizeof(planes[i].rect));
1330 void YUVBuffer::StartRender()
1332 for(unsigned i = 0; i < m_activeplanes; i++)
1334 if(planes[i].texture.Get() && planes[i].rect.pBits)
1335 if (!planes[i].texture.UnlockRect(0))
1336 CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock texture %d", i);
1337 memset(&planes[i].rect, 0, sizeof(planes[i].rect));
1341 void YUVBuffer::StartDecode()
1343 for(unsigned i = 0; i < m_activeplanes; i++)
1345 if(planes[i].texture.Get()
1346 && planes[i].texture.LockRect(0, &planes[i].rect, NULL, D3DLOCK_DISCARD) == false)
1348 memset(&planes[i].rect, 0, sizeof(planes[i].rect));
1349 CLog::Log(LOGERROR, __FUNCTION__" - failed to lock texture %d into memory", i);
1354 void YUVBuffer::Clear()
1356 // Set Y to 0 and U,V to 128 (RGB 0,0,0) to avoid visual artifacts at the start of playback
1360 case RENDER_FMT_YUV420P16:
1362 wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height / 2);
1363 wmemset((wchar_t*)planes[PLANE_U].rect.pBits, 32768, planes[PLANE_U].rect.Pitch * (m_height/2) / 2);
1364 wmemset((wchar_t*)planes[PLANE_V].rect.pBits, 32768, planes[PLANE_V].rect.Pitch * (m_height/2) / 2);
1367 case RENDER_FMT_YUV420P10:
1369 wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height / 2);
1370 wmemset((wchar_t*)planes[PLANE_U].rect.pBits, 512, planes[PLANE_U].rect.Pitch * (m_height/2) / 2);
1371 wmemset((wchar_t*)planes[PLANE_V].rect.pBits, 512, planes[PLANE_V].rect.Pitch * (m_height/2) / 2);
1374 case RENDER_FMT_YUV420P:
1376 memset(planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height);
1377 memset(planes[PLANE_U].rect.pBits, 128, planes[PLANE_U].rect.Pitch * (m_height/2));
1378 memset(planes[PLANE_V].rect.pBits, 128, planes[PLANE_V].rect.Pitch * (m_height/2));
1381 case RENDER_FMT_NV12:
1383 memset(planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height);
1384 memset(planes[PLANE_UV].rect.pBits, 128, planes[PLANE_U].rect.Pitch * (m_height/2));
1387 // YUY2, UYVY: wmemset to set a 16bit pattern, byte-swapped because x86 is LE
1388 case RENDER_FMT_YUYV422:
1390 wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0x8000, planes[PLANE_Y].rect.Pitch / 2 * m_height);
1393 case RENDER_FMT_UYVY422:
1395 wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0x0080, planes[PLANE_Y].rect.Pitch / 2 * m_height);
1403 //==================================
1405 DXVABuffer::~DXVABuffer()
1410 void DXVABuffer::Release()
1415 void DXVABuffer::StartDecode()