Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Windows: Refactor and extend MythRenderD3D9 for multithreaded DXVA2 s…

…upport.

- Add IDirect3DDeviceManager9 support when DXVA2 is available.

When DXVA2 support is not available, we simply 'acquire' the device by returning a pointer to it and locking our mutex.
If device manager functionality is available, we create a devicemanager and use this to acquire the device.
The device manager is also made available to other objects to allow them safe access to the underlying device (which will be used be DXVA2 decoder and video processor objects).
Device manager locking is not recursive, hence several private functions have also been refactored to avoid lockups when using DXVA2.

- Add a convenience class to acquire and automatically release the device (D3D9Locker).
- Use QLibrary to load and resolve D3D9 (and DXVA2) libs.
- Create the D3D9 device with multithreaded support.
  • Loading branch information...
commit 2e2a90074aacf2bd70e992a47ec4afb82251bcc6 1 parent 889f533
authored
406  mythtv/libs/libmythui/mythrender_d3d9.cpp
@@ -3,6 +3,7 @@
3 3
 #include <algorithm>
4 4
 using std::min;
5 5
 
  6
+#include <QLibrary>
6 7
 #include <QRect>
7 8
 #include <QMap>
8 9
 #include <QMutex>
@@ -10,6 +11,8 @@ using std::min;
10 11
 #include "mythverbose.h"
11 12
 #include "mythrender_d3d9.h"
12 13
 
  14
+#define DXVA2_E_NEW_VIDEO_DEVICE MAKE_HRESULT(1, 4, 4097)
  15
+
13 16
 class MythD3DVertexBuffer
14 17
 {
15 18
   public:
@@ -159,14 +162,40 @@ QRect D3D9Image::GetRect(void)
159 162
 #define D3DLOC QString("MythRenderD3D9: ")
160 163
 #define D3DERR QString("MythRenderD3D9 Error: ")
161 164
 
  165
+D3D9Locker::D3D9Locker(MythRenderD3D9 *render) : m_render(render)
  166
+{
  167
+}
  168
+
  169
+D3D9Locker::~D3D9Locker()
  170
+{
  171
+    if (m_render)
  172
+        m_render->ReleaseDevice();
  173
+}
  174
+
  175
+IDirect3DDevice9* D3D9Locker::Acquire(void)
  176
+{
  177
+    IDirect3DDevice9* result = NULL;
  178
+    if (m_render)
  179
+        result = m_render->AcquireDevice();
  180
+    if (!result)
  181
+        VERBOSE(VB_IMPORTANT, "D3D9Locker: Failed to acquire device.");
  182
+    return result;
  183
+}
  184
+
  185
+void* MythRenderD3D9::ResolveAddress(const char* lib, const char* proc)
  186
+{
  187
+    return QLibrary::resolve(lib, proc);
  188
+}
  189
+
162 190
 MythRenderD3D9::MythRenderD3D9(void)
163  
-  : m_d3d(NULL), m_d3dDevice(NULL),
  191
+  : m_d3d(NULL), m_rootD3DDevice(NULL),
164 192
     m_adaptor_fmt(D3DFMT_UNKNOWN),
165 193
     m_videosurface_fmt(D3DFMT_UNKNOWN),
166 194
     m_surface_fmt(D3DFMT_UNKNOWN), m_texture_fmt(D3DFMT_A8R8G8B8),
167 195
     m_rect_vertexbuffer(NULL), m_default_surface(NULL), m_current_surface(NULL),
168 196
     m_lock(QMutex::Recursive),
169  
-    m_blend(true), m_multi_texturing(true), m_texture_vertices(true)
  197
+    m_blend(true), m_multi_texturing(true), m_texture_vertices(true),
  198
+    m_deviceManager(NULL), m_deviceHandle(NULL), m_deviceManagerToken(0)
170 199
 {
171 200
 }
172 201
 
@@ -187,10 +216,12 @@ MythRenderD3D9::~MythRenderD3D9(void)
187 216
     DeleteVertexBuffers();
188 217
     DeleteSurfaces();
189 218
 
190  
-    if (m_d3dDevice)
  219
+    DestroyDeviceManager();
  220
+
  221
+    if (m_rootD3DDevice)
191 222
     {
192 223
         VERBOSE(VB_GENERAL, D3DLOC + "Deleting D3D9 device.");
193  
-        m_d3dDevice->Release();
  224
+        m_rootD3DDevice->Release();
194 225
     }
195 226
 
196 227
     if (m_d3d)
@@ -255,27 +286,14 @@ bool MythRenderD3D9::Create(QSize size, HWND window)
255 286
     QMutexLocker locker(&m_lock);
256 287
 
257 288
     typedef LPDIRECT3D9 (WINAPI *LPFND3DC)(UINT SDKVersion);
258  
-    static  HINSTANCE hD3DLib            = NULL;
259 289
     static  LPFND3DC  OurDirect3DCreate9 = NULL;
260 290
 
261  
-    if (!hD3DLib)
262  
-    {
263  
-        hD3DLib = LoadLibrary(TEXT("D3D9.DLL"));
264  
-        if (!hD3DLib)
265  
-            VERBOSE(VB_IMPORTANT, D3DERR + "Cannot load 'd3d9.dll'.");
266  
-    }
267  
-
268  
-    if (hD3DLib && !OurDirect3DCreate9)
  291
+    OurDirect3DCreate9 = (LPFND3DC)ResolveAddress("D3D9","Direct3DCreate9");
  292
+    if (!OurDirect3DCreate9)
269 293
     {
270  
-        OurDirect3DCreate9 = (LPFND3DC) GetProcAddress(
271  
-            hD3DLib, TEXT("Direct3DCreate9"));
272  
-        if (!OurDirect3DCreate9)
273  
-            VERBOSE(VB_IMPORTANT, D3DERR + "Cannot locate reference to "
274  
-                                           "Direct3DCreate9 ABI in DLL");
275  
-    }
276  
-
277  
-    if (!(hD3DLib && OurDirect3DCreate9))
  294
+        VERBOSE(VB_IMPORTANT, D3DERR + "FATAL :Failed to find Direct3DCreate9.");
278 295
         return false;
  296
+    }
279 297
 
