1 #define _WIN32_WINNT 0x500
13 #ifndef DXVA2_E_NEW_VIDEO_DEVICE
14 #define DXVA2_E_NEW_VIDEO_DEVICE MAKE_HRESULT(1, 4, 4097)
40 : m_size(size), m_render(render)
128 #define mD3DFMT_YV12 (D3DFORMAT)MAKEFOURCC('Y','V','1','2')
129 #define mD3DFMT_IYUV (D3DFORMAT)MAKEFOURCC('I','Y','U','V')
130 #define mD3DFMT_I420 (D3DFORMAT)MAKEFOURCC('I','4','2','0')
131 #define mD3DFMT_YV16 (D3DFORMAT)MAKEFOURCC('Y','V','1','6')
132 #define D3DFVF_TEXTUREVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1|D3DFVF_TEX2)
133 #define D3DFVF_VERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE)
134 #define D3DLOC QString("MythRenderD3D9: ")
144 IDirect3DDevice9* result =
nullptr;
148 LOG(VB_GENERAL, LOG_ERR,
"D3D9Locker: Failed to acquire device.");
154 return (
void *)QLibrary::resolve(lib, proc);
159 QMutexLocker locker(&
m_lock);
161 LOG(VB_GENERAL, LOG_INFO,
D3DLOC +
"Deleting D3D9 resources.");
178 LOG(VB_GENERAL, LOG_INFO,
D3DLOC +
"Deleting D3D9 device.");
184 LOG(VB_GENERAL, LOG_INFO,
D3DLOC +
"Deleting D3D9.");
195 case D3DFMT_A8R8G8B8:
197 case D3DFMT_X8R8G8B8:
199 case D3DFMT_A8B8G8R8:
201 case D3DFMT_X8B8G8R8:
218 return QString().setNum((ulong)fmt,16);
223 QMutexLocker locker(&
m_lock);
225 using LPFND3DC = LPDIRECT3D9 (WINAPI *)(UINT SDKVersion);
226 static LPFND3DC OurDirect3DCreate9 =
nullptr;
228 OurDirect3DCreate9 = (LPFND3DC)
ResolveAddress(
"D3D9",
"Direct3DCreate9");
229 if (!OurDirect3DCreate9)
232 "FATAL: Failed to find Direct3DCreate9.");
236 m_d3d = OurDirect3DCreate9(D3D_SDK_VERSION);
240 "Could not create Direct3D9 instance.");
245 ZeroMemory(&d3dCaps,
sizeof(d3dCaps));
246 if (D3D_OK !=
m_d3d->GetDeviceCaps(
247 D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps))
250 "Could not read adapter capabilities.");
253 D3DDISPLAYMODE d3ddm;
254 if (D3D_OK !=
m_d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm))
257 "Could not read adapter display mode.");
262 static const D3DFORMAT bfmt[] =
272 bool is_reasonable =
false;
273 for (
uint i = 0; i <
sizeof(bfmt) /
sizeof(bfmt[0]); i++)
275 is_reasonable =
true;
276 LOG(VB_GENERAL, LOG_INFO,
D3DLOC + QString(
"Default adaptor format %1.")
281 "Warning: Default adaptor format may not work.");
285 for (
unsigned i = 0; i <
sizeof bfmt /
sizeof bfmt[0]; ++i)
287 if (SUCCEEDED(
m_d3d->CheckDeviceType(D3DADAPTER_DEFAULT,
297 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to choose surface format - "
298 "using default back buffer format.");
304 QString(
"Chosen surface and texture format: %1")
309 if (
FAILED(
m_d3d->CheckDeviceFormatConversion(D3DADAPTER_DEFAULT,
311 SUCCEEDED(
m_d3d->CheckDeviceFormatConversion(D3DADAPTER_DEFAULT,
322 QString(
"Chosen video surface format %1.")
325 QString(
"Hardware YV12 to RGB conversion %1.")
327 "unavailable" :
"available"));
329 D3DPRESENT_PARAMETERS d3dpp;
330 ZeroMemory(&d3dpp,
sizeof(D3DPRESENT_PARAMETERS));
332 d3dpp.hDeviceWindow = window;
333 d3dpp.Windowed =
true;
334 d3dpp.BackBufferWidth = size.width();
335 d3dpp.BackBufferHeight = size.height();
336 d3dpp.BackBufferCount = 1;
337 d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE;
338 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
339 d3dpp.Flags = D3DPRESENTFLAG_VIDEO;
340 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
342 if (D3D_OK !=
m_d3d->CreateDevice(D3DADAPTER_DEFAULT,
343 D3DDEVTYPE_HAL, d3dpp.hDeviceWindow,
344 D3DCREATE_SOFTWARE_VERTEXPROCESSING |
345 D3DCREATE_MULTITHREADED,
348 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Could not create the D3D device.");
352 static bool debugged =
false;
356 D3DADAPTER_IDENTIFIER9 ident;
357 if (D3D_OK ==
m_d3d->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &ident))
359 LOG(VB_GENERAL, LOG_INFO,
D3DLOC + QString(
"Device: %1")
360 .arg(ident.Description));
361 LOG(VB_GENERAL, LOG_INFO,
D3DLOC +QString(
"Driver: %1.%2.%3.%4")
362 .arg(HIWORD(ident.DriverVersion.HighPart))
363 .arg(LOWORD(ident.DriverVersion.HighPart))
364 .arg(HIWORD(ident.DriverVersion.LowPart))
365 .arg(LOWORD(ident.DriverVersion.LowPart)));
382 IDirect3DDevice9* dev = locker.
Acquire();
387 HRESULT hr = dev->TestCooperativeLevel();
392 case D3DERR_DEVICENOTRESET:
394 "The device was lost and needs to be reset.");
399 case D3DERR_DEVICELOST:
401 "The device has been lost and cannot be reset "
406 case D3DERR_DRIVERINTERNALERROR:
408 "Internal driver error. "
409 "Please shut down the application.");
415 "TestCooperativeLevel() failed.");
425 IDirect3DDevice9* dev = locker.
Acquire();
429 HRESULT hr = dev->Clear(0,
nullptr, D3DCLEAR_TARGET,
430 D3DCOLOR_ARGB(0, 0, 0, 0), 1.0F, 0);
433 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Clear() failed.");
442 IDirect3DDevice9* dev = locker.
Acquire();
446 HRESULT hr = dev->BeginScene();
449 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"BeginScene() failed.");
458 IDirect3DDevice9* dev = locker.
Acquire();
462 HRESULT hr = dev->EndScene();
465 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"EndScene() failed.");
478 IDirect3DSurface9 *surface,
482 (known_surface && !
m_surfaces.contains(surface)))
486 IDirect3DDevice9* dev = locker.
Acquire();
490 LPDIRECT3DSURFACE9 d3ddest;
491 HRESULT hr = texture->GetSurfaceLevel(0, &d3ddest);
494 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"GetSurfaceLevel() failed");
498 hr = dev->StretchRect(surface,
nullptr, d3ddest,
499 nullptr, D3DTEXF_POINT);
503 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"StretchRect() failed");
515 IDirect3DDevice9* dev = locker.
Acquire();
528 HRESULT hr = dev->SetStreamSource(0, vertexbuffer,
532 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"SetStreamSource() failed");
536 hr = dev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
539 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"DrawPrimitive() failed");
549 IDirect3DDevice9* dev = locker.
Acquire();
555 HRESULT hr = dev->CreateVertexBuffer(
556 sizeof(
VERTEX)*4, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
562 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to create vertex buffer");
572 int alphamod = (int)(color.alpha() * (alpha / 255.0));
573 D3DCOLOR clr = D3DCOLOR_ARGB(alphamod, color.red(),
574 color.green(), color.blue());
580 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to lock vertex buffer.");
584 p_vertices[0].
x = (float)rect.left();
585 p_vertices[0].
y = (float)rect.top();
586 p_vertices[0].
z = 0.0F;
588 p_vertices[0].
rhw = 1.0F;
589 p_vertices[1].
x = (float)(rect.left() + rect.width());
590 p_vertices[1].
y = (float)rect.top();
591 p_vertices[1].
z = 0.0F;
593 p_vertices[1].
rhw = 1.0F;
594 p_vertices[2].
x = (float)(rect.left() + rect.width());
595 p_vertices[2].
y = (float)(rect.top() + rect.height());
596 p_vertices[2].
z = 0.0F;
598 p_vertices[2].
rhw = 1.0F;
599 p_vertices[3].
x = (float)rect.left();
600 p_vertices[3].
y = (float)(rect.top() + rect.height());
601 p_vertices[3].
z = 0.0F;
603 p_vertices[3].
rhw = 1.0F;
608 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to unlock vertex buffer");
616 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"SetStreamSource() failed");
620 hr = dev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
623 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"DrawPrimitive() failed");
629 IDirect3DTexture9 *texture)
640 dev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG2);
641 dev->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
642 dev->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
643 dev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
644 dev->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
645 dev->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
646 dev->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE);
647 dev->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
651 dev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
652 dev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
653 dev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
654 dev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
655 dev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
656 dev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
657 dev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
658 dev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
667 IDirect3DDevice9* dev = locker.
Acquire();
671 HRESULT hr = dev->Present(
nullptr,
nullptr, win,
nullptr);
674 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Present() failed)");
677 SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED);
691 IDirect3DDevice9* dev = locker.
Acquire();
705 "Failed to get default surface.");
710 IDirect3DSurface9 *new_surface =
nullptr;
711 hr = texture->GetSurfaceLevel(0, &new_surface);
713 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to get surface level.");
722 "Failed to set render target.");
732 "Failed to set render target.");
736 "No default surface for render target.");
744 IDirect3DTexture9 *texture,
int num)
749 HRESULT hr = dev->SetTexture(num, (LPDIRECT3DBASETEXTURE9)texture);
752 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"SetTexture() failed");
761 IDirect3DDevice9* dev = locker.
Acquire();
765 IDirect3DTexture9* temp_texture =
nullptr;
767 HRESULT hr = dev->CreateTexture(
768 size.width(), size.height(), 1, D3DUSAGE_RENDERTARGET,
771 if (
FAILED(hr) || !temp_texture)
773 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to create texture.");
783 QMap<IDirect3DTexture9*,QSize>::iterator it;
791 QMutexLocker locker(&
m_lock);
802 IDirect3DDevice9* dev = locker.
Acquire();
806 IDirect3DSurface9* temp_surface =
nullptr;
810 HRESULT hr = dev->CreateOffscreenPlainSurface(
811 size.width(), size.height(), format,
812 D3DPOOL_DEFAULT, &temp_surface,
nullptr);
814 if (
FAILED(hr)|| !temp_surface)
816 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to create surface.");
821 dev->ColorFill(temp_surface,
nullptr, D3DCOLOR_ARGB(0xFF, 0, 0, 0) );
829 if (!surface || !image || !
m_surfaces.contains(surface))
833 m_surfaces[surface].m_size.height() != image->height())
836 "Frame size does not equal surface size.");
841 uint8_t *buf =
GetBuffer(surface, d3dpitch);
843 if (!(buf && d3dpitch))
849 case D3DFMT_A8R8G8B8:
850 case D3DFMT_X8R8G8B8:
852 uint pitch = image->width() << 2;
854 uint8_t *src = (uint8_t*)image->bits();
855 for (
int i = 0; i < image->height(); i++)
857 memcpy(dst, src, pitch);
864 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Surface format not supported.");
874 QMap<IDirect3DSurface9*, MythD3DSurface>::iterator it;
882 QMutexLocker locker(&
m_lock);
896 D3DLOCKED_RECT d3drect;
897 HRESULT hr = surface->LockRect(&d3drect,
nullptr, 0);
901 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to lock picture surface.");
906 pitch = d3drect.Pitch;
907 return (uint8_t*)d3drect.pBits;
915 HRESULT hr = surface->UnlockRect();
917 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to unlock picture surface.");
924 IDirect3DDevice9* dev = locker.
Acquire();
931 IDirect3DVertexBuffer9* temp_vbuf =
nullptr;
932 HRESULT hr = dev->CreateVertexBuffer(
933 sizeof(
TEXTUREVERTEX)*4, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
935 &temp_vbuf,
nullptr);
939 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to create vertex buffer");
949 QMap<IDirect3DVertexBuffer9*,MythD3DVertexBuffer>::iterator it;
960 QMutexLocker locker(&
m_lock);
963 vertexbuffer->Release();
969 const QRect &dst,
const QRect &src,
970 int alpha,
bool video)
976 uint32_t clr = (alpha << 24) + (255 << 16) + (255 << 8) + 255;
978 int width = dst.width();
979 int height = dst.height();
982 width = std::min(src.width(), width);
983 height = std::min(src.height(), height);
985 QRect
dest(dst.left(), dst.top(), width, height);
989 src == mythvb.
m_src &&
993 QSize norm = src.size();
997 QMutexLocker locker(&
m_lock);
999 HRESULT hr = vertexbuffer->Lock(0, 0, (VOID **)(&p_vertices),
1001 D3DCOLOR color = D3DCOLOR_ARGB(alpha, 255, 255, 255);
1004 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to lock vertex buffer.");
1008 p_vertices[0].
x = (float)
dest.left();
1009 p_vertices[0].
y = (float)
dest.top();
1010 p_vertices[0].
z = 0.0F;
1011 p_vertices[0].
diffuse = color;
1012 p_vertices[0].
rhw = 1.0F;
1013 p_vertices[0].
t1u = ((float)src.left() - 0.5F) / (
float)norm.width();
1014 p_vertices[0].
t1v = ((float)src.top() - 0.5F) / (
float)norm.height();
1016 p_vertices[1].
x = (float)(
dest.left() +
dest.width());
1017 p_vertices[1].
y = (float)
dest.top();
1018 p_vertices[1].
z = 0.0F;
1019 p_vertices[1].
diffuse = color;
1020 p_vertices[1].
rhw = 1.0F;
1021 p_vertices[1].
t1u = ((float)(src.left() + src.width()) - 0.5F) /
1022 (float)norm.width();
1023 p_vertices[1].
t1v = ((float)src.top() - 0.5F) / (
float)norm.height();
1025 p_vertices[2].
x = (float)(
dest.left() +
dest.width());
1026 p_vertices[2].
y = (float)(
dest.top() +
dest.height());
1027 p_vertices[2].
z = 0.0F;
1028 p_vertices[2].
diffuse = color;
1029 p_vertices[2].
rhw = 1.0F;
1030 p_vertices[2].
t1u = ((float)(src.left() + src.width()) - 0.5F) /
1031 (float)norm.width();
1032 p_vertices[2].
t1v = ((float)(src.top() + src.height()) - 0.5F) /
1033 (float)norm.height();
1035 p_vertices[3].
x = (float)
dest.left();
1036 p_vertices[3].
y = (float)(
dest.top() +
dest.height());
1037 p_vertices[3].
z = 0.0F;
1038 p_vertices[3].
diffuse = color;
1039 p_vertices[3].
rhw = 1.0F;
1040 p_vertices[3].
t1u = ((float)src.left() - 0.5F) / (
float)norm.width();
1041 p_vertices[3].
t1v = ((float)(src.top() + src.height()) - 0.5F) /
1042 (float)norm.height();
1044 p_vertices[0].
t2u = p_vertices[0].
t1u;
1045 p_vertices[0].
t2v = p_vertices[0].
t1v;
1046 p_vertices[1].
t2u = p_vertices[1].
t1u;
1047 p_vertices[1].
t2v = p_vertices[1].
t1v;
1048 p_vertices[2].
t2u = p_vertices[2].
t1u;
1049 p_vertices[2].
t2v = p_vertices[2].
t1v;
1050 p_vertices[3].
t2u = p_vertices[3].
t1u;
1051 p_vertices[3].
t2v = p_vertices[3].
t1v;
1053 hr = vertexbuffer->Unlock();
1056 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to unlock vertex buffer");
1072 dev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1073 dev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1074 dev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
1075 dev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
1076 dev->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1077 dev->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1078 dev->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
1079 dev->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
1080 dev->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(255,255,255));
1081 dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1082 dev->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
1083 dev->SetRenderState(D3DRS_LIGHTING, FALSE);
1084 dev->SetRenderState(D3DRS_DITHERENABLE, TRUE);
1085 dev->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1086 dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
1087 dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
1088 dev->SetVertexShader(
nullptr);
1103 dev->SetRenderState(D3DRS_ALPHABLENDENABLE, enable);
1122 IDirect3DDevice9* result =
nullptr;
1140 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to acquire D3D9 device.");
1155 LOG(VB_GENERAL, LOG_ERR,
D3DLOC +
"Failed to release D3D9 device.");
1163 IDirect3DDeviceManager9 **);
1171 "DXVA2CreateDirect3DDeviceManager9");
1172 if (CreateDeviceManager9)
1174 UINT resetToken = 0;
1181 LOG(VB_GENERAL, LOG_INFO,
D3DLOC +
"Created DXVA2 device manager.");
1185 LOG(VB_GENERAL, LOG_INFO,
D3DLOC +
"Retrieved device handle.");
1189 "Failed to retrieve device handle.");
1194 "Failed to create DXVA2 device manager.");
1200 "Failed to get DXVA2CreateDirect3DDeviceManager9 proc address.");
1206 "DXVA2 support not available - not using device manager");