MythTV  master
mythpainter_d3d9.cpp
Go to the documentation of this file.
1 // QT headers
2 #include <QApplication>
3 #include <QPainter>
4 #include <QMutex>
5 
6 // Mythdb headers
7 #include "mythlogging.h"
8 
9 // Mythui headers
10 #include "mythpainter_d3d9.h"
11 
12 #define LOC QString("D3D9 Painter: ")
13 
15  MythPainter(), m_render(render)
16 {
17  if (m_render)
18  m_render->IncrRef();
19 }
20 
22 {
23  Teardown();
24 }
25 
26 bool MythD3D9Painter::InitD3D9(QPaintDevice *parent)
27 {
28  if (m_render)
29  return true;
30 
31  QWidget *real_parent = (QWidget*)parent;
32  if (!real_parent)
33  return false;
34 
35  m_render = new MythRenderD3D9();
36  if (!m_render)
37  return false;
38 
39  if (m_render->Create(real_parent->size(), (HWND)real_parent->winId()))
40  return true;
41 
42  Teardown();
43  return false;
44 }
45 
47 {
49  ClearCache();
50  DeleteBitmaps();
51 
52  m_ImageBitmapMap.clear();
53  m_ImageExpireList.clear();
54  m_bitmapDeleteList.clear();
55 
56  if (m_render)
57  {
58  m_render->DecrRef();
59  m_render = nullptr;
60  }
61 }
62 
64 {
65  ClearCache();
66  DeleteBitmaps();
67 }
68 
69 void MythD3D9Painter::Begin(QPaintDevice *parent)
70 {
71  if (!m_render)
72  {
73  if (!InitD3D9(parent))
74  {
75  LOG(VB_GENERAL, LOG_ERR, "Failed to create D3D9 render.");
76  return;
77  }
78  }
79 
80  DeleteBitmaps();
81 
82  if (!m_target)
83  {
84  bool dummy;
85  m_render->Test(dummy); // TODO recreate if necessary
86  }
87  else if (!m_target->SetAsRenderTarget())
88  {
89  LOG(VB_GENERAL, LOG_ERR, "Failed to enable offscreen buffer.");
90  return;
91  }
92 
93  if (m_target)
95  if (m_swap_control)
96  m_render->Begin();
97  MythPainter::Begin(parent);
98 }
99 
101 {
102  if (m_render)
103  {
104  if (m_swap_control)
105  {
106  m_render->End();
107  m_render->Present(nullptr);
108  }
109  if (m_target)
110  m_render->SetRenderTarget(nullptr);
111  }
113 }
114 
116 {
117  LOG(VB_GENERAL, LOG_INFO, LOC + "Clearing D3D9 painter cache.");
118 
119  QMutexLocker locker(&m_bitmapDeleteLock);
120  QMapIterator<MythImage *, D3D9Image*> it(m_ImageBitmapMap);
121  while (it.hasNext())
122  {
123  it.next();
124  m_bitmapDeleteList.push_back(m_ImageBitmapMap[it.key()]);
125  m_ImageExpireList.remove(it.key());
126  }
127  m_ImageBitmapMap.clear();
128 }
129 
131 {
132  QMutexLocker locker(&m_bitmapDeleteLock);
133  while (!m_bitmapDeleteList.empty())
134  {
135  D3D9Image *img = m_bitmapDeleteList.front();
136  m_bitmapDeleteList.pop_front();
138  delete img;
139  }
140 }
141 
142 void MythD3D9Painter::DrawImage(const QRect &r, MythImage *im,
143  const QRect &src, int alpha)
144 {
145  D3D9Image *image = GetImageFromCache(im);
146  if (image)
147  {
148  image->UpdateVertices(r, src, alpha);
149  image->Draw();
150  }
151 }
152 
153 void MythD3D9Painter::DrawRect(const QRect &area, const QBrush &fillBrush,
154  const QPen &linePen, int alpha)
155 {
156  int style = fillBrush.style();
157  if (style == Qt::SolidPattern || style == Qt::NoBrush)
158  {
159  if (!m_render)
160  return;
161 
162  if (style != Qt::NoBrush)
163  m_render->DrawRect(area, fillBrush.color(), alpha);
164 
165  if (linePen.style() != Qt::NoPen)
166  {
167  int lineWidth = linePen.width();
168  QRect top(QPoint(area.x(), area.y()),
169  QSize(area.width(), lineWidth));
170  QRect bot(QPoint(area.x(), area.y() + area.height() - lineWidth),
171  QSize(area.width(), lineWidth));
172  QRect left(QPoint(area.x(), area.y()),
173  QSize(lineWidth, area.height()));
174  QRect right(QPoint(area.x() + area.width() - lineWidth, area.y()),
175  QSize(lineWidth, area.height()));
176  m_render->DrawRect(top, linePen.color(), alpha);
177  m_render->DrawRect(bot, linePen.color(), alpha);
178  m_render->DrawRect(left, linePen.color(), alpha);
179  m_render->DrawRect(right, linePen.color(), alpha);
180  }
181  return;
182  }
183 
184  MythPainter::DrawRect(area, fillBrush, linePen, alpha);
185 }
186 
188 {
189  if (m_ImageBitmapMap.contains(im))
190  {
191  QMutexLocker locker(&m_bitmapDeleteLock);
192  m_bitmapDeleteList.push_back(m_ImageBitmapMap[im]);
193  m_ImageBitmapMap.remove(im);
194  m_ImageExpireList.remove(im);
195  }
196 }
197 
199 {
200  if (m_ImageBitmapMap.contains(im))
201  {
202  if (!im->IsChanged())
203  {
204  m_ImageExpireList.remove(im);
205  m_ImageExpireList.push_back(im);
206  return m_ImageBitmapMap[im];
207  }
208  else
209  {
211  }
212  }
213 
214  im->SetChanged(false);
215  D3D9Image *newimage = nullptr;
216  if (m_render)
217  newimage = new D3D9Image(m_render,im->size());
218 
219  if (newimage && newimage->IsValid())
220  {
221  CheckFormatImage(im);
222  m_HardwareCacheSize += newimage->GetDataSize();
223  newimage->UpdateImage(im);
224  m_ImageBitmapMap[im] = newimage;
225  m_ImageExpireList.push_back(im);
226 
228  {
229  MythImage *expiredIm = m_ImageExpireList.front();
230  m_ImageExpireList.pop_front();
231  DeleteFormatImagePriv(expiredIm);
232  DeleteBitmaps();
233  }
234  }
235  else
236  {
237  LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to create D3D9 UI bitmap.");
238  delete newimage;
239  newimage = nullptr;
240  }
241 
242  return newimage;
243 }
bool ClearBuffer(void)
void DeleteFormatImagePriv(MythImage *im) override
virtual void Teardown(void)
Definition: mythpainter.cpp:29
void Begin(QPaintDevice *parent) override
MythD3D9Painter(MythRenderD3D9 *render=nullptr)
MythRenderD3D9 * m_render
bool InitD3D9(QPaintDevice *parent)
D3D9Image * m_target
virtual void SetChanged(bool change=true)
Definition: mythimage.h:45
bool IsValid(void) const
void DeleteBitmaps(void)
#define LOC
bool Present(HWND win)
unsigned char r
Definition: ParseText.cpp:329
QMap< MythImage *, D3D9Image * > m_ImageBitmapMap
int m_HardwareCacheSize
Definition: mythpainter.h:129
D3D9Image * GetImageFromCache(MythImage *im)
virtual void End()
Definition: mythpainter.h:51
bool Create(QSize size, HWND window)
void DrawRect(const QRect &rect, const QColor &color, int alpha)
virtual int IncrRef(void)
Increments reference count.
virtual void DrawRect(const QRect &area, const QBrush &fillBrush, const QPen &linePen, int alpha)
virtual int DecrRef(void)
Decrements reference count and deletes on 0.
void FreeResources(void) override
bool UpdateVertices(const QRect &dvr, const QRect &vr, int alpha=255, bool video=false)
bool SetRenderTarget(IDirect3DTexture9 *texture)
bool Draw(void)
void End() override
bool UpdateImage(IDirect3DSurface9 *surface)
int GetDataSize(void) const
bool SetAsRenderTarget(void)
bool Test(bool &reset)
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
std::list< D3D9Image * > m_bitmapDeleteList
void DrawImage(const QRect &dest, MythImage *im, const QRect &src, int alpha) override
void CheckFormatImage(MythImage *im)
std::list< MythImage * > m_ImageExpireList
bool IsChanged() const
Definition: mythimage.h:46
void Teardown(void) override
virtual void Begin(QPaintDevice *parent)
Definition: mythpainter.h:50
void DrawRect(const QRect &area, const QBrush &fillBrush, const QPen &linePen, int alpha) override
int m_MaxHardwareCacheSize
Definition: mythpainter.h:130