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
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
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
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();
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
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 }