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);
397 m_iRequestedMethod = CSettings::Get().GetInt("videoplayer.rendermethod");
399 if (g_advancedSettings.m_DXVAForceProcessorRenderer || m_iRequestedMethod == RENDER_METHOD_DXVA
400 || m_iRequestedMethod == RENDER_METHOD_DXVAHD)
402 if (m_iRequestedMethod != RENDER_METHOD_DXVA && CSysInfo::IsWindowsVersionAtLeast(CSysInfo::WindowsVersionWin7))
404 m_processor = new DXVA::CProcessorHD();
405 if (!m_processor->PreInit())
407 CLog::Log(LOGNOTICE, "CWinRenderer::Preinit - could not init DXVA-HD processor - skipping");
408 SAFE_DELETE(m_processor);
409 m_processor = new DXVA::CProcessor();
415 m_processor = new DXVA::CProcessor();
417 if (!m_processor->PreInit())
418 CLog::Log(LOGNOTICE, "CWinRenderer::Preinit - could not init DXVA2 processor - skipping");
423 if (g_Windowing.IsTextureFormatOk(D3DFMT_L16, 0))
425 m_formats.push_back(RENDER_FMT_YUV420P10);
426 m_formats.push_back(RENDER_FMT_YUV420P16);
428 m_formats.push_back(RENDER_FMT_NV12);
429 m_formats.push_back(RENDER_FMT_YUYV422);
430 m_formats.push_back(RENDER_FMT_UYVY422);
435 void CWinRenderer::UnInit()
437 CSingleLock lock(g_graphicsContext);
439 if (m_SWTarget.Get())
440 m_SWTarget.Release();
442 if (m_IntermediateTarget.Get())
443 m_IntermediateTarget.Release();
445 SAFE_DELETE(m_colorShader);
446 SAFE_DELETE(m_scalerShader);
448 m_bConfigured = false;
449 m_bFilterInitialized = false;
451 for(int i = 0; i < NUM_BUFFERS; i++)
452 DeleteYV12Texture(i);
454 m_NumYV12Buffers = 0;
458 m_dllSwScale->sws_freeContext(m_sw_scale_ctx);
459 m_sw_scale_ctx = NULL;
461 SAFE_DELETE(m_dllSwScale);
465 m_processor->UnInit();
466 SAFE_DELETE(m_processor);
470 bool CWinRenderer::CreateIntermediateRenderTarget(unsigned int width, unsigned int height)
472 // Initialize a render target for intermediate rendering
473 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
474 D3DFORMAT format = D3DFMT_X8R8G8B8;
475 DWORD usage = D3DUSAGE_RENDERTARGET;
477 if (m_renderMethod == RENDER_DXVA) format = D3DFMT_X8R8G8B8;
478 else if (g_Windowing.IsTextureFormatOk(D3DFMT_A2R10G10B10, usage)) format = D3DFMT_A2R10G10B10;
479 else if (g_Windowing.IsTextureFormatOk(D3DFMT_A2B10G10R10, usage)) format = D3DFMT_A2B10G10R10;
480 else if (g_Windowing.IsTextureFormatOk(D3DFMT_A8R8G8B8, usage)) format = D3DFMT_A8R8G8B8;
481 else if (g_Windowing.IsTextureFormatOk(D3DFMT_A8B8G8R8, usage)) format = D3DFMT_A8B8G8R8;
482 else if (g_Windowing.IsTextureFormatOk(D3DFMT_X8R8G8B8, usage)) format = D3DFMT_X8R8G8B8;
483 else if (g_Windowing.IsTextureFormatOk(D3DFMT_X8B8G8R8, usage)) format = D3DFMT_X8B8G8R8;
484 else if (g_Windowing.IsTextureFormatOk(D3DFMT_R8G8B8, usage)) format = D3DFMT_R8G8B8;
486 // don't create new one if it exists with requested size and format
487 if ( m_IntermediateTarget.Get() && m_IntermediateTarget.GetFormat() == format
488 && m_IntermediateTarget.GetWidth() == width && m_IntermediateTarget.GetHeight() == height)
491 if (m_IntermediateTarget.Get())
492 m_IntermediateTarget.Release();
494 CLog::Log(LOGDEBUG, __FUNCTION__": format %i", format);
496 if(!m_IntermediateTarget.Create(width, height, 1, usage, format, D3DPOOL_DEFAULT))
498 CLog::Log(LOGERROR, __FUNCTION__": intermediate render target creation failed.", format);
504 void CWinRenderer::SelectSWVideoFilter()
506 switch (m_scalingMethod)
508 case VS_SCALINGMETHOD_AUTO:
509 case VS_SCALINGMETHOD_LINEAR:
510 if (Supports(VS_SCALINGMETHOD_LINEAR))
512 m_TextureFilter = D3DTEXF_LINEAR;
515 // fall through for fallback
516 case VS_SCALINGMETHOD_NEAREST:
518 m_TextureFilter = D3DTEXF_POINT;
523 void CWinRenderer::SelectPSVideoFilter()
525 m_bUseHQScaler = false;
527 switch (m_scalingMethod)
529 case VS_SCALINGMETHOD_NEAREST:
530 case VS_SCALINGMETHOD_LINEAR:
533 case VS_SCALINGMETHOD_CUBIC:
534 case VS_SCALINGMETHOD_LANCZOS2:
535 case VS_SCALINGMETHOD_SPLINE36_FAST:
536 case VS_SCALINGMETHOD_LANCZOS3_FAST:
537 m_bUseHQScaler = true;
540 case VS_SCALINGMETHOD_SPLINE36:
541 case VS_SCALINGMETHOD_LANCZOS3:
542 m_bUseHQScaler = true;
545 case VS_SCALINGMETHOD_SINC8:
546 case VS_SCALINGMETHOD_NEDI:
547 CLog::Log(LOGERROR, "D3D: TODO: This scaler has not yet been implemented");
550 case VS_SCALINGMETHOD_BICUBIC_SOFTWARE:
551 case VS_SCALINGMETHOD_LANCZOS_SOFTWARE:
552 case VS_SCALINGMETHOD_SINC_SOFTWARE:
553 CLog::Log(LOGERROR, "D3D: TODO: Software scaling has not yet been implemented");
560 if (m_scalingMethod == VS_SCALINGMETHOD_AUTO)
562 bool scaleSD = m_sourceHeight < 720 && m_sourceWidth < 1280;
563 bool scaleUp = (int)m_sourceHeight < g_graphicsContext.GetHeight() && (int)m_sourceWidth < g_graphicsContext.GetWidth();
564 bool scaleFps = m_fps < (g_advancedSettings.m_videoAutoScaleMaxFps + 0.01f);
566 if (m_renderMethod == RENDER_DXVA)
568 m_scalingMethod = VS_SCALINGMETHOD_DXVA_HARDWARE;
569 m_bUseHQScaler = false;
571 else if (scaleSD && scaleUp && scaleFps && Supports(VS_SCALINGMETHOD_LANCZOS3_FAST))
573 m_scalingMethod = VS_SCALINGMETHOD_LANCZOS3_FAST;
574 m_bUseHQScaler = true;
579 void CWinRenderer::UpdatePSVideoFilter()
581 SAFE_DELETE(m_scalerShader);
585 // First try the more efficient two pass convolution scaler
586 m_scalerShader = new CConvolutionShaderSeparable();
588 if (!m_scalerShader->Create(m_scalingMethod))
590 SAFE_DELETE(m_scalerShader);
591 CLog::Log(LOGNOTICE, __FUNCTION__": two pass convolution shader init problem, falling back to one pass.");
594 // Fallback on the one pass version
595 if (m_scalerShader == NULL)
597 m_scalerShader = new CConvolutionShader1Pass();
599 if (!m_scalerShader->Create(m_scalingMethod))
601 SAFE_DELETE(m_scalerShader);
602 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(34400), g_localizeStrings.Get(34401));
603 m_bUseHQScaler = false;
608 if (m_bUseHQScaler && !CreateIntermediateRenderTarget(m_sourceWidth, m_sourceHeight))
610 SAFE_DELETE(m_scalerShader);
611 m_bUseHQScaler = false;
614 SAFE_DELETE(m_colorShader);
616 if (m_renderMethod == RENDER_DXVA)
618 // we'd use m_IntermediateTarget as rendering target for possible anaglyph stereo with dxva processor.
620 CreateIntermediateRenderTarget(m_destWidth, m_destHeight);
622 // When using DXVA, we are already setup at this point, color shader is not needed
628 m_colorShader = new CYUV2RGBShader();
629 if (!m_colorShader->Create(m_sourceWidth, m_sourceHeight, m_format))
631 // Try again after disabling the HQ scaler and freeing its resources
632 m_IntermediateTarget.Release();
633 SAFE_DELETE(m_scalerShader);
634 SAFE_DELETE(m_colorShader);
635 m_bUseHQScaler = false;
639 if (!m_bUseHQScaler) //fallback from HQ scalers and multipass creation above
641 m_colorShader = new CYUV2RGBShader();
642 if (!m_colorShader->Create(m_sourceWidth, m_sourceHeight, m_format))
643 SAFE_DELETE(m_colorShader);
644 // we're in big trouble - should fallback on D3D accelerated or sw method
648 void CWinRenderer::UpdateVideoFilter()
650 if (m_scalingMethodGui == CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod && m_bFilterInitialized)
653 m_bFilterInitialized = true;
655 m_scalingMethodGui = CMediaSettings::Get().GetCurrentVideoSettings().m_ScalingMethod;
656 m_scalingMethod = m_scalingMethodGui;
658 if (!Supports(m_scalingMethod))
660 CLog::Log(LOGWARNING, __FUNCTION__" - chosen scaling method %d is not supported by renderer", (int)m_scalingMethod);
661 m_scalingMethod = VS_SCALINGMETHOD_AUTO;
664 switch(m_renderMethod)
667 SelectSWVideoFilter();
672 SelectPSVideoFilter();
673 UpdatePSVideoFilter();
681 void CWinRenderer::Render(DWORD flags)
683 if (m_renderMethod == RENDER_DXVA)
687 g_Windowing.FlushGPU();
688 CWinRenderer::RenderProcessor(flags);
694 // Optimize later? we could get by with bilinear under some circumstances
696 || !g_graphicsContext.IsFullScreenVideo()
697 || g_graphicsContext.IsCalibrating()
698 || (m_destRect.Width() == m_sourceWidth && m_destRect.Height() == m_sourceHeight))
700 CSingleLock lock(g_graphicsContext);
702 // Don't need a stencil/depth buffer and a buffer smaller than the render target causes D3D complaints and nVidia issues
703 // Save & restore when we're done.
704 LPDIRECT3DSURFACE9 pZBuffer;
705 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
706 pD3DDevice->GetDepthStencilSurface(&pZBuffer);
707 pD3DDevice->SetDepthStencilSurface(NULL);
709 if (m_renderMethod == RENDER_SW)
711 else if (m_renderMethod == RENDER_PS)
714 pD3DDevice->SetDepthStencilSurface(pZBuffer);
718 void CWinRenderer::RenderSW()
720 enum PixelFormat format = PixelFormatFromFormat(m_format);
722 // 1. convert yuv to rgb
723 m_sw_scale_ctx = m_dllSwScale->sws_getCachedContext(m_sw_scale_ctx,
724 m_sourceWidth, m_sourceHeight, format,
725 m_sourceWidth, m_sourceHeight, PIX_FMT_BGRA,
726 SWS_FAST_BILINEAR | SwScaleCPUFlags(), NULL, NULL, NULL);
728 YUVBuffer* buf = (YUVBuffer*)m_VideoBuffers[m_iYV12RenderBuffer];
730 D3DLOCKED_RECT srclr[MAX_PLANES];
731 uint8_t *src[MAX_PLANES];
732 int srcStride[MAX_PLANES];
734 for (unsigned int idx = 0; idx < buf->GetActivePlanes(); idx++)
736 if(!(buf->planes[idx].texture.LockRect(0, &srclr[idx], NULL, D3DLOCK_READONLY)))
737 CLog::Log(LOGERROR, __FUNCTION__" - failed to lock yuv textures into memory");
740 src[idx] = (uint8_t*)srclr[idx].pBits;
741 srcStride[idx] = srclr[idx].Pitch;
745 D3DLOCKED_RECT destlr = {0,0};
746 if (!m_SWTarget.LockRect(0, &destlr, NULL, D3DLOCK_DISCARD))
747 CLog::Log(LOGERROR, __FUNCTION__" - failed to lock swtarget texture into memory");
749 uint8_t *dst[] = { (uint8_t*) destlr.pBits, 0, 0, 0 };
750 int dstStride[] = { destlr.Pitch, 0, 0, 0 };
752 m_dllSwScale->sws_scale(m_sw_scale_ctx, src, srcStride, 0, m_sourceHeight, dst, dstStride);
754 for (unsigned int idx = 0; idx < buf->GetActivePlanes(); idx++)
755 if(!(buf->planes[idx].texture.UnlockRect(0)))
756 CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock yuv textures");
758 if (!m_SWTarget.UnlockRect(0))
759 CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock swtarget texture");
761 // 2. scale to display
763 // Don't know where this martian comes from but it can happen in the initial frames of a video
764 if ((m_destRect.x1 < 0 && m_destRect.x2 < 0) || (m_destRect.y1 < 0 && m_destRect.y2 < 0))
767 ScaleFixedPipeline();
771 Code kept for reference, as a basis to re-enable StretchRect and
772 do the color conversion with it.
773 See IDirect3D9::CheckDeviceFormat() for support of non-standard fourcc textures
774 and IDirect3D9::CheckDeviceFormatConversion for color conversion support
776 void CWinRenderer::ScaleStretchRect()
778 // Test HW scaler support. StretchRect is slightly faster than drawing a quad.
779 // If linear filtering is not supported, drop back to quads, as most HW has linear filtering for quads.
780 //if(m_deviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES
781 //&& m_deviceCaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MINFLINEAR
782 //&& m_deviceCaps.StretchRectFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)
784 // m_StretchRectSupported = true;
787 CRect sourceRect = m_sourceRect;
788 CRect destRect = m_destRect;
790 D3DSURFACE_DESC desc;
791 if (FAILED(target->GetDesc(&desc)))
792 CLog::Log(LOGERROR, "CWinRenderer::Render - failed to get back buffer description");
793 CRect tgtRect(0, 0, desc.Width, desc.Height);
795 // Need to manipulate the coordinates since StretchRect doesn't accept off-screen coordinates.
796 CWIN32Util::CropSource(sourceRect, destRect, tgtRect);
798 RECT srcRect = { sourceRect.x1, sourceRect.y1, sourceRect.x2, sourceRect.y2 };
799 IDirect3DSurface9* source;
800 if(!m_SWTarget.GetSurfaceLevel(0, &source))
801 CLog::Log(LOGERROR, "CWinRenderer::Render - failed to get source");
803 RECT dstRect = { destRect.x1, destRect.y1, destRect.x2, destRect.y2 };
804 IDirect3DSurface9* target;
805 if(FAILED(g_Windowing.Get3DDevice()->GetRenderTarget(0, &target)))
806 CLog::Log(LOGERROR, "CWinRenderer::Render - failed to get back buffer");
809 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
811 if(FAILED(hr = pD3DDevice->StretchRect(source, &srcRect, target, &dstRect, m_TextureFilter)))
812 CLog::Log(LOGERROR, __FUNCTION__" - StretchRect failed (0x%08X)", hr);
819 void CWinRenderer::ScaleFixedPipeline()
822 IDirect3DDevice9 *pD3DDev = g_Windowing.Get3DDevice();
823 D3DSURFACE_DESC srcDesc;
824 if (FAILED(hr = m_SWTarget.Get()->GetLevelDesc(0, &srcDesc)))
825 CLog::Log(LOGERROR, __FUNCTION__": GetLevelDesc failed. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
827 float srcWidth = (float)srcDesc.Width;
828 float srcHeight = (float)srcDesc.Height;
830 bool cbcontrol = (CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast != 50.0f || CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness != 50.0f);
831 unsigned int contrast = (unsigned int)(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast *.01f * 255.0f); // we have to divide by two here/multiply by two later
832 unsigned int brightness = (unsigned int)(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * .01f * 255.0f);
834 D3DCOLOR diffuse = D3DCOLOR_ARGB(255, contrast, contrast, contrast);
835 D3DCOLOR specular = D3DCOLOR_ARGB(255, brightness, brightness, brightness);
845 // Vertex format ignores viewport offsets, so correct for that here
846 CRect dest = g_graphicsContext.StereoCorrection(m_destRect);
850 {dest.x1, dest.y1, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x1 / srcWidth, m_sourceRect.y1 / srcHeight},
851 {dest.x2, dest.y1, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x2 / srcWidth, m_sourceRect.y1 / srcHeight},
852 {dest.x2, dest.y2, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x2 / srcWidth, m_sourceRect.y2 / srcHeight},
853 {dest.x1, dest.y2, 0.0f, 1.0f, diffuse, specular, m_sourceRect.x1 / srcWidth, m_sourceRect.y2 / srcHeight},
856 // Compensate for D3D coordinates system
857 for(int i = 0; i < sizeof(vertex)/sizeof(vertex[0]); i++)
863 pD3DDev->SetTexture(0, m_SWTarget.Get());
867 pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
868 pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
869 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
870 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
871 pD3DDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
872 pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
876 pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE2X );
877 pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
878 pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
879 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
880 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE );
882 pD3DDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_ADDSIGNED );
883 pD3DDev->SetTextureStageState( 1, D3DTSS_COLORARG1, D3DTA_CURRENT );
884 pD3DDev->SetTextureStageState( 1, D3DTSS_COLORARG2, D3DTA_SPECULAR );
885 pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
886 pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAARG1, D3DTA_CURRENT );
888 pD3DDev->SetTextureStageState( 2, D3DTSS_COLOROP, D3DTOP_DISABLE );
889 pD3DDev->SetTextureStageState( 2, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
892 pD3DDev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
893 pD3DDev->SetRenderState(D3DRS_LIGHTING, FALSE);
894 pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
895 pD3DDev->SetRenderState(D3DRS_STENCILENABLE, FALSE);
896 pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
897 pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
898 pD3DDev->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
900 pD3DDev->SetSamplerState(0, D3DSAMP_MAGFILTER, m_TextureFilter);
901 pD3DDev->SetSamplerState(0, D3DSAMP_MINFILTER, m_TextureFilter);
902 pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
903 pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
905 pD3DDev->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX1);
907 if (FAILED(hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, vertex, sizeof(VERTEX))))
908 CLog::Log(LOGERROR, __FUNCTION__": DrawPrimitiveUP failed. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
910 pD3DDev->SetTexture(0, NULL);
913 void CWinRenderer::RenderPS()
926 void CWinRenderer::Stage1()
930 m_colorShader->Render(m_sourceRect, g_graphicsContext.StereoCorrection(m_destRect),
931 CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast,
932 CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness,
934 (YUVBuffer*)m_VideoBuffers[m_iYV12RenderBuffer]);
938 // Switch the render target to the temporary destination
939 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
940 LPDIRECT3DSURFACE9 newRT, oldRT;
941 m_IntermediateTarget.GetSurfaceLevel(0, &newRT);
942 pD3DDevice->GetRenderTarget(0, &oldRT);
943 pD3DDevice->SetRenderTarget(0, newRT);
945 CRect srcRect(0.0f, 0.0f, m_sourceWidth, m_sourceHeight);
946 CRect rtRect(0.0f, 0.0f, m_sourceWidth, m_sourceHeight);
948 m_colorShader->Render(srcRect, rtRect,
949 CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast,
950 CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness,
952 (YUVBuffer*)m_VideoBuffers[m_iYV12RenderBuffer]);
954 // Restore the render target
955 pD3DDevice->SetRenderTarget(0, oldRT);
957 // MSDN says: Setting a new render target will cause the viewport
958 // to be set to the full size of the new render target.
959 // So we need restore our viewport
960 g_Windowing.RestoreViewPort();
967 void CWinRenderer::Stage2()
971 // fixup stereo+dxva+hq scaling issue
972 if (m_renderMethod == RENDER_DXVA)
974 sourceRect.y1 = 0.0f;
975 sourceRect.y2 = m_sourceHeight;
976 sourceRect.x1 = 0.0f;
977 sourceRect.x2 = m_sourceWidth;
980 sourceRect = m_sourceRect;
982 m_scalerShader->Render(m_IntermediateTarget, m_sourceWidth, m_sourceHeight, m_destWidth, m_destHeight, sourceRect, g_graphicsContext.StereoCorrection(m_destRect));
985 void CWinRenderer::RenderProcessor(DWORD flags)
987 CSingleLock lock(g_graphicsContext);
994 destRect.y2 = m_sourceHeight;
996 destRect.x2 = m_sourceWidth;
999 destRect = g_graphicsContext.StereoCorrection(m_destRect);
1001 DXVABuffer *image = (DXVABuffer*)m_VideoBuffers[m_iYV12RenderBuffer];
1003 IDirect3DSurface9* target;
1005 || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN
1006 || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA)
1008 m_IntermediateTarget.GetSurfaceLevel(0, &target);
1012 if(FAILED(hr = g_Windowing.Get3DDevice()->GetRenderTarget(0, &target)))
1014 CLog::Log(LOGERROR, "CWinRenderer::RenderSurface - failed to get render target. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
1019 m_processor->Render(m_sourceRect, destRect, target, image->id, flags);
1027 else if ( g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_RED_CYAN
1028 || g_graphicsContext.GetStereoMode() == RENDER_STEREO_MODE_ANAGLYPH_GREEN_MAGENTA)
1030 IDirect3DDevice9 *pD3DDev = g_Windowing.Get3DDevice();
1040 {destRect.x1 - 0.5f, destRect.y1 - 0.5f, 0.0f, m_destRect.x1 / m_destWidth, m_destRect.y1 / m_destHeight},
1041 {destRect.x2 - 0.5f, destRect.y1 - 0.5f, 0.0f, m_destRect.x2 / m_destWidth, m_destRect.y1 / m_destHeight},
1042 {destRect.x2 - 0.5f, destRect.y2 - 0.5f, 0.0f, m_destRect.x2 / m_destWidth, m_destRect.y2 / m_destHeight},
1043 {destRect.x1 - 0.5f, destRect.y2 - 0.5f, 0.0f, m_destRect.x1 / m_destWidth, m_destRect.y2 / m_destHeight},
1046 pD3DDev->SetTexture(0, m_IntermediateTarget.Get());
1048 pD3DDev->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
1049 pD3DDev->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
1050 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
1051 pD3DDev->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
1052 pD3DDev->SetTextureStageState( 1, D3DTSS_COLOROP, D3DTOP_DISABLE );
1053 pD3DDev->SetTextureStageState( 1, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
1055 pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1056 pD3DDev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1058 pD3DDev->SetFVF(D3DFVF_XYZ | D3DFVF_TEX1);
1060 if (FAILED(hr = pD3DDev->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, vertex, sizeof(VERTEX))))
1061 CLog::Log(LOGERROR, __FUNCTION__": DrawPrimitiveUP failed. %s", CRenderSystemDX::GetErrorDescription(hr).c_str());
1063 pD3DDev->SetTexture(0, NULL);
1067 bool CWinRenderer::RenderCapture(CRenderCapture* capture)
1069 if (!m_bConfigured || m_NumYV12Buffers == 0)
1072 bool succeeded = false;
1074 LPDIRECT3DDEVICE9 pD3DDevice = g_Windowing.Get3DDevice();
1076 CRect saveSize = m_destRect;
1077 saveRotatedCoords();//backup current m_rotatedDestCoords
1079 m_destRect.SetRect(0, 0, (float)capture->GetWidth(), (float)capture->GetHeight());
1080 syncDestRectToRotatedPoints();//syncs the changed destRect to m_rotatedDestCoords
1082 LPDIRECT3DSURFACE9 oldSurface;
1083 pD3DDevice->GetRenderTarget(0, &oldSurface);
1085 capture->BeginRender();
1086 if (capture->GetState() != CAPTURESTATE_FAILED)
1088 pD3DDevice->BeginScene();
1090 pD3DDevice->EndScene();
1091 capture->EndRender();
1095 pD3DDevice->SetRenderTarget(0, oldSurface);
1096 oldSurface->Release();
1098 m_destRect = saveSize;
1099 restoreRotatedCoords();//restores the previous state of the rotated dest coords
1104 //********************************************************************************************************
1105 // YV12 Texture creation, deletion, copying + clearing
1106 //********************************************************************************************************
1107 void CWinRenderer::DeleteYV12Texture(int index)
1109 CSingleLock lock(g_graphicsContext);
1110 if (m_VideoBuffers[index] != NULL)
1111 SAFE_DELETE(m_VideoBuffers[index]);
1112 m_NumYV12Buffers = 0;
1115 bool CWinRenderer::CreateYV12Texture(int index)
1117 CSingleLock lock(g_graphicsContext);
1118 DeleteYV12Texture(index);
1120 if (m_renderMethod == RENDER_DXVA)
1122 m_VideoBuffers[index] = new DXVABuffer();
1126 YUVBuffer *buf = new YUVBuffer();
1128 if (!buf->Create(m_format, m_sourceWidth, m_sourceHeight))
1130 CLog::Log(LOGERROR, __FUNCTION__" - Unable to create YV12 video texture %i", index);
1133 m_VideoBuffers[index] = buf;
1136 SVideoBuffer *buf = m_VideoBuffers[index];
1141 if(index == m_iYV12RenderBuffer)
1144 CLog::Log(LOGDEBUG, "created video buffer %i", index);
1148 bool CWinRenderer::Supports(EDEINTERLACEMODE mode)
1150 if(mode == VS_DEINTERLACEMODE_OFF
1151 || mode == VS_DEINTERLACEMODE_AUTO
1152 || mode == VS_DEINTERLACEMODE_FORCE)
1158 bool CWinRenderer::Supports(EINTERLACEMETHOD method)
1160 if(method == VS_INTERLACEMETHOD_AUTO)
1163 if (m_renderMethod == RENDER_DXVA)
1165 if(method == VS_INTERLACEMETHOD_DXVA_BOB
1166 || method == VS_INTERLACEMETHOD_DXVA_BEST)
1170 if(m_format != RENDER_FMT_DXVA
1171 && ( method == VS_INTERLACEMETHOD_DEINTERLACE
1172 || method == VS_INTERLACEMETHOD_DEINTERLACE_HALF
1173 || method == VS_INTERLACEMETHOD_SW_BLEND))
1179 bool CWinRenderer::Supports(ERENDERFEATURE feature)
1181 if(feature == RENDERFEATURE_BRIGHTNESS)
1184 if(feature == RENDERFEATURE_CONTRAST)
1187 if (feature == RENDERFEATURE_STRETCH ||
1188 feature == RENDERFEATURE_NONLINSTRETCH ||
1189 feature == RENDERFEATURE_CROP ||
1190 feature == RENDERFEATURE_ZOOM ||
1191 feature == RENDERFEATURE_VERTICAL_SHIFT ||
1192 feature == RENDERFEATURE_PIXEL_RATIO ||
1193 feature == RENDERFEATURE_POSTPROCESS)
1200 bool CWinRenderer::Supports(ESCALINGMETHOD method)
1202 if (m_renderMethod == RENDER_PS || m_renderMethod == RENDER_DXVA)
1204 if(m_renderMethod == RENDER_DXVA && method == VS_SCALINGMETHOD_DXVA_HARDWARE)
1207 if(m_deviceCaps.PixelShaderVersion >= D3DPS_VERSION(2, 0)
1208 && ( method == VS_SCALINGMETHOD_AUTO
1209 || (method == VS_SCALINGMETHOD_LINEAR && m_renderMethod == RENDER_PS) ))
1212 if(m_deviceCaps.PixelShaderVersion >= D3DPS_VERSION(3, 0))
1214 if(method == VS_SCALINGMETHOD_CUBIC
1215 || method == VS_SCALINGMETHOD_LANCZOS2
1216 || method == VS_SCALINGMETHOD_SPLINE36_FAST
1217 || method == VS_SCALINGMETHOD_LANCZOS3_FAST
1218 || method == VS_SCALINGMETHOD_SPLINE36
1219 || method == VS_SCALINGMETHOD_LANCZOS3)
1221 // if scaling is below level, avoid hq scaling
1222 float scaleX = fabs(((float)m_sourceWidth - m_destRect.Width())/m_sourceWidth)*100;
1223 float scaleY = fabs(((float)m_sourceHeight - m_destRect.Height())/m_sourceHeight)*100;
1224 int minScale = CSettings::Get().GetInt("videoplayer.hqscalers");
1225 if (scaleX < minScale && scaleY < minScale)
1231 else if(m_renderMethod == RENDER_SW)
1233 if(method == VS_SCALINGMETHOD_AUTO
1234 || method == VS_SCALINGMETHOD_NEAREST)
1236 if(method == VS_SCALINGMETHOD_LINEAR
1237 && m_deviceCaps.TextureFilterCaps & D3DPTFILTERCAPS_MINFLINEAR
1238 && m_deviceCaps.TextureFilterCaps & D3DPTFILTERCAPS_MAGFLINEAR)
1244 EINTERLACEMETHOD CWinRenderer::AutoInterlaceMethod()
1246 if (m_renderMethod == RENDER_DXVA)
1247 return VS_INTERLACEMETHOD_DXVA_BOB;
1249 return VS_INTERLACEMETHOD_DEINTERLACE_HALF;
1252 unsigned int CWinRenderer::GetProcessorSize()
1254 if (m_format == RENDER_FMT_DXVA && m_processor)
1255 return m_processor->Size();
1260 //============================================
1262 YUVBuffer::~YUVBuffer()
1267 bool YUVBuffer::Create(ERenderFormat format, unsigned int width, unsigned int height)
1273 // Create the buffers in system memory and copy to D3DPOOL_DEFAULT:
1274 // - helps with lost devices. A buffer can be locked for dvdplayer without interfering.
1275 // - Dynamic + D3DPOOL_DEFAULT caused trouble for Intel i3 and some IGP. Bad sync/locking in the driver I suppose
1276 // and Present failed every second time for the second video played.
1277 // - this is what D3D9 does behind the scenes anyway
1280 case RENDER_FMT_YUV420P10:
1281 case RENDER_FMT_YUV420P16:
1283 if ( !planes[PLANE_Y].texture.Create(m_width , m_height , 1, 0, D3DFMT_L16, D3DPOOL_SYSTEMMEM)
1284 || !planes[PLANE_U].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L16, D3DPOOL_SYSTEMMEM)
1285 || !planes[PLANE_V].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L16, D3DPOOL_SYSTEMMEM))
1290 case RENDER_FMT_YUV420P:
1292 if ( !planes[PLANE_Y].texture.Create(m_width , m_height , 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM)
1293 || !planes[PLANE_U].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM)
1294 || !planes[PLANE_V].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM))
1299 case RENDER_FMT_NV12:
1301 if ( !planes[PLANE_Y].texture.Create(m_width , m_height , 1, 0, D3DFMT_L8, D3DPOOL_SYSTEMMEM)
1302 || !planes[PLANE_UV].texture.Create(m_width / 2, m_height / 2, 1, 0, D3DFMT_A8L8, D3DPOOL_SYSTEMMEM))
1307 case RENDER_FMT_YUYV422:
1309 if ( !planes[PLANE_Y].texture.Create(m_width >> 1 , m_height , 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM))
1314 case RENDER_FMT_UYVY422:
1316 if ( !planes[PLANE_Y].texture.Create(m_width >> 1 , m_height , 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM))
1329 void YUVBuffer::Release()
1331 for(unsigned i = 0; i < m_activeplanes; i++)
1333 planes[i].texture.Release();
1334 memset(&planes[i].rect, 0, sizeof(planes[i].rect));
1338 void YUVBuffer::StartRender()
1340 for(unsigned i = 0; i < m_activeplanes; i++)
1342 if(planes[i].texture.Get() && planes[i].rect.pBits)
1343 if (!planes[i].texture.UnlockRect(0))
1344 CLog::Log(LOGERROR, __FUNCTION__" - failed to unlock texture %d", i);
1345 memset(&planes[i].rect, 0, sizeof(planes[i].rect));
1349 void YUVBuffer::StartDecode()
1351 for(unsigned i = 0; i < m_activeplanes; i++)
1353 if(planes[i].texture.Get()
1354 && planes[i].texture.LockRect(0, &planes[i].rect, NULL, D3DLOCK_DISCARD) == false)
1356 memset(&planes[i].rect, 0, sizeof(planes[i].rect));
1357 CLog::Log(LOGERROR, __FUNCTION__" - failed to lock texture %d into memory", i);
1362 void YUVBuffer::Clear()
1364 // Set Y to 0 and U,V to 128 (RGB 0,0,0) to avoid visual artifacts at the start of playback
1368 case RENDER_FMT_YUV420P16:
1370 wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height / 2);
1371 wmemset((wchar_t*)planes[PLANE_U].rect.pBits, 32768, planes[PLANE_U].rect.Pitch * (m_height/2) / 2);
1372 wmemset((wchar_t*)planes[PLANE_V].rect.pBits, 32768, planes[PLANE_V].rect.Pitch * (m_height/2) / 2);
1375 case RENDER_FMT_YUV420P10:
1377 wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height / 2);
1378 wmemset((wchar_t*)planes[PLANE_U].rect.pBits, 512, planes[PLANE_U].rect.Pitch * (m_height/2) / 2);
1379 wmemset((wchar_t*)planes[PLANE_V].rect.pBits, 512, planes[PLANE_V].rect.Pitch * (m_height/2) / 2);
1382 case RENDER_FMT_YUV420P:
1384 memset(planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height);
1385 memset(planes[PLANE_U].rect.pBits, 128, planes[PLANE_U].rect.Pitch * (m_height/2));
1386 memset(planes[PLANE_V].rect.pBits, 128, planes[PLANE_V].rect.Pitch * (m_height/2));
1389 case RENDER_FMT_NV12:
1391 memset(planes[PLANE_Y].rect.pBits, 0, planes[PLANE_Y].rect.Pitch * m_height);
1392 memset(planes[PLANE_UV].rect.pBits, 128, planes[PLANE_U].rect.Pitch * (m_height/2));
1395 // YUY2, UYVY: wmemset to set a 16bit pattern, byte-swapped because x86 is LE
1396 case RENDER_FMT_YUYV422:
1398 wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0x8000, planes[PLANE_Y].rect.Pitch / 2 * m_height);
1401 case RENDER_FMT_UYVY422:
1403 wmemset((wchar_t*)planes[PLANE_Y].rect.pBits, 0x0080, planes[PLANE_Y].rect.Pitch / 2 * m_height);
1411 //==================================
1413 DXVABuffer::~DXVABuffer()
1418 void DXVABuffer::Release()
1423 void DXVABuffer::StartDecode()