MythTV  master
mythpainteropengl.cpp
Go to the documentation of this file.
1 // Config header generated in base directory by configure
2 #include "config.h"
3 
4 // Qt
5 #include <QCoreApplication>
6 #include <QPainter>
7 
8 // MythTV
9 #include "mythmainwindow.h"
10 #include "mythrenderopengl.h"
11 #include "mythpainteropengl.h"
12 
14  : MythPainterGPU(Parent),
15  m_render(Render)
16 {
18 
19  if (!m_render)
20  LOG(VB_GENERAL, LOG_ERR, "OpenGL painter has no render device");
21 }
22 
24 {
25  if (!m_render)
26  return;
27  if (!m_render->IsReady())
28  return;
29  OpenGLLocker locker(m_render);
30  if (VERBOSE_LEVEL_CHECK(VB_GPU, LOG_INFO))
31  m_render->logDebugMarker("PAINTER_RELEASE_START");
32  Teardown();
34  if (VERBOSE_LEVEL_CHECK(VB_GPU, LOG_INFO))
35  m_render->logDebugMarker("PAINTER_RELEASE_END");
36 }
37 
39 {
40  OpenGLLocker locker(m_render);
41  ClearCache();
44  {
45  for (auto & buf : m_mappedBufferPool)
46  {
47  delete buf;
48  buf = nullptr;
49  }
51  }
52 
54 }
55 
57 {
58  if (!m_render || m_textureDeleteList.empty())
59  return;
60 
61  QMutexLocker gllocker(&m_textureDeleteLock);
62  OpenGLLocker locker(m_render);
63  while (!m_textureDeleteList.empty())
64  {
65  MythGLTexture *texture = m_textureDeleteList.front();
67  m_render->DeleteTexture(texture);
68  m_textureDeleteList.pop_front();
69  }
70 }
71 
73 {
74  LOG(VB_GENERAL, LOG_INFO, "Clearing OpenGL painter cache.");
75 
76  QMutexLocker locker(&m_textureDeleteLock);
77  QMapIterator<MythImage *, MythGLTexture*> it(m_imageToTextureMap);
78  while (it.hasNext())
79  {
80  it.next();
81  m_textureDeleteList.push_back(m_imageToTextureMap[it.key()]);
82  m_imageExpireList.remove(it.key());
83  }
84  m_imageToTextureMap.clear();
85 }
86 
87 void MythOpenGLPainter::Begin(QPaintDevice *Parent)
88 {
89  MythPainterGPU::Begin(Parent);
90 
91  if (!(m_render && m_parent))
92  {
93  LOG(VB_GENERAL, LOG_ERR, "FATAL ERROR: No render device in 'Begin'");
94  return;
95  }
96 
98  {
100  // initialise the VBO pool
101  std::generate(m_mappedBufferPool.begin(), m_mappedBufferPool.end(),
102  [&]() { return m_render->CreateVBO(static_cast<int>(MythRenderOpenGL::kVertexSize)); });
103  }
104 
105  QSize currentsize = m_parent->size();
106 
107  // check if we need to adjust cache sizes
108  // NOTE - don't use the scaled size if using high DPI. Our images are at the lower
109  // resolution
110  if (m_lastSize != currentsize)
111  {
112  // This will scale the cache depending on the resolution in use
113  static const int s_onehd = 1920 * 1080;
114  static const int s_basesize = 64;
115  m_lastSize = currentsize;
116  float hdscreens = (static_cast<float>(m_lastSize.width() + 1) * m_lastSize.height()) / s_onehd;
117  int cpu = qMax(static_cast<int>(hdscreens * s_basesize), s_basesize);
118  int gpu = cpu * 3 / 2;
119  SetMaximumCacheSizes(gpu, cpu);
120  }
121 
122  if (VERBOSE_LEVEL_CHECK(VB_GPU, LOG_INFO))
123  m_render->logDebugMarker("PAINTER_FRAME_START");
124 
125  DeleteTextures();
127 
128  // If master (have complete swap control) then bind default framebuffer and clear
129  if (m_viewControl.testFlag(Framebuffer))
130  {
131  m_render->BindFramebuffer(nullptr);
132  m_render->SetBackground(0, 0, 0, 255);
134  }
135 
136  // If we have viewport control, set as needed.
137  if (m_viewControl.testFlag(Viewport))
138  {
139  // If using high DPI then scale the viewport
140  if (m_usingHighDPI)
141  currentsize *= m_pixelRatio;
142  m_render->SetViewPort(QRect(0, 0, currentsize.width(), currentsize.height()));
143  }
144 }
145 
147 {
148  if (!m_render)
149  {
150  LOG(VB_GENERAL, LOG_ERR, "FATAL ERROR: No render device in 'End'");
151  return;
152  }
153 
154  if (VERBOSE_LEVEL_CHECK(VB_GPU, LOG_INFO))
155  m_render->logDebugMarker("PAINTER_FRAME_END");
156 
157  if (m_viewControl.testFlag(Framebuffer))
158  {
159  m_render->Flush();
161  }
163 
164  m_mappedTextures.clear();
166 }
167 
169 {
170  if (!m_render)
171  return nullptr;
172 
173  if (m_imageToTextureMap.contains(Image))
174  {
175  if (!Image->IsChanged())
176  {
177  m_imageExpireList.remove(Image);
178  m_imageExpireList.push_back(Image);
179  return m_imageToTextureMap[Image];
180  }
181  DeleteFormatImagePriv(Image);
182  }
183 
184  Image->SetChanged(false);
185 
186  int count = 0;
187  MythGLTexture* texture = nullptr;
188  while (texture == nullptr)
189  {
190  texture = m_render->CreateTextureFromQImage(Image);
191  if (texture != nullptr)
192  break;
193 
194  // This can happen if the cached textures are too big for GPU memory
195  if ((count++ > 1000) || (m_hardwareCacheSize <= 8 * 1024 * 1024))
196  {
197  LOG(VB_GENERAL, LOG_ERR, "Failed to create OpenGL texture.");
198  return nullptr;
199  }
200 
201  // Shrink the cache size
203  LOG(VB_GENERAL, LOG_NOTICE, QString("Shrinking UIPainterMaxCacheHW to %1KB")
204  .arg(m_maxHardwareCacheSize / 1024));
205 
207  {
208  MythImage *expiredIm = m_imageExpireList.front();
209  m_imageExpireList.pop_front();
210  DeleteFormatImagePriv(expiredIm);
211  DeleteTextures();
212  }
213  }
214 
215  CheckFormatImage(Image);
217  m_imageToTextureMap[Image] = texture;
218  m_imageExpireList.push_back(Image);
219 
221  {
222  MythImage *expiredIm = m_imageExpireList.front();
223  m_imageExpireList.pop_front();
224  DeleteFormatImagePriv(expiredIm);
225  DeleteTextures();
226  }
227 
228  return texture;
229 }
230 
231 #ifdef Q_OS_MACOS
232 #define DEST dest
233 #else
234 #define DEST Dest
235 #endif
236 
237 void MythOpenGLPainter::DrawImage(const QRect Dest, MythImage *Image,
238  const QRect Source, int Alpha)
239 {
240  if (m_render)
241  {
242  qreal pixelratio = 1.0;
243  if (m_usingHighDPI && m_viewControl.testFlag(Viewport))
244  pixelratio = m_pixelRatio;
245 #ifdef Q_OS_MACOS
246  QRect dest = QRect(static_cast<int>(Dest.left() * pixelratio),
247  static_cast<int>(Dest.top() * pixelratio),
248  static_cast<int>(Dest.width() * pixelratio),
249  static_cast<int>(Dest.height() * pixelratio));
250 #endif
251 
252  // Drawing an image multiple times with the same VBO will stall most GPUs as
253  // the VBO is re-mapped whilst still in use. Use a pooled VBO instead.
254  MythGLTexture *texture = GetTextureFromCache(Image);
255  if (texture && m_mappedTextures.contains(texture))
256  {
257  QOpenGLBuffer *vbo = texture->m_vbo;
259  texture->m_destination = QRect();
260  m_render->DrawBitmap(texture, nullptr, Source, DEST, nullptr, Alpha, pixelratio);
261  texture->m_destination = QRect();
262  texture->m_vbo = vbo;
265  }
266  else
267  {
268  m_render->DrawBitmap(texture, nullptr, Source, DEST, nullptr, Alpha, pixelratio);
269  m_mappedTextures.append(texture);
270  }
271  }
272 }
273 
283 void MythOpenGLPainter::DrawRect(const QRect Area, const QBrush &FillBrush,
284  const QPen &LinePen, int Alpha)
285 {
286  if ((FillBrush.style() == Qt::SolidPattern ||
287  FillBrush.style() == Qt::NoBrush) && m_render && !m_usingHighDPI)
288  {
289  m_render->DrawRect(nullptr, Area, FillBrush, LinePen, Alpha);
290  return;
291  }
292  MythPainterGPU::DrawRect(Area, FillBrush, LinePen, Alpha);
293 }
294 
295 void MythOpenGLPainter::DrawRoundRect(const QRect Area, int CornerRadius,
296  const QBrush &FillBrush,
297  const QPen &LinePen, int Alpha)
298 {
299  if ((FillBrush.style() == Qt::SolidPattern ||
300  FillBrush.style() == Qt::NoBrush) && m_render && !m_usingHighDPI)
301  {
302  m_render->DrawRoundRect(nullptr, Area, CornerRadius, FillBrush,
303  LinePen, Alpha);
304  return;
305  }
306  MythPainterGPU::DrawRoundRect(Area, CornerRadius, FillBrush, LinePen, Alpha);
307 }
308 
310 {
311  if (m_imageToTextureMap.contains(Image))
312  {
313  QMutexLocker locker(&m_textureDeleteLock);
314  m_textureDeleteList.push_back(m_imageToTextureMap[Image]);
315  m_imageToTextureMap.remove(Image);
316  m_imageExpireList.remove(Image);
317  }
318 }
319 
320 void MythOpenGLPainter::PushTransformation(const UIEffects &Fx, QPointF Center)
321 {
322  if (m_render)
323  m_render->PushTransformation(Fx, Center);
324 }
325 
327 {
328  if (m_render)
330 }
MythOpenGLPainter::m_imageExpireList
std::list< MythImage * > m_imageExpireList
Definition: mythpainteropengl.h:59
MythPainterGPU::m_parent
MythMainWindow * m_parent
Definition: mythpaintergpu.h:33
build_compdb.dest
dest
Definition: build_compdb.py:9
MythOpenGLPainter::DeleteTextures
void DeleteTextures(void)
Definition: mythpainteropengl.cpp:56
MythGLTexture
Definition: mythrenderopengl.h:59
MythPainter::m_hardwareCacheSize
int m_hardwareCacheSize
Definition: mythpainter.h:127
MythRenderOpenGL::SetBackground
void SetBackground(uint8_t Red, uint8_t Green, uint8_t Blue, uint8_t Alpha)
Definition: mythrenderopengl.cpp:616
MythRenderOpenGL::IsReady
bool IsReady(void)
Definition: mythrenderopengl.cpp:504
MythGLTexture::m_destination
QRect m_destination
Definition: mythrenderopengl.h:78
MythRenderOpenGL::ClearFramebuffer
void ClearFramebuffer(void)
Definition: mythrenderopengl.cpp:803
MythOpenGLPainter::m_textureDeleteLock
QMutex m_textureDeleteLock
Definition: mythpainteropengl.h:61
MythOpenGLPainter::Begin
void Begin(QPaintDevice *Parent) override
Definition: mythpainteropengl.cpp:87
MythPainter::SetMaximumCacheSizes
void SetMaximumCacheSizes(int hardware, int software)
Definition: mythpainter.cpp:607
MythOpenGLPainter::MythOpenGLPainter
MythOpenGLPainter(MythRenderOpenGL *Render, MythMainWindow *Parent)
Definition: mythpainteropengl.cpp:13
MythOpenGLPainter::DrawRect
void DrawRect(QRect Area, const QBrush &FillBrush, const QPen &LinePen, int Alpha) override
Draw a rectangle.
Definition: mythpainteropengl.cpp:283
MythRenderOpenGL::logDebugMarker
void logDebugMarker(const QString &Message)
Definition: mythrenderopengl.cpp:194
MythOpenGLPainter::FreeResources
void FreeResources(void) override
Definition: mythpainteropengl.cpp:38
DEST
#define DEST
Definition: mythpainteropengl.cpp:234
MythRenderOpenGL::PushTransformation
void PushTransformation(const UIEffects &Fx, QPointF &Center)
Definition: mythrenderopengl.cpp:1360
MythOpenGLPainter::m_mappedBufferPoolIdx
size_t m_mappedBufferPoolIdx
Definition: mythpainteropengl.h:65
MythRenderOpenGL::DrawBitmap
void DrawBitmap(MythGLTexture *Texture, QOpenGLFramebufferObject *Target, QRect Source, QRect Destination, QOpenGLShaderProgram *Program, int Alpha=255, qreal Scale=1.0)
Definition: mythrenderopengl.cpp:810
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:23
MythOpenGLPainter::GetTextureFromCache
MythGLTexture * GetTextureFromCache(MythImage *Image)
Definition: mythpainteropengl.cpp:168
MythPainter::DrawRect
virtual void DrawRect(QRect area, const QBrush &fillBrush, const QPen &linePen, int alpha)
Definition: mythpainter.cpp:157
MythPainter::m_maxHardwareCacheSize
int m_maxHardwareCacheSize
Definition: mythpainter.h:128
MythPainterGPU::m_viewControl
ViewControls m_viewControl
Definition: mythpaintergpu.h:34
MythPainterGPU::m_usingHighDPI
bool m_usingHighDPI
Definition: mythpaintergpu.h:36
MythRenderOpenGL::GetTextureDataSize
static int GetTextureDataSize(MythGLTexture *Texture)
Definition: mythrenderopengl.cpp:670
MythOpenGLPainter::PushTransformation
void PushTransformation(const UIEffects &Fx, QPointF Center=QPointF()) override
Definition: mythpainteropengl.cpp:320
mythrenderopengl.h
MythPainterGPU::m_pixelRatio
qreal m_pixelRatio
Definition: mythpaintergpu.h:35
Source
Definition: channelsettings.cpp:68
MythGLTexture::m_vbo
QOpenGLBuffer * m_vbo
Definition: mythrenderopengl.h:72
MythRenderOpenGL::CreateTextureFromQImage
MythGLTexture * CreateTextureFromQImage(QImage *Image)
Definition: mythrenderopengl.cpp:628
MythRenderOpenGL::DrawRect
void DrawRect(QOpenGLFramebufferObject *Target, QRect Area, const QBrush &FillBrush, const QPen &LinePen, int Alpha)
Definition: mythrenderopengl.cpp:956
MythRenderOpenGL::Flush
void Flush(void)
Definition: mythrenderopengl.cpp:595
MythOpenGLPainter::m_render
MythRenderOpenGL * m_render
Definition: mythpainteropengl.h:56
MythPainterGPU::Viewport
@ Viewport
Definition: mythpaintergpu.h:19
MythRenderOpenGL::PopTransformation
void PopTransformation(void)
Definition: mythrenderopengl.cpp:1373
MythRenderOpenGL::swapBuffers
void swapBuffers()
Definition: mythrenderopengl.cpp:509
MythRenderOpenGL::makeCurrent
void makeCurrent()
Definition: mythrenderopengl.cpp:564
MythOpenGLPainter::m_mappedBufferPoolReady
bool m_mappedBufferPoolReady
Definition: mythpainteropengl.h:66
MythRenderOpenGL::DeleteTexture
void DeleteTexture(MythGLTexture *Texture)
Definition: mythrenderopengl.cpp:714
MythOpenGLPainter::DeleteFormatImagePriv
void DeleteFormatImagePriv(MythImage *Image) override
Definition: mythpainteropengl.cpp:309
MythOpenGLPainter::m_mappedBufferPool
std::array< QOpenGLBuffer *, MAX_BUFFER_POOL > m_mappedBufferPool
Definition: mythpainteropengl.h:64
MythRenderOpenGL::DrawRoundRect
void DrawRoundRect(QOpenGLFramebufferObject *Target, QRect Area, int CornerRadius, const QBrush &FillBrush, const QPen &LinePen, int Alpha)
Definition: mythrenderopengl.cpp:964
MythImage::SetChanged
virtual void SetChanged(bool change=true)
Definition: mythimage.h:50
MythOpenGLPainter::PopTransformation
void PopTransformation(void) override
Definition: mythpainteropengl.cpp:326
MythPainter::FreeResources
virtual void FreeResources(void)
Definition: mythpainter.h:51
MAX_BUFFER_POOL
#define MAX_BUFFER_POOL
Definition: mythpainteropengl.h:21
MythPainter::End
virtual void End()
Definition: mythpainter.h:53
MythRenderOpenGL::doneCurrent
void doneCurrent()
Definition: mythrenderopengl.cpp:572
mythpainteropengl.h
MythRenderOpenGL
Definition: mythrenderopengl.h:99
VERBOSE_LEVEL_CHECK
#define VERBOSE_LEVEL_CHECK(_MASK_, _LEVEL_)
Definition: mythlogging.h:14
MythRenderOpenGL::BindFramebuffer
void BindFramebuffer(QOpenGLFramebufferObject *Framebuffer)
Definition: mythrenderopengl.cpp:783
MythPainterGPU::Framebuffer
@ Framebuffer
Definition: mythpaintergpu.h:20
MythOpenGLPainter::m_mappedTextures
QVector< MythGLTexture * > m_mappedTextures
Definition: mythpainteropengl.h:63
MythImage
Definition: mythimage.h:36
MythPainterGPU::m_lastSize
QSize m_lastSize
Definition: mythpaintergpu.h:37
UIEffects
Definition: mythuianimation.h:12
MythOpenGLPainter::End
void End() override
Definition: mythpainteropengl.cpp:146
MythImage::IsChanged
bool IsChanged() const
Definition: mythimage.h:51
MythRenderOpenGL::SetViewPort
void SetViewPort(QRect Rect, bool ViewportOnly=false) override
Definition: mythrenderopengl.cpp:582
MythOpenGLPainter::~MythOpenGLPainter
~MythOpenGLPainter() override
Definition: mythpainteropengl.cpp:23
MythPainter::Teardown
virtual void Teardown(void)
Definition: mythpainter.cpp:28
MythPainter::CheckFormatImage
void CheckFormatImage(MythImage *im)
Definition: mythpainter.cpp:556
mythmainwindow.h
MythOpenGLPainter::DrawRoundRect
void DrawRoundRect(QRect Area, int CornerRadius, const QBrush &FillBrush, const QPen &LinePen, int Alpha) override
Definition: mythpainteropengl.cpp:295
MythOpenGLPainter::DrawImage
void DrawImage(QRect Dest, MythImage *Image, QRect Source, int Alpha) override
Definition: mythpainteropengl.cpp:237
MythPainter::Begin
virtual void Begin(QPaintDevice *)
Definition: mythpainter.h:52
MythPainter::DrawRoundRect
virtual void DrawRoundRect(QRect area, int cornerRadius, const QBrush &fillBrush, const QPen &linePen, int alpha)
Definition: mythpainter.cpp:168
MythMainWindow
Definition: mythmainwindow.h:35
MythOpenGLPainter::m_imageToTextureMap
QMap< MythImage *, MythGLTexture * > m_imageToTextureMap
Definition: mythpainteropengl.h:58
MythOpenGLPainter::m_textureDeleteList
std::list< MythGLTexture * > m_textureDeleteList
Definition: mythpainteropengl.h:60
MythOpenGLPainter::ClearCache
void ClearCache(void)
Definition: mythpainteropengl.cpp:72
MythPainterGPU
Definition: mythpaintergpu.h:11
OpenGLLocker
Definition: mythrenderopengl.h:261