280 298
     m_d3d = OurDirect3DCreate9(D3D_SDK_VERSION);
281 299
     if (!m_d3d)
@@ -382,8 +400,9 @@ bool MythRenderD3D9::Create(QSize size, HWND window)
382 400
 
383 401
     if (D3D_OK != m_d3d->CreateDevice(D3DADAPTER_DEFAULT,
384 402
                                       D3DDEVTYPE_HAL, d3dpp.hDeviceWindow,
385  
-                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
386  
-                                      &d3dpp, &m_d3dDevice))
  403
+                                      D3DCREATE_SOFTWARE_VERTEXPROCESSING |
  404
+                                      D3DCREATE_MULTITHREADED,
  405
+                                      &d3dpp, &m_rootD3DDevice))
387 406
     {
388 407
         VERBOSE(VB_IMPORTANT, D3DERR + "Could not create the D3D device.");
389 408
         return false;
@@ -420,15 +439,20 @@ bool MythRenderD3D9::Create(QSize size, HWND window)
420 439
         }
421 440
     }
422 441
 
  442
+    CreateDeviceManager();
423 443
     Init2DState();
424 444
     return true;
425 445
 }
426 446
 
427 447
 bool MythRenderD3D9::Test(bool &reset)
428 448
 {
429  
-    QMutexLocker locker(&m_lock);
  449
+    D3D9Locker locker(this);
  450
+    IDirect3DDevice9* dev = locker.Acquire();
  451
+    if (!dev)
  452
+        return false;
  453
+
430 454
     bool result = true;
431  
-    HRESULT hr = m_d3dDevice->TestCooperativeLevel();
  455
+    HRESULT hr = dev->TestCooperativeLevel();
432 456
     if (FAILED(hr))
433 457
     {
434 458
         switch (hr)
@@ -465,9 +489,13 @@ bool MythRenderD3D9::Test(bool &reset)
465 489
 
466 490
 bool MythRenderD3D9::ClearBuffer(void)
467 491
 {
468  
-    QMutexLocker locker(&m_lock);
469  
-    HRESULT hr = m_d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET,
470  
-                                    D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0);
  492
+    D3D9Locker locker(this);
  493
+    IDirect3DDevice9* dev = locker.Acquire();
  494
+    if (!dev)
  495
+        return false;
  496
+
  497
+    HRESULT hr = dev->Clear(0, NULL, D3DCLEAR_TARGET,
  498
+                            D3DCOLOR_ARGB(0, 0, 0, 0), 1.0f, 0);
471 499
     if (FAILED(hr))
472 500
     {
473 501
         VERBOSE(VB_IMPORTANT, D3DERR + "Clear() failed.");
@@ -478,8 +506,12 @@ bool MythRenderD3D9::ClearBuffer(void)
478 506
 
479 507
 bool MythRenderD3D9::Begin(void)
480 508
 {
481  
-    QMutexLocker locker(&m_lock);
482  
-    HRESULT hr = m_d3dDevice->BeginScene();
  509
+    D3D9Locker locker(this);
  510
+    IDirect3DDevice9* dev = locker.Acquire();
  511
+    if (!dev)
  512
+        return false;
  513
+
  514
+    HRESULT hr = dev->BeginScene();
483 515
     if (FAILED(hr))
484 516
     {
485 517
         VERBOSE(VB_IMPORTANT, D3DERR + "BeginScene() failed.");
@@ -490,8 +522,12 @@ bool MythRenderD3D9::Begin(void)
490 522
 
491 523
 bool MythRenderD3D9::End(void)
492 524
 {
493  
-    QMutexLocker locker(&m_lock);
494  
-    HRESULT hr = m_d3dDevice->EndScene();
  525
+    D3D9Locker locker(this);
  526
+    IDirect3DDevice9* dev = locker.Acquire();
  527
+    if (!dev)
  528
+        return false;
  529
+
  530
+    HRESULT hr = dev->EndScene();
495 531
     if (FAILED(hr))
496 532
     {
497 533
         VERBOSE(VB_IMPORTANT, D3DERR + "EndScene() failed.");
@@ -514,7 +550,11 @@ bool MythRenderD3D9::StretchRect(IDirect3DTexture9 *texture,
514 550
        (known_surface && !m_surfaces.contains(surface)))
515 551
         return false;
516 552
 
517  
-    QMutexLocker locker(&m_lock);
  553
+    D3D9Locker locker(this);
  554
+    IDirect3DDevice9* dev = locker.Acquire();
  555
+    if (!dev)
  556
+        return false;
  557
+
518 558
     LPDIRECT3DSURFACE9 d3ddest;
519 559
     HRESULT hr = texture->GetSurfaceLevel(0, &d3ddest);
520 560
     if (FAILED(hr))
@@ -523,7 +563,7 @@ bool MythRenderD3D9::StretchRect(IDirect3DTexture9 *texture,
523 563
         return false;
524 564
     }
525 565
 
526  
-    hr = m_d3dDevice->StretchRect(surface, NULL, d3ddest,
  566
+    hr = dev->StretchRect(surface, NULL, d3ddest,
527 567
                                   NULL, D3DTEXF_POINT);
528 568
     d3ddest->Release();
529 569
     if (FAILED(hr))
@@ -539,18 +579,21 @@ bool MythRenderD3D9::DrawTexturedQuad(IDirect3DVertexBuffer9 *vertexbuffer)
539 579
     if (!m_vertexbuffers.contains(vertexbuffer))
540 580
         return false;
541 581
 
542  
-    QMutexLocker locker(&m_lock);
  582
+    D3D9Locker locker(this);
  583
+    IDirect3DDevice9* dev = locker.Acquire();
  584
+    if (!dev)
  585
+        return false;
543 586
 
544 587
     IDirect3DTexture9 *texture = m_vertexbuffers[vertexbuffer].m_texture;
545 588
 
546  
-    if (texture && !SetTexture(texture))
  589
+    if (texture && !SetTexture(dev, texture))
547 590
         return false;
548 591
 
549  
-    EnableBlending(true);
550  
-    SetTextureVertices(true);
551  
-    MultiTexturing(false);
  592
+    EnableBlending(dev, true);
  593
+    SetTextureVertices(dev, true);
  594
+    MultiTexturing(dev, false);
552 595
 
553  
-    HRESULT hr = m_d3dDevice->SetStreamSource(0, vertexbuffer,
  596
+    HRESULT hr = dev->SetStreamSource(0, vertexbuffer,
554 597
                                               0, sizeof(TEXTUREVERTEX));
555 598
     if (FAILED(hr))
556 599
     {
@@ -558,7 +601,7 @@ bool MythRenderD3D9::DrawTexturedQuad(IDirect3DVertexBuffer9 *vertexbuffer)
558 601
         return false;
559 602
     }
560 603
 
561  
-    hr = m_d3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
  604
+    hr = dev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
562 605
     if (FAILED(hr))
563 606
     {
564 607
         VERBOSE(VB_IMPORTANT, D3DERR + "DrawPrimitive() failed");
@@ -570,9 +613,14 @@ bool MythRenderD3D9::DrawTexturedQuad(IDirect3DVertexBuffer9 *vertexbuffer)
570 613
 
571 614
 void MythRenderD3D9::DrawRect(const QRect &rect, const QColor &color)
572 615
 {
  616
+    D3D9Locker locker(this);
  617
+    IDirect3DDevice9* dev = locker.Acquire();
  618
+    if (!dev)
  619
+        return;
  620
+
573 621
     if (!m_rect_vertexbuffer)
574 622
     {
575  
-        HRESULT hr = m_d3dDevice->CreateVertexBuffer(
  623
+        HRESULT hr = dev->CreateVertexBuffer(
576 624
                 sizeof(VERTEX)*4,     D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
577 625
                 D3DFVF_VERTEX,        D3DPOOL_DEFAULT,
578 626
                 &m_rect_vertexbuffer, NULL);
@@ -584,12 +632,11 @@ void MythRenderD3D9::DrawRect(const QRect &rect, const QColor &color)
584 632
         }
585 633
     }
586 634
 
587  
-    EnableBlending(false);
588  
-    SetTextureVertices(false);
589  
-    MultiTexturing(false);
590  
-    SetTexture(NULL, 0);
  635
+    EnableBlending(dev, false);
  636
+    SetTextureVertices(dev, false);
  637
+    MultiTexturing(dev, false);
  638
+    SetTexture(dev, NULL, 0);
591 639
 
592  
-    QMutexLocker locker(&m_lock);
593 640
     D3DCOLOR clr = D3DCOLOR_ARGB(color.alpha(), color.red(),
594 641
                                  color.green(), color.blue());
595 642
     VERTEX *p_vertices;
@@ -629,7 +676,7 @@ void MythRenderD3D9::DrawRect(const QRect &rect, const QColor &color)
629 676
         return;
630 677
     }
631 678
 
632  
-    hr = m_d3dDevice->SetStreamSource(0, m_rect_vertexbuffer,
  679
+    hr = dev->SetStreamSource(0, m_rect_vertexbuffer,
633 680
                                       0, sizeof(VERTEX));
634 681
     if (FAILED(hr))
635 682
     {
@@ -637,7 +684,7 @@ void MythRenderD3D9::DrawRect(const QRect &rect, const QColor &color)
637 684
         return;
638 685
     }
639 686
 
640  
-    hr = m_d3dDevice->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
  687
+    hr = dev->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2);
641 688
     if (FAILED(hr))
642 689
     {
643 690
         VERBOSE(VB_IMPORTANT, D3DERR + "DrawPrimitive() failed");
@@ -645,42 +692,50 @@ void MythRenderD3D9::DrawRect(const QRect &rect, const QColor &color)
645 692
     }
646 693
 }
647 694
 
648  
-void MythRenderD3D9::MultiTexturing(bool enable, IDirect3DTexture9 *texture)
  695
+void MythRenderD3D9::MultiTexturing(IDirect3DDevice9* dev, bool enable,
  696
+                                    IDirect3DTexture9 *texture)
649 697
 {
650  
-    if (!m_d3dDevice || (m_multi_texturing == enable))
  698
+    if (m_multi_texturing == enable)
  699
+        return;
  700
+
  701
+    if (!dev)
651 702
         return;
652 703
 
653 704
     if (enable)
654 705
     {
655  
-        SetTexture(texture, 1);
656  
-        m_d3dDevice->SetTextureStageState(1, D3DTSS_COLOROP,   D3DTOP_SELECTARG2);
657  
-        m_d3dDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
658  
-        m_d3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
659  
-        m_d3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1);
660  
-        m_d3dDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
661  
-        m_d3dDevice->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
662  
-        m_d3dDevice->SetTextureStageState(2, D3DTSS_COLOROP,   D3DTOP_DISABLE);
663  
-        m_d3dDevice->SetTextureStageState(2, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
  706
+        SetTexture(dev, texture, 1);
  707
+        dev->SetTextureStageState(1, D3DTSS_COLOROP,   D3DTOP_SELECTARG2);
  708
+        dev->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  709
+        dev->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT);
  710
+        dev->SetTextureStageState(1, D3DTSS_ALPHAOP,   D3DTOP_SELECTARG1);
  711
+        dev->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  712
+        dev->SetTextureStageState(1, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
  713
+        dev->SetTextureStageState(2, D3DTSS_COLOROP,   D3DTOP_DISABLE);
  714
+        dev->SetTextureStageState(2, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
664 715
     }
665 716
     else
666 717
     {
667  
-        m_d3dDevice->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_MODULATE);
668  
-        m_d3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
669  
-        m_d3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
670  
-        m_d3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE);
671  
-        m_d3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
672  
-        m_d3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
673  
-        m_d3dDevice->SetTextureStageState(1, D3DTSS_COLOROP,   D3DTOP_DISABLE);
674  
-        m_d3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
675  
-        SetTexture(NULL, 1);
  718
+        dev->SetTextureStageState(0, D3DTSS_COLOROP,   D3DTOP_MODULATE);
  719
+        dev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
  720
+        dev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
  721
+        dev->SetTextureStageState(0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE);
  722
+        dev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
  723
+        dev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT);
  724
+        dev->SetTextureStageState(1, D3DTSS_COLOROP,   D3DTOP_DISABLE);
  725
+        dev->SetTextureStageState(1, D3DTSS_ALPHAOP,   D3DTOP_DISABLE);
  726
+        SetTexture(dev, NULL, 1);
676 727
     }
677 728
     m_multi_texturing = enable;
678 729
 }
679 730
 
680 731
 bool MythRenderD3D9::Present(HWND win)
681 732
 {
682  
-    QMutexLocker locker(&m_lock);
683  
-    HRESULT hr = m_d3dDevice->Present(NULL, NULL, win, NULL);
  733
+    D3D9Locker locker(this);
  734
+    IDirect3DDevice9* dev = locker.Acquire();
  735
+    if (!dev)
  736
+        return false;
  737
+
  738
+    HRESULT hr = dev->Present(NULL, NULL, win, NULL);
684 739
     if (FAILED(hr))
685 740
     {
686 741
         VERBOSE(VB_IMPORTANT, D3DERR + "Present() failed)");
@@ -699,13 +754,18 @@ QRect MythRenderD3D9::GetRect(IDirect3DVertexBuffer9 *vertexbuffer)
699 754
 
700 755
 bool MythRenderD3D9::SetRenderTarget(IDirect3DTexture9 *texture)
701 756
 {
  757
+    D3D9Locker locker(this);
  758
+    IDirect3DDevice9* dev = locker.Acquire();
  759
+    if (!dev)
  760
+        return false;
  761
+
702 762
     bool ret = true;
703 763
     HRESULT hr;
704 764
     if (texture && m_textures.contains(texture))
705 765
     {
706 766
         if (!m_default_surface)
707 767
         {
708  
-            hr = m_d3dDevice->GetRenderTarget(0, &m_default_surface);
  768
+            hr = dev->GetRenderTarget(0, &m_default_surface);
709 769
             if (FAILED(hr))
710 770
             {
711 771
                 VERBOSE(VB_IMPORTANT, QString("Failed to get default surface."));
@@ -722,7 +782,7 @@ bool MythRenderD3D9::SetRenderTarget(IDirect3DTexture9 *texture)
722 782
             if (m_current_surface && m_current_surface != new_surface)
723 783
                 m_current_surface->Release();
724 784
             m_current_surface = new_surface;
725  
-            hr = m_d3dDevice->SetRenderTarget(0, m_current_surface);
  785
+            hr = dev->SetRenderTarget(0, m_current_surface);
726 786
             if (FAILED(hr))
727 787
                 VERBOSE(VB_IMPORTANT, QString("Failed to set render target."));
728 788
         }
@@ -731,7 +791,7 @@ bool MythRenderD3D9::SetRenderTarget(IDirect3DTexture9 *texture)
731 791
     {
732 792
         if (m_default_surface)
733 793
         {
734  
-            hr = m_d3dDevice->SetRenderTarget(0, m_default_surface);
  794
+            hr = dev->SetRenderTarget(0, m_default_surface);
735 795
             if (FAILED(hr))
736 796
                 VERBOSE(VB_IMPORTANT, QString("Failed to set render target."));
737 797
         }
@@ -743,9 +803,13 @@ bool MythRenderD3D9::SetRenderTarget(IDirect3DTexture9 *texture)
743 803
     return ret;
744 804
 }
745 805
 
746  
-bool MythRenderD3D9::SetTexture(IDirect3DTexture9 *texture, int num)
  806
+bool MythRenderD3D9::SetTexture(IDirect3DDevice9* dev,
  807
+                                IDirect3DTexture9 *texture, int num)
747 808
 {
748  
-    HRESULT hr = m_d3dDevice->SetTexture(num, (LPDIRECT3DBASETEXTURE9)texture);
  809
+    if (!dev)
  810
+        return false;
  811
+
  812
+    HRESULT hr = dev->SetTexture(num, (LPDIRECT3DBASETEXTURE9)texture);
749 813
     if (FAILED(hr))
750 814
     {
751 815
         VERBOSE(VB_IMPORTANT, D3DERR + "SetTexture() failed");
@@ -756,10 +820,14 @@ bool MythRenderD3D9::SetTexture(IDirect3DTexture9 *texture, int num)
756 820
 
757 821
 IDirect3DTexture9* MythRenderD3D9::CreateTexture(const QSize &size)
758 822
 {
759  
-    QMutexLocker locker(&m_lock);
  823
+    D3D9Locker locker(this);
  824
+    IDirect3DDevice9* dev = locker.Acquire();
  825
+    if (!dev)
  826
+        return NULL;
  827
+
760 828
     IDirect3DTexture9* temp_texture = NULL;
761 829
 
762  
-    HRESULT hr = m_d3dDevice->CreateTexture(
  830
+    HRESULT hr = dev->CreateTexture(
763 831
                     size.width(),  size.height(), 1, D3DUSAGE_RENDERTARGET,
764 832
                     m_texture_fmt, D3DPOOL_DEFAULT, &temp_texture, NULL);
765 833
 
@@ -793,12 +861,16 @@ void MythRenderD3D9::DeleteTexture(IDirect3DTexture9* texture)
793 861
 
794 862
 IDirect3DSurface9* MythRenderD3D9::CreateSurface(const QSize &size, bool video)
795 863
 {
796  
-    QMutexLocker locker(&m_lock);
  864
+    D3D9Locker locker(this);
  865
+    IDirect3DDevice9* dev = locker.Acquire();
  866
+    if (!dev)
  867
+        return NULL;
  868
+
797 869
     IDirect3DSurface9* temp_surface = NULL;
798 870
 
799 871
     D3DFORMAT format = video ? m_videosurface_fmt : m_surface_fmt;
800 872
 
801  
-    HRESULT hr = m_d3dDevice->CreateOffscreenPlainSurface(
  873
+    HRESULT hr = dev->CreateOffscreenPlainSurface(
802 874
                     size.width(), size.height(), format,
803 875
                     D3DPOOL_DEFAULT, &temp_surface, NULL);
804 876
 
@@ -809,7 +881,7 @@ IDirect3DSurface9* MythRenderD3D9::CreateSurface(const QSize &size, bool video)
809 881
     }
810 882
 
811 883
     m_surfaces[temp_surface] = MythD3DSurface(size, format);
812  
-    m_d3dDevice->ColorFill(temp_surface, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0) );
  884
+    dev->ColorFill(temp_surface, NULL, D3DCOLOR_ARGB(0xFF, 0, 0, 0) );
813 885
 
814 886
     return temp_surface;
815 887
 }
@@ -911,13 +983,16 @@ void MythRenderD3D9::ReleaseBuffer(IDirect3DSurface9* surface)
911 983
 
912 984
 IDirect3DVertexBuffer9* MythRenderD3D9::CreateVertexBuffer(IDirect3DTexture9* texture)
913 985
 {
914  
-    QMutexLocker locker(&m_lock);
  986
+    D3D9Locker locker(this);
  987
+    IDirect3DDevice9* dev = locker.Acquire();
  988
+    if (!dev)
  989
+        return NULL;
915 990
 
916 991
     if (texture && !m_textures.contains(texture))
917 992
         return false;
918 993
 
919 994
     IDirect3DVertexBuffer9* temp_vbuf = NULL;
920  
-    HRESULT hr = m_d3dDevice->CreateVertexBuffer(
  995
+    HRESULT hr = dev->CreateVertexBuffer(
921 996
         sizeof(TEXTUREVERTEX)*4, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
922 997
         D3DFVF_TEXTUREVERTEX,    D3DPOOL_DEFAULT,
923 998
         &temp_vbuf,             NULL);
@@ -1053,44 +1128,153 @@ bool MythRenderD3D9::UpdateVertexBuffer(IDirect3DVertexBuffer9* vertexbuffer,
1053 1128
 
1054 1129
 void MythRenderD3D9::Init2DState(void)
1055 1130
 {
1056  
-    if (!m_d3dDevice)
  1131
+    IDirect3DDevice9* dev = AcquireDevice();
  1132
+    if (!dev)
1057 1133
         return;
1058 1134
 
1059  
-    m_d3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1060  
-    m_d3dDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1061  
-    m_d3dDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
1062  
-    m_d3dDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
1063  
-    m_d3dDevice->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
1064  
-    m_d3dDevice->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
1065  
-    m_d3dDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
1066  
-    m_d3dDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
1067  
-    m_d3dDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(255,255,255));
1068  
-    m_d3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
1069  
-    m_d3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
1070  
-    m_d3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
1071  
-    m_d3dDevice->SetRenderState(D3DRS_DITHERENABLE, TRUE);
1072  
-    m_d3dDevice->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1073  
-    m_d3dDevice->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA);
1074  
-    m_d3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
1075  
-    m_d3dDevice->SetVertexShader(NULL);
1076  
-
1077  
-    SetTextureVertices(false);
1078  
-    MultiTexturing(false);
1079  
-    EnableBlending(false);
  1135
+    dev->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
  1136
+    dev->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
  1137
+    dev->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  1138
+    dev->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  1139
+    dev->SetSamplerState(1, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
  1140
+    dev->SetSamplerState(1, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
  1141
+    dev->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
  1142
+    dev->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
  1143
+    dev->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(255,255,255));
  1144
+    dev->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
  1145
+    dev->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
  1146
+    dev->SetRenderState(D3DRS_LIGHTING, FALSE);
  1147
+    dev->SetRenderState(D3DRS_DITHERENABLE, TRUE);
  1148
+    dev->SetRenderState(D3DRS_STENCILENABLE, FALSE);
  1149
+    dev->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_SRCALPHA);
  1150
+    dev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
  1151
+    dev->SetVertexShader(NULL);
  1152
+    SetTextureVertices(dev, false);
  1153
+    MultiTexturing(dev, false);
  1154
+    EnableBlending(dev, false);
  1155
+
  1156
+    ReleaseDevice();
1080 1157
 }
1081 1158
 
1082  
-void MythRenderD3D9::EnableBlending(bool enable)
  1159
+void MythRenderD3D9::EnableBlending(IDirect3DDevice9* dev, bool enable)
1083 1160
 {
1084  
-    if (!m_d3dDevice || (m_blend == enable))
  1161
+    if (m_blend == enable)
1085 1162
         return;
1086 1163
     m_blend = enable;
1087  
-    m_d3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, enable);
  1164
+
  1165
+    if (dev)
  1166
+        dev->SetRenderState(D3DRS_ALPHABLENDENABLE, enable);
1088 1167
 }
1089 1168
 
1090  
-void MythRenderD3D9::SetTextureVertices(bool enable)
  1169
+void MythRenderD3D9::SetTextureVertices(IDirect3DDevice9* dev, bool enable)
1091 1170
 {
1092  
-    if (!m_d3dDevice || (m_texture_vertices == enable))
  1171
+    if (m_texture_vertices == enable)
1093 1172
         return;
1094 1173
     m_texture_vertices = enable;
1095  
-    m_d3dDevice->SetFVF(enable ? D3DFVF_TEXTUREVERTEX : D3DFVF_VERTEX);
  1174
+
  1175
+    if (dev)
  1176
+        dev->SetFVF(enable ? D3DFVF_TEXTUREVERTEX : D3DFVF_VERTEX);
  1177
+}
  1178
+
  1179
+IDirect3DDevice9* MythRenderD3D9::AcquireDevice(void)
  1180
+{
  1181
+    m_lock.lock();
  1182
+#ifdef USING_DXVA2
  1183
+    if (m_deviceManager)
  1184
+    {
  1185
+        IDirect3DDevice9* result = NULL;
  1186
+
  1187
+        HRESULT hr = IDirect3DDeviceManager9_LockDevice(m_deviceManager, m_deviceHandle, &result, true);
  1188
+
  1189
+        if (hr == DXVA2_E_NEW_VIDEO_DEVICE)
  1190
+        {
  1191
+            hr = IDirect3DDeviceManager9_CloseDeviceHandle(m_deviceManager, m_deviceHandle);
  1192
+
  1193
+            if (SUCCEEDED(hr))
  1194
+                hr = IDirect3DDeviceManager9_OpenDeviceHandle(m_deviceManager, &m_deviceHandle);
  1195
+
  1196
+            if (SUCCEEDED(hr))
  1197
+                hr = IDirect3DDeviceManager9_LockDevice(m_deviceManager, m_deviceHandle, &result, true);
  1198
+        }
  1199
+
  1200
+        if (SUCCEEDED(hr))
  1201
+            return result;
  1202
+
  1203
+        VERBOSE(VB_IMPORTANT, D3DERR + "Failed to acquire D3D9 device.");
  1204
+        m_lock.unlock();
  1205
+        return NULL;
  1206
+    }
  1207
+#endif
  1208
+    return m_rootD3DDevice;
  1209
+}
  1210
+
  1211
+void MythRenderD3D9::ReleaseDevice(void)
  1212
+{
  1213
+#ifdef USING_DXVA2
  1214
+    if (m_deviceManager)
  1215
+    {
  1216
+        HRESULT hr = IDirect3DDeviceManager9_UnlockDevice(m_deviceManager, m_deviceHandle, false);
  1217
+        if (!SUCCEEDED(hr))
  1218
+            VERBOSE(VB_IMPORTANT, D3DERR + "Failed to release D3D9 device.");
  1219
+    }
  1220
+#endif
  1221
+    m_lock.unlock();
  1222
+}
  1223
+
  1224
+#ifdef USING_DXVA2
  1225
+typedef HRESULT (WINAPI *CreateDeviceManager9Ptr)(UINT *pResetToken,
  1226
+                                                  IDirect3DDeviceManager9 **);
  1227
+#endif
  1228
+
  1229
+void MythRenderD3D9::CreateDeviceManager(void)
  1230
+{
  1231
+#ifdef USING_DXVA2
  1232
+    CreateDeviceManager9Ptr CreateDeviceManager9 =
  1233
+        (CreateDeviceManager9Ptr)ResolveAddress("DXVA2",
  1234
+                                                "DXVA2CreateDirect3DDeviceManager9");
  1235
+    if (CreateDeviceManager9)
  1236
+    {
  1237
+        UINT resetToken = 0;
  1238
+        HRESULT hr = CreateDeviceManager9(&resetToken, &m_deviceManager);
  1239
+        if (SUCCEEDED(hr))
  1240
+        {
  1241
+            IDirect3DDeviceManager9_ResetDevice(m_deviceManager, m_rootD3DDevice, resetToken);
  1242
+            IDirect3DDeviceManager9_AddRef(m_deviceManager);
  1243
+            m_deviceManagerToken = resetToken;
  1244
+            VERBOSE(VB_GENERAL, D3DLOC + "Created DXVA2 device manager.");
  1245
+            hr = IDirect3DDeviceManager9_OpenDeviceHandle(m_deviceManager, &m_deviceHandle);
  1246
+            if (SUCCEEDED(hr))
  1247
+            {
  1248
+                VERBOSE(VB_GENERAL, D3DLOC + "Retrieved device handle.");
  1249
+                return;
  1250
+            }
  1251
+            VERBOSE(VB_IMPORTANT, D3DERR + "Failed to retrieve device handle.");
  1252
+        }
  1253
+        else
  1254
+        {
  1255
+            VERBOSE(VB_IMPORTANT, D3DERR + "Failed to create DXVA2 device manager.");
  1256
+        }
  1257
+    }
  1258
+    else
  1259
+    {
  1260
+        VERBOSE(VB_IMPORTANT, D3DERR +
  1261
+            "Failed to get DXVA2CreateDirect3DDeviceManager9 proc address.");
  1262
+    }
  1263
+#endif
  1264
+    m_deviceManager = NULL;
  1265
+    m_deviceManagerToken = 0;
  1266
+    VERBOSE(VB_IMPORTANT, D3DLOC +
  1267
+        "DXVA2 support not available - not using device manager");
  1268
+}
  1269
+
  1270
+void MythRenderD3D9::DestroyDeviceManager(void)
  1271
+{
  1272
+#ifdef USING_DXVA2
  1273
+    if (m_deviceHandle && m_deviceManager)
  1274
+        IDirect3DDeviceManager9_CloseDeviceHandle(m_deviceManager, m_deviceHandle);
  1275
+    if (m_deviceManager)
  1276
+        IDirect3DDeviceManager9_Release(m_deviceManager);
  1277
+#endif
  1278
+    m_deviceHandle  = NULL;
  1279
+    m_deviceManager = NULL;
1096 1280
 }
47  mythtv/libs/libmythui/mythrender_d3d9.h
... ...
@@ -1,12 +1,20 @@
1 1
 #ifndef MYTHRENDER_D3D9_H
2 2
 #define MYTHRENDER_D3D9_H
3 3
 
  4
+#include <QMap>
  5
+
4 6
 #include <windows.h>
5 7
 #include <d3d9.h>
6 8
 
7 9
 #include "mythimage.h"
8 10
 #include "mythuiexp.h"
9 11
 
  12
+#ifdef USING_DXVA2
  13
+#include "dxva2api.h"
  14
+#else
  15
+typedef void* IDirect3DDeviceManager9;
  16
+#endif
  17
+
10 18
 class MythD3DVertexBuffer;
11 19
 class MythD3DSurface;
12 20
 class MythRenderD3D9;
@@ -38,16 +46,27 @@ class MUI_PUBLIC D3D9Image
38 46
     IDirect3DSurface9      *m_surface;
39 47
 };
40 48
 
  49
+class MUI_PUBLIC D3D9Locker
  50
+{
  51
+  public:
  52
+    D3D9Locker(MythRenderD3D9 *render);
  53
+   ~D3D9Locker();
  54
+    IDirect3DDevice9* Acquire(void);
  55
+  private:
  56
+    MythRenderD3D9 *m_render;
  57
+};
  58
+
41 59
 class MUI_PUBLIC MythRenderD3D9
42 60
 {
43 61
   public:
  62
+    static void* ResolveAddress(const char* lib, const char* proc);
  63
+
44 64
     MythRenderD3D9();
45 65
     ~MythRenderD3D9();
46 66
 
47 67
     bool Create(QSize size, HWND window);
48 68
     bool Test(bool &reset);
49 69
 
50  
-    IDirect3DDevice9* GetDevice(void) { return m_d3dDevice; }
51 70
     bool ClearBuffer(void);
52 71
     bool Begin(void);
53 72
     bool End(void);
@@ -80,15 +99,17 @@ class MUI_PUBLIC MythRenderD3D9
80 99
 
81 100
   private:
82 101
     bool                    FormatSupported(D3DFORMAT surface, D3DFORMAT adaptor);
83  
-    bool                    SetTexture(IDirect3DTexture9 *texture, int num = 0);
  102
+    bool                    SetTexture(IDirect3DDevice9* dev,
  103
+                                       IDirect3DTexture9 *texture,
  104
+                                       int num = 0);
84 105
     void                    DeleteTextures(void);
85 106
     void                    DeleteVertexBuffers(void);
86 107
     void                    DeleteSurfaces(void);
87 108
     void                    Init2DState(void);
88  
-    void                    EnableBlending(bool enable);
89  
-    void                    MultiTexturing(bool enable,
  109
+    void                    EnableBlending(IDirect3DDevice9* dev, bool enable);
  110
+    void                    MultiTexturing(IDirect3DDevice9* dev, bool enable,
90 111
                                            IDirect3DTexture9 *texture = NULL);
91  
-    void                    SetTextureVertices(bool enable);
  112
+    void                    SetTextureVertices(IDirect3DDevice9* dev, bool enable);
92 113
 
93 114
   private:
94 115
     QMap<IDirect3DTexture9*, QSize>                    m_textures;
@@ -96,7 +117,7 @@ class MUI_PUBLIC MythRenderD3D9
96 117
     QMap<IDirect3DSurface9*, MythD3DSurface>           m_surfaces;
97 118
 
98 119
     IDirect3D9             *m_d3d;
99  
-    IDirect3DDevice9       *m_d3dDevice;
  120
+    IDirect3DDevice9       *m_rootD3DDevice;
100 121
     D3DFORMAT               m_adaptor_fmt;
101 122
     D3DFORMAT               m_videosurface_fmt;
102 123
     D3DFORMAT               m_surface_fmt;
@@ -109,6 +130,20 @@ class MUI_PUBLIC MythRenderD3D9
109 130
     bool                    m_blend;
110 131
     bool                    m_multi_texturing;
111 132
     bool                    m_texture_vertices;
  133
+
  134
+  public:
  135
+    IDirect3DDevice9* AcquireDevice(void);
  136
+    void              ReleaseDevice(void);
  137
+    IDirect3DDeviceManager9* GetDeviceManager(void) { return m_deviceManager; }
  138
+
  139
+  private:
  140
+    void CreateDeviceManager(void);
  141
+    void DestroyDeviceManager(void);
  142
+
  143
+  private:
  144
+    IDirect3DDeviceManager9 *m_deviceManager;
  145
+    HANDLE                   m_deviceHandle;
  146
+    uint                     m_deviceManagerToken;
112 147
 };
113 148
 
114 149
 #endif // MYTHRENDER_D3D9_H

0 notes on commit 2e2a900

Please sign in to comment.
Something went wrong with that request. Please try again.