|
MythTV
0.26-pre
|
00001 #define _WIN32_WINNT 0x500 00002 00003 #include <algorithm> 00004 using std::min; 00005 00006 #include <QLibrary> 00007 #include <QRect> 00008 #include <QMap> 00009 #include <QMutex> 00010 00011 #include "mythlogging.h" 00012 #include "mythrender_d3d9.h" 00013 00014 #define DXVA2_E_NEW_VIDEO_DEVICE MAKE_HRESULT(1, 4, 4097) 00015 00016 class MythD3DVertexBuffer 00017 { 00018 public: 00019 MythD3DVertexBuffer(IDirect3DTexture9* tex = NULL) : 00020 m_color(0xFFFFFFFF), m_dest(QRect(QPoint(0,0),QSize(0,0))), 00021 m_src(QRect(QPoint(0,0),QSize(0,0))), m_texture(tex) 00022 { 00023 } 00024 00025 uint32_t m_color; 00026 QRect m_dest; 00027 QRect m_src; 00028 IDirect3DTexture9 *m_texture; 00029 }; 00030 00031 class MythD3DSurface 00032 { 00033 public: 00034 MythD3DSurface(QSize size = QSize(0,0), D3DFORMAT fmt = D3DFMT_UNKNOWN) : 00035 m_size(size), m_fmt(fmt) 00036 { 00037 } 00038 00039 QSize m_size; 00040 D3DFORMAT m_fmt; 00041 }; 00042 00043 typedef struct 00044 { 00045 FLOAT x; 00046 FLOAT y; 00047 FLOAT z; 00048 FLOAT rhw; 00049 D3DCOLOR diffuse; 00050 FLOAT t1u; 00051 FLOAT t1v; 00052 FLOAT t2u; 00053 FLOAT t2v; 00054 } TEXTUREVERTEX; 00055 00056 typedef struct 00057 { 00058 FLOAT x; 00059 FLOAT y; 00060 FLOAT z; 00061 FLOAT rhw; 00062 D3DCOLOR diffuse; 00063 } VERTEX; 00064 00065 D3D9Image::D3D9Image(MythRenderD3D9 *render, QSize size, bool video) 00066 : m_size(size), m_valid(false), m_render(render), m_vertexbuffer(NULL), 00067 m_texture(NULL), m_surface(NULL) 00068 { 00069 if (m_render) 00070 { 00071 m_texture = m_render->CreateTexture(m_size); 00072 m_vertexbuffer = m_render->CreateVertexBuffer(m_texture); 00073 m_surface = m_render->CreateSurface(m_size, video); 00074 } 00075 m_valid = m_texture && m_vertexbuffer && m_surface; 00076 } 00077 00078 D3D9Image::~D3D9Image() 00079 { 00080 if (!m_render) 00081 return; 00082 00083 if (m_texture) 00084 m_render->DeleteTexture(m_texture); 00085 if (m_vertexbuffer) 00086 m_render->DeleteVertexBuffer(m_vertexbuffer); 00087 if (m_surface) 00088 m_render->DeleteSurface(m_surface); 00089 } 00090 00091 bool D3D9Image::SetAsRenderTarget(void) 00092 { 00093 if (m_valid) 00094 return m_render->SetRenderTarget(m_texture); 00095 return m_valid; 00096 } 00097 00098 bool D3D9Image::UpdateImage(IDirect3DSurface9 *surface) 00099 { 00100 if (m_valid) 00101 return m_render->StretchRect(m_texture, surface, false); 00102 return false; 00103 } 00104 00105 bool D3D9Image::UpdateImage(const MythImage *img) 00106 { 00107 bool result = true; 00108 if (m_valid) 00109 { 00110 result &= m_render->UpdateSurface(m_surface, img); 00111 result &= m_render->StretchRect(m_texture, m_surface); 00112 } 00113 return m_valid && result; 00114 } 00115 00116 bool D3D9Image::UpdateVertices(const QRect &dvr, const QRect &vr, int alpha, 00117 bool video) 00118 { 00119 if (m_valid) 00120 return m_render->UpdateVertexBuffer(m_vertexbuffer, dvr, vr, 00121 alpha, video); 00122 return m_valid; 00123 } 00124 00125 bool D3D9Image::Draw(void) 00126 { 00127 if (m_valid) 00128 return m_render->DrawTexturedQuad(m_vertexbuffer); 00129 return m_valid; 00130 } 00131 00132 uint8_t* D3D9Image::GetBuffer(bool &hardware_conv, uint &pitch) 00133 { 00134 if (!m_valid) 00135 return NULL; 00136 00137 hardware_conv = m_render->HardwareYUVConversion(); 00138 return m_render->GetBuffer(m_surface, pitch); 00139 } 00140 00141 void D3D9Image::ReleaseBuffer(void) 00142 { 00143 if (!m_valid) 00144 return; 00145 m_render->ReleaseBuffer(m_surface); 00146 m_render->StretchRect(m_texture, m_surface); 00147 } 00148 00149 QRect D3D9Image::GetRect(void) 00150 { 00151 if (!m_valid) 00152 return QRect(); 00153 return m_render->GetRect(m_vertexbuffer); 00154 } 00155 00156 #define mD3DFMT_YV12 (D3DFORMAT)MAKEFOURCC('Y','V','1','2') 00157 #define mD3DFMT_IYUV (D3DFORMAT)MAKEFOURCC('I','Y','U','V') 00158 #define mD3DFMT_I420 (D3DFORMAT)MAKEFOURCC('I','4','2','0') 00159 #define mD3DFMT_YV16 (D3DFORMAT)MAKEFOURCC('Y','V','1','6') 00160 #define D3DFVF_TEXTUREVERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE|D3DFVF_TEX1|D3DFVF_TEX2) 00161 #define D3DFVF_VERTEX (D3DFVF_XYZRHW|D3DFVF_DIFFUSE) 00162 #define D3DLOC QString("MythRenderD3D9: ") 00163 00164 D3D9Locker::D3D9Locker(MythRenderD3D9 *render) : m_render(render) 00165 { 00166 } 00167 00168 D3D9Locker::~D3D9Locker() 00169 { 00170 if (m_render) 00171 m_render->ReleaseDevice(); 00172 } 00173 00174 IDirect3DDevice9* D3D9Locker::Acquire(void) 00175 { 00176 IDirect3DDevice9* result = NULL; 00177 if (m_render) 00178 result = m_render->AcquireDevice(); 00179 if (!result) 00180 LOG(VB_GENERAL, LOG_ERR, "D3D9Locker: Failed to acquire device."); 00181 return result; 00182 } 00183 00184 void* MythRenderD3D9::ResolveAddress(const char* lib, const char* proc) 00185 { 00186 return QLibrary::resolve(lib, proc); 00187 } 00188 00189 MythRenderD3D9::MythRenderD3D9(void) 00190 : MythRender(kRenderDirect3D9), 00191 m_d3d(NULL), m_rootD3DDevice(NULL), 00192 m_adaptor_fmt(D3DFMT_UNKNOWN), 00193 m_videosurface_fmt(D3DFMT_UNKNOWN), 00194 m_surface_fmt(D3DFMT_UNKNOWN), m_texture_fmt(D3DFMT_UNKNOWN), 00195 m_rect_vertexbuffer(NULL), m_default_surface(NULL), m_current_surface(NULL), 00196 m_lock(QMutex::Recursive), 00197 m_blend(true), m_multi_texturing(true), m_texture_vertices(true), 00198 m_deviceManager(NULL), m_deviceHandle(NULL), m_deviceManagerToken(0) 00199 { 00200 } 00201 00202 MythRenderD3D9::~MythRenderD3D9(void) 00203 { 00204 QMutexLocker locker(&m_lock); 00205 00206 LOG(VB_GENERAL, LOG_INFO, D3DLOC + "Deleting D3D9 resources."); 00207 00208 if (m_rect_vertexbuffer) 00209 m_rect_vertexbuffer->Release(); 00210 if (m_current_surface) 00211 m_current_surface->Release(); 00212 if (m_default_surface) 00213 m_default_surface->Release(); 00214 00215 DeleteTextures(); 00216 DeleteVertexBuffers(); 00217 DeleteSurfaces(); 00218 00219 DestroyDeviceManager(); 00220 00221 if (m_rootD3DDevice) 00222 { 00223 LOG(VB_GENERAL, LOG_INFO, D3DLOC + "Deleting D3D9 device."); 00224 m_rootD3DDevice->Release(); 00225 } 00226 00227 if (m_d3d) 00228 { 00229 LOG(VB_GENERAL, LOG_INFO, D3DLOC + "Deleting D3D9."); 00230 m_d3d->Release(); 00231 } 00232 } 00233 00234 static const QString toString(D3DFORMAT fmt) 00235 { 00236 switch (fmt) 00237 { 00238 case D3DFMT_A8: 00239 return "A8"; 00240 case D3DFMT_A8R8G8B8: 00241 return "A8R8G8B8"; 00242 case D3DFMT_X8R8G8B8: 00243 return "X8R8G8B8"; 00244 case D3DFMT_A8B8G8R8: 00245 return "A8B8G8R8"; 00246 case D3DFMT_X8B8G8R8: 00247 return "X8B8G8R8"; 00248 case mD3DFMT_YV12: 00249 return "YV12"; 00250 case D3DFMT_UYVY: 00251 return "UYVY"; 00252 case D3DFMT_YUY2: 00253 return "YUY2"; 00254 case mD3DFMT_IYUV: 00255 return "IYUV"; 00256 case mD3DFMT_I420: 00257 return "I420"; 00258 case mD3DFMT_YV16: 00259 return "YV16"; 00260 default: 00261 break; 00262 } 00263 return QString().setNum((ulong)fmt,16); 00264 } 00265 00266 bool MythRenderD3D9::Create(QSize size, HWND window) 00267 { 00268 QMutexLocker locker(&m_lock); 00269 00270 typedef LPDIRECT3D9 (WINAPI *LPFND3DC)(UINT SDKVersion); 00271 static LPFND3DC OurDirect3DCreate9 = NULL; 00272 00273 OurDirect3DCreate9 = (LPFND3DC)ResolveAddress("D3D9","Direct3DCreate9"); 00274 if (!OurDirect3DCreate9) 00275 { 00276 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 00277 "FATAL: Failed to find Direct3DCreate9."); 00278 return false; 00279 } 00280 00281 m_d3d = OurDirect3DCreate9(D3D_SDK_VERSION); 00282 if (!m_d3d) 00283 { 00284 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 00285 "Could not create Direct3D9 instance."); 00286 return false; 00287 } 00288 00289 D3DCAPS9 d3dCaps; 00290 ZeroMemory(&d3dCaps, sizeof(d3dCaps)); 00291 if (D3D_OK != m_d3d->GetDeviceCaps( 00292 D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &d3dCaps)) 00293 { 00294 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 00295 "Could not read adapter capabilities."); 00296 } 00297 00298 D3DDISPLAYMODE d3ddm; 00299 if (D3D_OK != m_d3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm)) 00300 { 00301 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 00302 "Could not read adapter display mode."); 00303 return false; 00304 } 00305 00306 // Check the adaptor format is reasonable 00307 static const D3DFORMAT bfmt[] = 00308 { 00309 D3DFMT_A8R8G8B8, 00310 D3DFMT_A8B8G8R8, 00311 D3DFMT_X8R8G8B8, 00312 D3DFMT_X8B8G8R8, 00313 D3DFMT_R8G8B8 00314 }; 00315 00316 m_adaptor_fmt = d3ddm.Format; 00317 bool is_reasonable = false; 00318 for (uint i = 0; i < sizeof(bfmt) / sizeof(bfmt[0]); i++) 00319 if (bfmt[i] == m_adaptor_fmt) 00320 is_reasonable = true; 00321 LOG(VB_GENERAL, LOG_INFO, D3DLOC + QString("Default adaptor format %1.") 00322 .arg(toString(m_adaptor_fmt))); 00323 if (!is_reasonable) 00324 { 00325 LOG(VB_GENERAL, LOG_WARNING, D3DLOC + 00326 "Warning: Default adaptor format may not work."); 00327 } 00328 00329 // Choose a surface format 00330 for (unsigned i = 0; i < sizeof bfmt / sizeof bfmt[0]; ++i) 00331 { 00332 if (SUCCEEDED(m_d3d->CheckDeviceType(D3DADAPTER_DEFAULT, 00333 D3DDEVTYPE_HAL, m_adaptor_fmt, bfmt[i], TRUE))) 00334 { 00335 m_surface_fmt = bfmt[i]; 00336 break; 00337 } 00338 } 00339 00340 if (D3DFMT_UNKNOWN == m_surface_fmt) 00341 { 00342 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to choose surface format - " 00343 "using default back buffer format."); 00344 m_surface_fmt = m_adaptor_fmt; 00345 } 00346 00347 m_texture_fmt = m_surface_fmt; 00348 LOG(VB_GENERAL, LOG_INFO, D3DLOC + 00349 QString("Chosen surface and texture format: %1") 00350 .arg(toString(m_surface_fmt))); 00351 00352 00353 // Test whether a YV12 video surface is available 00354 if (FAILED(m_d3d->CheckDeviceFormatConversion(D3DADAPTER_DEFAULT, 00355 D3DDEVTYPE_HAL, D3DFMT_UNKNOWN, m_adaptor_fmt)) && 00356 SUCCEEDED(m_d3d->CheckDeviceFormatConversion(D3DADAPTER_DEFAULT, 00357 D3DDEVTYPE_HAL, mD3DFMT_YV12, m_surface_fmt))) 00358 { 00359 m_videosurface_fmt = mD3DFMT_YV12; 00360 } 00361 else 00362 { 00363 m_videosurface_fmt = m_surface_fmt; 00364 } 00365 00366 LOG(VB_GENERAL, LOG_INFO, D3DLOC + 00367 QString("Chosen video surface format %1.") 00368 .arg(toString(m_videosurface_fmt))); 00369 LOG(VB_GENERAL, LOG_INFO, D3DLOC + 00370 QString("Hardware YV12 to RGB conversion %1.") 00371 .arg(m_videosurface_fmt != mD3DFMT_YV12 ? 00372 "unavailable" : "available")); 00373 00374 D3DPRESENT_PARAMETERS d3dpp; 00375 ZeroMemory(&d3dpp, sizeof(D3DPRESENT_PARAMETERS)); 00376 d3dpp.BackBufferFormat = m_adaptor_fmt; 00377 d3dpp.hDeviceWindow = window; 00378 d3dpp.Windowed = true; 00379 d3dpp.BackBufferWidth = size.width(); 00380 d3dpp.BackBufferHeight = size.height(); 00381 d3dpp.BackBufferCount = 1; 00382 d3dpp.MultiSampleType = D3DMULTISAMPLE_NONE; 00383 d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; 00384 d3dpp.Flags = D3DPRESENTFLAG_VIDEO; 00385 d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; 00386 00387 if (D3D_OK != m_d3d->CreateDevice(D3DADAPTER_DEFAULT, 00388 D3DDEVTYPE_HAL, d3dpp.hDeviceWindow, 00389 D3DCREATE_SOFTWARE_VERTEXPROCESSING | 00390 D3DCREATE_MULTITHREADED, 00391 &d3dpp, &m_rootD3DDevice)) 00392 { 00393 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Could not create the D3D device."); 00394 return false; 00395 } 00396 00397 static bool debugged = false; 00398 if (!debugged) 00399 { 00400 debugged = true; 00401 D3DADAPTER_IDENTIFIER9 ident; 00402 if (D3D_OK == m_d3d->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &ident)) 00403 { 00404 LOG(VB_GENERAL, LOG_INFO, D3DLOC + QString("Device: %1") 00405 .arg(ident.Description)); 00406 LOG(VB_GENERAL, LOG_INFO, D3DLOC +QString("Driver: %1.%2.%3.%4") 00407 .arg(HIWORD(ident.DriverVersion.HighPart)) 00408 .arg(LOWORD(ident.DriverVersion.HighPart)) 00409 .arg(HIWORD(ident.DriverVersion.LowPart)) 00410 .arg(LOWORD(ident.DriverVersion.LowPart))); 00411 } 00412 } 00413 00414 CreateDeviceManager(); 00415 Init2DState(); 00416 return true; 00417 } 00418 00419 bool MythRenderD3D9::HardwareYUVConversion(void) 00420 { 00421 return m_videosurface_fmt == mD3DFMT_YV12; 00422 } 00423 00424 bool MythRenderD3D9::Test(bool &reset) 00425 { 00426 D3D9Locker locker(this); 00427 IDirect3DDevice9* dev = locker.Acquire(); 00428 if (!dev) 00429 return false; 00430 00431 bool result = true; 00432 HRESULT hr = dev->TestCooperativeLevel(); 00433 if (FAILED(hr)) 00434 { 00435 switch (hr) 00436 { 00437 case D3DERR_DEVICENOTRESET: 00438 LOG(VB_GENERAL, LOG_NOTICE, D3DLOC + 00439 "The device was lost and needs to be reset."); 00440 result = false; 00441 reset |= true; 00442 break; 00443 00444 case D3DERR_DEVICELOST: 00445 LOG(VB_GENERAL, LOG_NOTICE, D3DLOC + 00446 "The device has been lost and cannot be reset " 00447 "at this time."); 00448 result = false; 00449 break; 00450 00451 case D3DERR_DRIVERINTERNALERROR: 00452 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 00453 "Internal driver error. " 00454 "Please shut down the application."); 00455 result = false; 00456 break; 00457 00458 default: 00459 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 00460 "TestCooperativeLevel() failed."); 00461 result = false; 00462 } 00463 } 00464 return result; 00465 } 00466 00467 bool MythRenderD3D9::ClearBuffer(void) 00468 { 00469 D3D9Locker locker(this); 00470 IDirect3DDevice9* dev = locker.Acquire(); 00471 if (!dev) 00472 return false; 00473 00474 HRESULT hr = dev->Clear(0, NULL, D3DCLEAR_TARGET, 00475 D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0); 00476 if (FAILED(hr)) 00477 { 00478 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Clear() failed."); 00479 return false; 00480 } 00481 return true; 00482 } 00483 00484 bool MythRenderD3D9::Begin(void) 00485 { 00486 D3D9Locker locker(this); 00487 IDirect3DDevice9* dev = locker.Acquire(); 00488 if (!dev) 00489 return false; 00490 00491 HRESULT hr = dev->BeginScene(); 00492 if (FAILED(hr)) 00493 { 00494 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "BeginScene() failed."); 00495 return false; 00496 } 00497 return true; 00498 } 00499 00500 bool MythRenderD3D9::End(void) 00501 { 00502 D3D9Locker locker(this); 00503 IDirect3DDevice9* dev = locker.Acquire(); 00504 if (!dev) 00505 return false; 00506 00507 HRESULT hr = dev->EndScene(); 00508 if (FAILED(hr)) 00509 { 00510 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "EndScene() failed."); 00511 return false; 00512 } 00513 return true; 00514 } 00515 00516 void MythRenderD3D9::CopyFrame(void* surface, D3D9Image *img) 00517 { 00518 if (surface && img) 00519 img->UpdateImage((IDirect3DSurface9*)surface); 00520 } 00521 00522 bool MythRenderD3D9::StretchRect(IDirect3DTexture9 *texture, 00523 IDirect3DSurface9 *surface, 00524 bool known_surface) 00525 { 00526 if (!m_textures.contains(texture) || 00527 (known_surface && !m_surfaces.contains(surface))) 00528 return false; 00529 00530 D3D9Locker locker(this); 00531 IDirect3DDevice9* dev = locker.Acquire(); 00532 if (!dev) 00533 return false; 00534 00535 LPDIRECT3DSURFACE9 d3ddest; 00536 HRESULT hr = texture->GetSurfaceLevel(0, &d3ddest); 00537 if (FAILED(hr)) 00538 { 00539 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "GetSurfaceLevel() failed"); 00540 return false; 00541 } 00542 00543 hr = dev->StretchRect(surface, NULL, d3ddest, 00544 NULL, D3DTEXF_POINT); 00545 d3ddest->Release(); 00546 if (FAILED(hr)) 00547 { 00548 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "StretchRect() failed"); 00549 return false; 00550 } 00551 return true; 00552 } 00553 00554 bool MythRenderD3D9::DrawTexturedQuad(IDirect3DVertexBuffer9 *vertexbuffer) 00555 { 00556 if (!m_vertexbuffers.contains(vertexbuffer)) 00557 return false; 00558 00559 D3D9Locker locker(this); 00560 IDirect3DDevice9* dev = locker.Acquire(); 00561 if (!dev) 00562 return false; 00563 00564 IDirect3DTexture9 *texture = m_vertexbuffers[vertexbuffer].m_texture; 00565 00566 if (texture && !SetTexture(dev, texture)) 00567 return false; 00568 00569 EnableBlending(dev, true); 00570 SetTextureVertices(dev, true); 00571 MultiTexturing(dev, false); 00572 00573 HRESULT hr = dev->SetStreamSource(0, vertexbuffer, 00574 0, sizeof(TEXTUREVERTEX)); 00575 if (FAILED(hr)) 00576 { 00577 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "SetStreamSource() failed"); 00578 return false; 00579 } 00580 00581 hr = dev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2); 00582 if (FAILED(hr)) 00583 { 00584 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "DrawPrimitive() failed"); 00585 return false; 00586 } 00587 00588 return true; 00589 } 00590 00591 void MythRenderD3D9::DrawRect(const QRect &rect, const QColor &color, int alpha) 00592 { 00593 D3D9Locker locker(this); 00594 IDirect3DDevice9* dev = locker.Acquire(); 00595 if (!dev) 00596 return; 00597 00598 if (!m_rect_vertexbuffer) 00599 { 00600 HRESULT hr = dev->CreateVertexBuffer( 00601 sizeof(VERTEX)*4, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, 00602 D3DFVF_VERTEX, D3DPOOL_DEFAULT, 00603 &m_rect_vertexbuffer, NULL); 00604 00605 if (FAILED(hr)) 00606 { 00607 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to create vertex buffer"); 00608 return; 00609 } 00610 } 00611 00612 EnableBlending(dev, true); 00613 SetTextureVertices(dev, false); 00614 MultiTexturing(dev, false); 00615 SetTexture(dev, NULL, 0); 00616 00617 int alphamod = (int)(color.alpha() * (alpha / 255.0)); 00618 D3DCOLOR clr = D3DCOLOR_ARGB(alphamod, color.red(), 00619 color.green(), color.blue()); 00620 VERTEX *p_vertices; 00621 HRESULT hr = m_rect_vertexbuffer->Lock(0, 0, (VOID **)(&p_vertices), 00622 D3DLOCK_DISCARD); 00623 if (FAILED(hr)) 00624 { 00625 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to lock vertex buffer."); 00626 return; 00627 } 00628 00629 p_vertices[0].x = (float)rect.left(); 00630 p_vertices[0].y = (float)rect.top(); 00631 p_vertices[0].z = 0.0f; 00632 p_vertices[0].diffuse = clr; 00633 p_vertices[0].rhw = 1.0f; 00634 p_vertices[1].x = (float)(rect.left() + rect.width()); 00635 p_vertices[1].y = (float)rect.top(); 00636 p_vertices[1].z = 0.0f; 00637 p_vertices[1].diffuse = clr; 00638 p_vertices[1].rhw = 1.0f; 00639 p_vertices[2].x = (float)(rect.left() + rect.width()); 00640 p_vertices[2].y = (float)(rect.top() + rect.height()); 00641 p_vertices[2].z = 0.0f; 00642 p_vertices[2].diffuse = clr; 00643 p_vertices[2].rhw = 1.0f; 00644 p_vertices[3].x = (float)rect.left(); 00645 p_vertices[3].y = (float)(rect.top() + rect.height()); 00646 p_vertices[3].z = 0.0f; 00647 p_vertices[3].diffuse = clr; 00648 p_vertices[3].rhw = 1.0f; 00649 00650 hr = m_rect_vertexbuffer->Unlock(); 00651 if (FAILED(hr)) 00652 { 00653 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to unlock vertex buffer"); 00654 return; 00655 } 00656 00657 hr = dev->SetStreamSource(0, m_rect_vertexbuffer, 00658 0, sizeof(VERTEX)); 00659 if (FAILED(hr)) 00660 { 00661 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "SetStreamSource() failed"); 00662 return; 00663 } 00664 00665 hr = dev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2); 00666 if (FAILED(hr)) 00667 { 00668 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "DrawPrimitive() failed"); 00669 return; 00670 } 00671 } 00672 00673 void MythRenderD3D9::MultiTexturing(IDirect3DDevice9* dev, bool enable, 00674 IDirect3DTexture9 *texture) 00675 { 00676 if (m_multi_texturing == enable) 00677 return; 00678 00679 if (!dev) 00680 return; 00681 00682 if (enable) 00683 { 00684 SetTexture(dev, texture, 1); 00685 dev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_SELECTARG2); 00686 dev->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); 00687 dev->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); 00688 dev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); 00689 dev->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); 00690 dev->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT); 00691 dev->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE); 00692 dev->SetTextureStageState(2, D3DTSS_ALPHAOP, D3DTOP_DISABLE); 00693 } 00694 else 00695 { 00696 dev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); 00697 dev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); 00698 dev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); 00699 dev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); 00700 dev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); 00701 dev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT); 00702 dev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); 00703 dev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); 00704 SetTexture(dev, NULL, 1); 00705 } 00706 m_multi_texturing = enable; 00707 } 00708 00709 bool MythRenderD3D9::Present(HWND win) 00710 { 00711 D3D9Locker locker(this); 00712 IDirect3DDevice9* dev = locker.Acquire(); 00713 if (!dev) 00714 return false; 00715 00716 HRESULT hr = dev->Present(NULL, NULL, win, NULL); 00717 if (FAILED(hr)) 00718 { 00719 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Present() failed)"); 00720 return false; 00721 } 00722 SetThreadExecutionState(ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED); 00723 return true; 00724 } 00725 00726 QRect MythRenderD3D9::GetRect(IDirect3DVertexBuffer9 *vertexbuffer) 00727 { 00728 if (!m_vertexbuffers.contains(vertexbuffer)) 00729 return QRect(); 00730 return m_vertexbuffers[vertexbuffer].m_dest; 00731 } 00732 00733 bool MythRenderD3D9::SetRenderTarget(IDirect3DTexture9 *texture) 00734 { 00735 D3D9Locker locker(this); 00736 IDirect3DDevice9* dev = locker.Acquire(); 00737 if (!dev) 00738 return false; 00739 00740 bool ret = true; 00741 HRESULT hr; 00742 if (texture && m_textures.contains(texture)) 00743 { 00744 if (!m_default_surface) 00745 { 00746 hr = dev->GetRenderTarget(0, &m_default_surface); 00747 if (FAILED(hr)) 00748 { 00749 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 00750 "Failed to get default surface."); 00751 return false; 00752 } 00753 } 00754 00755 IDirect3DSurface9 *new_surface = NULL; 00756 hr = texture->GetSurfaceLevel(0, &new_surface); 00757 if (FAILED(hr)) 00758 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to get surface level."); 00759 else 00760 { 00761 if (m_current_surface && m_current_surface != new_surface) 00762 m_current_surface->Release(); 00763 m_current_surface = new_surface; 00764 hr = dev->SetRenderTarget(0, m_current_surface); 00765 if (FAILED(hr)) 00766 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 00767 "Failed to set render target."); 00768 } 00769 } 00770 else if (!texture) 00771 { 00772 if (m_default_surface) 00773 { 00774 hr = dev->SetRenderTarget(0, m_default_surface); 00775 if (FAILED(hr)) 00776 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 00777 "Failed to set render target."); 00778 } 00779 else 00780 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 00781 "No default surface for render target."); 00782 } 00783 else 00784 ret = false; 00785 return ret; 00786 } 00787 00788 bool MythRenderD3D9::SetTexture(IDirect3DDevice9* dev, 00789 IDirect3DTexture9 *texture, int num) 00790 { 00791 if (!dev) 00792 return false; 00793 00794 HRESULT hr = dev->SetTexture(num, (LPDIRECT3DBASETEXTURE9)texture); 00795 if (FAILED(hr)) 00796 { 00797 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "SetTexture() failed"); 00798 return false; 00799 } 00800 return true; 00801 } 00802 00803 IDirect3DTexture9* MythRenderD3D9::CreateTexture(const QSize &size) 00804 { 00805 D3D9Locker locker(this); 00806 IDirect3DDevice9* dev = locker.Acquire(); 00807 if (!dev) 00808 return NULL; 00809 00810 IDirect3DTexture9* temp_texture = NULL; 00811 00812 HRESULT hr = dev->CreateTexture( 00813 size.width(), size.height(), 1, D3DUSAGE_RENDERTARGET, 00814 m_texture_fmt, D3DPOOL_DEFAULT, &temp_texture, NULL); 00815 00816 if (FAILED(hr) || !temp_texture) 00817 { 00818 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to create texture."); 00819 return NULL; 00820 } 00821 00822 m_textures[temp_texture] = size;; 00823 return temp_texture; 00824 } 00825 00826 void MythRenderD3D9::DeleteTextures(void) 00827 { 00828 QMap<IDirect3DTexture9*,QSize>::iterator it; 00829 for (it = m_textures.begin(); it != m_textures.end(); ++it) 00830 it.key()->Release(); 00831 m_textures.clear(); 00832 } 00833 00834 void MythRenderD3D9::DeleteTexture(IDirect3DTexture9* texture) 00835 { 00836 QMutexLocker locker(&m_lock); 00837 if (m_textures.contains(texture)) 00838 { 00839 texture->Release(); 00840 m_textures.remove(texture); 00841 } 00842 } 00843 00844 IDirect3DSurface9* MythRenderD3D9::CreateSurface(const QSize &size, bool video) 00845 { 00846 D3D9Locker locker(this); 00847 IDirect3DDevice9* dev = locker.Acquire(); 00848 if (!dev) 00849 return NULL; 00850 00851 IDirect3DSurface9* temp_surface = NULL; 00852 00853 D3DFORMAT format = video ? m_videosurface_fmt : m_surface_fmt; 00854 00855 HRESULT hr = dev->CreateOffscreenPlainSurface( 00856 size.width(), size.height(), format, 00857 D3DPOOL_DEFAULT, &temp_surface, NULL); 00858 00859 if (FAILED(hr)|| !temp_surface) 00860 { 00861 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to create surface."); 00862 return NULL; 00863 } 00864 00865 m_surfaces[temp_surface] = MythD3DSurface(size, format); 00866 dev->ColorFill(temp_surface, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0) ); 00867 00868 return temp_surface; 00869 } 00870 00871 bool MythRenderD3D9::UpdateSurface(IDirect3DSurface9 *surface, 00872 const MythImage *image) 00873 { 00874 if (!surface || !image || !m_surfaces.contains(surface)) 00875 return false; 00876 00877 if (m_surfaces[surface].m_size.width() != image->width() || 00878 m_surfaces[surface].m_size.height() != image->height()) 00879 { 00880 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 00881 "Frame size does not equal surface size."); 00882 return false; 00883 } 00884 00885 uint d3dpitch = 0; 00886 uint8_t *buf = GetBuffer(surface, d3dpitch); 00887 00888 if (!(buf && d3dpitch)) 00889 return false; 00890 00891 D3DFORMAT format = m_surfaces[surface].m_fmt; 00892 switch (format) 00893 { 00894 case D3DFMT_A8R8G8B8: 00895 case D3DFMT_X8R8G8B8: 00896 { 00897 uint pitch = image->width() << 2; 00898 uint8_t *dst = buf; 00899 uint8_t *src = (uint8_t*)image->bits(); 00900 for (int i = 0; i < image->height(); i++) 00901 { 00902 memcpy(dst, src, pitch); 00903 dst += d3dpitch; 00904 src += pitch; 00905 } 00906 } 00907 break; 00908 default: 00909 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Surface format not supported."); 00910 break; 00911 } 00912 00913 ReleaseBuffer(surface); 00914 return true; 00915 } 00916 00917 void MythRenderD3D9::DeleteSurfaces(void) 00918 { 00919 QMap<IDirect3DSurface9*, MythD3DSurface>::iterator it; 00920 for (it = m_surfaces.begin(); it != m_surfaces.end(); ++it) 00921 it.key()->Release(); 00922 m_surfaces.clear(); 00923 } 00924 00925 void MythRenderD3D9::DeleteSurface(IDirect3DSurface9 *surface) 00926 { 00927 QMutexLocker locker(&m_lock); 00928 if (m_surfaces.contains(surface)) 00929 { 00930 surface->Release(); 00931 m_surfaces.remove(surface); 00932 } 00933 } 00934 00935 uint8_t* MythRenderD3D9::GetBuffer(IDirect3DSurface9* surface, uint &pitch) 00936 { 00937 if (!m_surfaces.contains(surface)) 00938 return NULL; 00939 00940 m_lock.lock(); // unlocked in release buffer 00941 D3DLOCKED_RECT d3drect; 00942 HRESULT hr = surface->LockRect(&d3drect, NULL, 0); 00943 00944 if (FAILED(hr)) 00945 { 00946 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to lock picture surface."); 00947 m_lock.unlock(); 00948 return false; 00949 } 00950 00951 pitch = d3drect.Pitch; 00952 return (uint8_t*)d3drect.pBits; 00953 } 00954 00955 void MythRenderD3D9::ReleaseBuffer(IDirect3DSurface9* surface) 00956 { 00957 if (!m_surfaces.contains(surface)) 00958 return; 00959 00960 HRESULT hr = surface->UnlockRect(); 00961 if (FAILED(hr)) 00962 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to unlock picture surface."); 00963 m_lock.unlock(); 00964 } 00965 00966 IDirect3DVertexBuffer9* MythRenderD3D9::CreateVertexBuffer(IDirect3DTexture9* texture) 00967 { 00968 D3D9Locker locker(this); 00969 IDirect3DDevice9* dev = locker.Acquire(); 00970 if (!dev) 00971 return NULL; 00972 00973 if (texture && !m_textures.contains(texture)) 00974 return false; 00975 00976 IDirect3DVertexBuffer9* temp_vbuf = NULL; 00977 HRESULT hr = dev->CreateVertexBuffer( 00978 sizeof(TEXTUREVERTEX)*4, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY, 00979 D3DFVF_TEXTUREVERTEX, D3DPOOL_DEFAULT, 00980 &temp_vbuf, NULL); 00981 00982 if (FAILED(hr)) 00983 { 00984 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to create vertex buffer"); 00985 return false; 00986 } 00987 00988 m_vertexbuffers[temp_vbuf] = MythD3DVertexBuffer(texture); 00989 return temp_vbuf; 00990 } 00991 00992 void MythRenderD3D9::DeleteVertexBuffers(void) 00993 { 00994 QMap<IDirect3DVertexBuffer9*,MythD3DVertexBuffer>::iterator it; 00995 for (it = m_vertexbuffers.begin(); 00996 it != m_vertexbuffers.end(); ++it) 00997 { 00998 it.key()->Release(); 00999 } 01000 m_vertexbuffers.clear(); 01001 } 01002 01003 void MythRenderD3D9::DeleteVertexBuffer(IDirect3DVertexBuffer9 *vertexbuffer) 01004 { 01005 QMutexLocker locker(&m_lock); 01006 if (m_vertexbuffers.contains(vertexbuffer)) 01007 { 01008 vertexbuffer->Release(); 01009 m_vertexbuffers.remove(vertexbuffer); 01010 } 01011 } 01012 01013 bool MythRenderD3D9::UpdateVertexBuffer(IDirect3DVertexBuffer9* vertexbuffer, 01014 const QRect &dst, const QRect &src, 01015 int alpha, bool video) 01016 { 01017 if (!m_vertexbuffers.contains(vertexbuffer)) 01018 return false; 01019 01020 MythD3DVertexBuffer mythvb = m_vertexbuffers[vertexbuffer]; 01021 uint32_t clr = (alpha << 24) + (255 << 16) + (255 << 8) + 255; 01022 01023 int width = dst.width(); 01024 int height = dst.height(); 01025 if (!video) 01026 { 01027 width = min(src.width(), width); 01028 height = min(src.height(), height); 01029 } 01030 QRect dest(dst.left(), dst.top(), width, height); 01031 01032 // FIXME - with alpha pulse, this updates far more textures than necessary 01033 if (dest == mythvb.m_dest && 01034 src == mythvb.m_src && 01035 clr == mythvb.m_color) 01036 return true; 01037 01038 QSize norm = src.size(); 01039 if (video && mythvb.m_texture) 01040 norm = m_textures[mythvb.m_texture]; 01041 01042 QMutexLocker locker(&m_lock); 01043 TEXTUREVERTEX *p_vertices; 01044 HRESULT hr = vertexbuffer->Lock(0, 0, (VOID **)(&p_vertices), 01045 D3DLOCK_DISCARD); 01046 D3DCOLOR color = D3DCOLOR_ARGB(alpha, 255, 255, 255); 01047 if (FAILED(hr)) 01048 { 01049 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to lock vertex buffer."); 01050 return false; 01051 } 01052 01053 p_vertices[0].x = (float)dest.left(); 01054 p_vertices[0].y = (float)dest.top(); 01055 p_vertices[0].z = 0.0f; 01056 p_vertices[0].diffuse = color; 01057 p_vertices[0].rhw = 1.0f; 01058 p_vertices[0].t1u = ((float)src.left() - 0.5f) / (float)norm.width(); 01059 p_vertices[0].t1v = ((float)src.top() - 0.5f) / (float)norm.height(); 01060 01061 p_vertices[1].x = (float)(dest.left() + dest.width()); 01062 p_vertices[1].y = (float)dest.top(); 01063 p_vertices[1].z = 0.0f; 01064 p_vertices[1].diffuse = color; 01065 p_vertices[1].rhw = 1.0f; 01066 p_vertices[1].t1u = ((float)(src.left() + src.width()) - 0.5f) / 01067 (float)norm.width(); 01068 p_vertices[1].t1v = ((float)src.top() - 0.5f) / (float)norm.height(); 01069 01070 p_vertices[2].x = (float)(dest.left() + dest.width()); 01071 p_vertices[2].y = (float)(dest.top() + dest.height()); 01072 p_vertices[2].z = 0.0f; 01073 p_vertices[2].diffuse = color; 01074 p_vertices[2].rhw = 1.0f; 01075 p_vertices[2].t1u = ((float)(src.left() + src.width()) - 0.5f) / 01076 (float)norm.width(); 01077 p_vertices[2].t1v = ((float)(src.top() + src.height()) - 0.5f) / 01078 (float)norm.height(); 01079 01080 p_vertices[3].x = (float)dest.left(); 01081 p_vertices[3].y = (float)(dest.top() + dest.height()); 01082 p_vertices[3].z = 0.0f; 01083 p_vertices[3].diffuse = color; 01084 p_vertices[3].rhw = 1.0f; 01085 p_vertices[3].t1u = ((float)src.left() - 0.5f) / (float)norm.width(); 01086 p_vertices[3].t1v = ((float)(src.top() + src.height()) - 0.5f) / 01087 (float)norm.height(); 01088 01089 p_vertices[0].t2u = p_vertices[0].t1u; 01090 p_vertices[0].t2v = p_vertices[0].t1v; 01091 p_vertices[1].t2u = p_vertices[1].t1u; 01092 p_vertices[1].t2v = p_vertices[1].t1v; 01093 p_vertices[2].t2u = p_vertices[2].t1u; 01094 p_vertices[2].t2v = p_vertices[2].t1v; 01095 p_vertices[3].t2u = p_vertices[3].t1u; 01096 p_vertices[3].t2v = p_vertices[3].t1v; 01097 01098 hr = vertexbuffer->Unlock(); 01099 if (FAILED(hr)) 01100 { 01101 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to unlock vertex buffer"); 01102 return false; 01103 } 01104 01105 m_vertexbuffers[vertexbuffer].m_dest = dest; 01106 m_vertexbuffers[vertexbuffer].m_src = src; 01107 m_vertexbuffers[vertexbuffer].m_color = clr; 01108 return true; 01109 } 01110 01111 void MythRenderD3D9::Init2DState(void) 01112 { 01113 IDirect3DDevice9* dev = AcquireDevice(); 01114 if (!dev) 01115 return; 01116 01117 dev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); 01118 dev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); 01119 dev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 01120 dev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 01121 dev->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); 01122 dev->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); 01123 dev->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); 01124 dev->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); 01125 dev->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(255,255,255)); 01126 dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 01127 dev->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); 01128 dev->SetRenderState(D3DRS_LIGHTING, FALSE); 01129 dev->SetRenderState(D3DRS_DITHERENABLE, TRUE); 01130 dev->SetRenderState(D3DRS_STENCILENABLE, FALSE); 01131 dev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); 01132 dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); 01133 dev->SetVertexShader(NULL); 01134 SetTextureVertices(dev, false); 01135 MultiTexturing(dev, false); 01136 EnableBlending(dev, false); 01137 01138 ReleaseDevice(); 01139 } 01140 01141 void MythRenderD3D9::EnableBlending(IDirect3DDevice9* dev, bool enable) 01142 { 01143 if (m_blend == enable) 01144 return; 01145 m_blend = enable; 01146 01147 if (dev) 01148 dev->SetRenderState(D3DRS_ALPHABLENDENABLE, enable); 01149 } 01150 01151 void MythRenderD3D9::SetTextureVertices(IDirect3DDevice9* dev, bool enable) 01152 { 01153 if (m_texture_vertices == enable) 01154 return; 01155 m_texture_vertices = enable; 01156 01157 if (dev) 01158 dev->SetFVF(enable ? D3DFVF_TEXTUREVERTEX : D3DFVF_VERTEX); 01159 } 01160 01161 IDirect3DDevice9* MythRenderD3D9::AcquireDevice(void) 01162 { 01163 m_lock.lock(); 01164 #ifdef USING_DXVA2 01165 if (m_deviceManager) 01166 { 01167 IDirect3DDevice9* result = NULL; 01168 01169 HRESULT hr = IDirect3DDeviceManager9_LockDevice(m_deviceManager, m_deviceHandle, &result, true); 01170 01171 if (hr == DXVA2_E_NEW_VIDEO_DEVICE) 01172 { 01173 hr = IDirect3DDeviceManager9_CloseDeviceHandle(m_deviceManager, m_deviceHandle); 01174 01175 if (SUCCEEDED(hr)) 01176 hr = IDirect3DDeviceManager9_OpenDeviceHandle(m_deviceManager, &m_deviceHandle); 01177 01178 if (SUCCEEDED(hr)) 01179 hr = IDirect3DDeviceManager9_LockDevice(m_deviceManager, m_deviceHandle, &result, true); 01180 } 01181 01182 if (SUCCEEDED(hr)) 01183 return result; 01184 01185 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to acquire D3D9 device."); 01186 m_lock.unlock(); 01187 return NULL; 01188 } 01189 #endif 01190 return m_rootD3DDevice; 01191 } 01192 01193 void MythRenderD3D9::ReleaseDevice(void) 01194 { 01195 #ifdef USING_DXVA2 01196 if (m_deviceManager) 01197 { 01198 HRESULT hr = IDirect3DDeviceManager9_UnlockDevice(m_deviceManager, m_deviceHandle, false); 01199 if (!SUCCEEDED(hr)) 01200 LOG(VB_GENERAL, LOG_ERR, D3DLOC + "Failed to release D3D9 device."); 01201 } 01202 #endif 01203 m_lock.unlock(); 01204 } 01205 01206 #ifdef USING_DXVA2 01207 typedef HRESULT (WINAPI *CreateDeviceManager9Ptr)(UINT *pResetToken, 01208 IDirect3DDeviceManager9 **); 01209 #endif 01210 01211 void MythRenderD3D9::CreateDeviceManager(void) 01212 { 01213 #ifdef USING_DXVA2 01214 CreateDeviceManager9Ptr CreateDeviceManager9 = 01215 (CreateDeviceManager9Ptr)ResolveAddress("DXVA2", 01216 "DXVA2CreateDirect3DDeviceManager9"); 01217 if (CreateDeviceManager9) 01218 { 01219 UINT resetToken = 0; 01220 HRESULT hr = CreateDeviceManager9(&resetToken, &m_deviceManager); 01221 if (SUCCEEDED(hr)) 01222 { 01223 IDirect3DDeviceManager9_ResetDevice(m_deviceManager, m_rootD3DDevice, resetToken); 01224 IDirect3DDeviceManager9_AddRef(m_deviceManager); 01225 m_deviceManagerToken = resetToken; 01226 LOG(VB_GENERAL, LOG_INFO, D3DLOC + "Created DXVA2 device manager."); 01227 hr = IDirect3DDeviceManager9_OpenDeviceHandle(m_deviceManager, &m_deviceHandle); 01228 if (SUCCEEDED(hr)) 01229 { 01230 LOG(VB_GENERAL, LOG_INFO, D3DLOC + "Retrieved device handle."); 01231 return; 01232 } 01233 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 01234 "Failed to retrieve device handle."); 01235 } 01236 else 01237 { 01238 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 01239 "Failed to create DXVA2 device manager."); 01240 } 01241 } 01242 else 01243 { 01244 LOG(VB_GENERAL, LOG_ERR, D3DLOC + 01245 "Failed to get DXVA2CreateDirect3DDeviceManager9 proc address."); 01246 } 01247 #endif 01248 m_deviceManager = NULL; 01249 m_deviceManagerToken = 0; 01250 LOG(VB_GENERAL, LOG_NOTICE, D3DLOC + 01251 "DXVA2 support not available - not using device manager"); 01252 } 01253 01254 void MythRenderD3D9::DestroyDeviceManager(void) 01255 { 01256 #ifdef USING_DXVA2 01257 if (m_deviceHandle && m_deviceManager) 01258 IDirect3DDeviceManager9_CloseDeviceHandle(m_deviceManager, m_deviceHandle); 01259 if (m_deviceManager) 01260 IDirect3DDeviceManager9_Release(m_deviceManager); 01261 #endif 01262 m_deviceHandle = NULL; 01263 m_deviceManager = NULL; 01264 }
1.7.6.1