10#include <QGuiApplication>
13#include "libmythbase/mythconfig.h"
25#define LOC QString("OpenGL: ")
44 : m_textureId(Texture)
85 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"OpenGL is disabled for Remote X Session");
91 bool opengles = !qEnvironmentVariableIsEmpty(
"MYTHTV_OPENGL_ES");
92 bool core = !qEnvironmentVariableIsEmpty(
"MYTHTV_OPENGL_CORE");
93 QSurfaceFormat format = QSurfaceFormat::defaultFormat();
96 format.setProfile(QSurfaceFormat::CoreProfile);
97 format.setMajorVersion(4);
98 format.setMinorVersion(3);
105 format.setProfile(QSurfaceFormat::CoreProfile);
106 format.setMajorVersion(3);
107 format.setMinorVersion(1);
109 format.setRenderableType(QSurfaceFormat::OpenGLES);
113 format.setOption(QSurfaceFormat::DebugContext);
133 LOG(VB_GENERAL, LOG_INFO,
LOC +
"MythRenderOpenGL closing");
147 QString source(
"Unknown");
148 QString
type(
"Unknown");
150 switch (Message.source())
152 case QOpenGLDebugMessage::ApplicationSource:
return;
153 case QOpenGLDebugMessage::APISource: source =
"API";
break;
154 case QOpenGLDebugMessage::WindowSystemSource: source =
"WinSys";
break;
155 case QOpenGLDebugMessage::ShaderCompilerSource: source =
"ShaderComp";
break;
156 case QOpenGLDebugMessage::ThirdPartySource: source =
"3rdParty";
break;
157 case QOpenGLDebugMessage::OtherSource: source =
"Other";
break;
163 switch (Message.type())
165 case QOpenGLDebugMessage::ErrorType:
166 type =
"Error";
break;
167 case QOpenGLDebugMessage::DeprecatedBehaviorType:
168 type =
"Deprecated";
break;
169 case QOpenGLDebugMessage::UndefinedBehaviorType:
170 type =
"Undef behaviour";
break;
171 case QOpenGLDebugMessage::PortabilityType:
172 type =
"Portability";
break;
173 case QOpenGLDebugMessage::PerformanceType:
174 type =
"Performance";
break;
175 case QOpenGLDebugMessage::OtherType:
176 type =
"Other";
break;
177 case QOpenGLDebugMessage::MarkerType:
178 type =
"Marker";
break;
179 case QOpenGLDebugMessage::GroupPushType:
180 type =
"GroupPush";
break;
181 case QOpenGLDebugMessage::GroupPopType:
182 type =
"GroupPop";
break;
185 LOG(VB_GPU, LOG_INFO,
LOC + QString(
"Src: %1 Type: %2 Msg: %3")
186 .arg(source,
type, Message.message()));
193 QOpenGLDebugMessage message = QOpenGLDebugMessage::createApplicationMessage(
194 Message, 0, QOpenGLDebugMessage::NotificationSeverity, QOpenGLDebugMessage::MarkerType);
203 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Context about to be destroyed");
210 LOG(VB_GENERAL, LOG_ERR,
LOC +
"MythRenderOpenGL is not a valid OpenGL rendering context");
215 initializeOpenGLFunctions();
226 QOpenGLDebugLogger::LoggingMode mode = QOpenGLDebugLogger::AsynchronousLogging;
229 if (!qEnvironmentVariableIsEmpty(
"MYTHTV_OPENGL_SYNCHRONOUS"))
230 mode = QOpenGLDebugLogger::SynchronousLogging;
233 if (mode == QOpenGLDebugLogger::AsynchronousLogging)
234 LOG(VB_GENERAL, LOG_INFO,
LOC +
"GPU debug logging started (async)");
236 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Started synchronous GPU debug logging (will hurt performance)");
240 QString filter = qgetenv(
"MYTHTV_OPENGL_LOGFILTER");
241 if (filter.contains(
"other", Qt::CaseInsensitive))
246 if (filter.contains(
"error", Qt::CaseInsensitive))
251 if (filter.contains(
"deprecated", Qt::CaseInsensitive))
254 debug <<
"Deprecated";
256 if (filter.contains(
"undefined", Qt::CaseInsensitive))
259 debug <<
"Undefined";
261 if (filter.contains(
"portability", Qt::CaseInsensitive))
264 debug <<
"Portability";
266 if (filter.contains(
"performance", Qt::CaseInsensitive))
269 debug <<
"Performance";
271 if (filter.contains(
"grouppush", Qt::CaseInsensitive))
274 debug <<
"GroupPush";
276 if (filter.contains(
"grouppop", Qt::CaseInsensitive))
282 if (!
debug.isEmpty())
283 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Filtering out GPU messages for: %1")
284 .arg(
debug.join(
", ")));
288 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Failed to initialise OpenGL logging");
302 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxtexsz);
303 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &maxunits);
306 QSurfaceFormat fmt = format();
314 if ((isOpenGLES() && hasExtension(
"GL_OES_mapbuffer") && buffer_procs) ||
315 (hasExtension(
"GL_ARB_vertex_buffer_object") && buffer_procs))
319 if (!isOpenGLES() && (hasExtension(
"GL_NV_texture_rectangle") ||
320 hasExtension(
"GL_ARB_texture_rectangle") ||
321 hasExtension(
"GL_EXT_texture_rectangle")))
325 if ((isOpenGLES() && format().majorVersion() < 3) ||
326 (!isOpenGLES() && format().majorVersion() < 2))
331 if (!isOpenGLES() || (isOpenGLES() && ((fmt.majorVersion() >= 3) || hasExtension(
"GL_EXT_unpack_subimage"))))
335 if (fmt.profile() == QSurfaceFormat::OpenGLContextProfile::CoreProfile)
339 extraFunctions()->glGenVertexArrays(1, &
m_vao);
340 extraFunctions()->glBindVertexArray(
m_vao);
350 static const std::array<const QByteArray,3> kTiled {
"videocore",
"vc4",
"v3d" };
351 auto renderer = QByteArray(
reinterpret_cast<const char*
>(glGetString(GL_RENDERER))).toLower();
352 for (
const auto & name : kTiled)
354 if (renderer.contains(name))
362 if (hasExtension(
"GL_NVX_gpu_memory_info"))
369 if (QOpenGLShader::hasOpenGLShaders(QOpenGLShader::Compute))
371 if (QOpenGLShader::hasOpenGLShaders(QOpenGLShader::Geometry))
379 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Failed to create default shaders");
383 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Initialised MythRenderOpenGL");
384 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Using %1 range output").arg(
m_fullRange ?
"full" :
"limited"));
390static constexpr QLatin1String
GLYesNo (
bool v)
392 return v ? QLatin1String(
"Yes") : QLatin1String(
"No");
397 QSurfaceFormat fmt = format();
398 QString qtglversion = QString(
"OpenGL%1 %2.%3")
399 .arg(fmt.renderableType() == QSurfaceFormat::OpenGLES ?
"ES" :
"")
400 .arg(fmt.majorVersion()).arg(fmt.minorVersion());
401 QString qtglsurface = QString(
"RGBA: %1:%2:%3:%4 Depth: %5 Stencil: %6")
402 .arg(fmt.redBufferSize()).arg(fmt.greenBufferSize())
403 .arg(fmt.blueBufferSize()).arg(fmt.alphaBufferSize())
404 .arg(fmt.depthBufferSize()).arg(fmt.stencilBufferSize());
405 QStringList shaders {
"None"};
408 shaders = QStringList {
"Vertex",
"Fragment" };
410 shaders <<
"Geometry";
412 shaders <<
"Compute";
414 const QString module = QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL ?
"OpenGL (not ES)" :
"OpenGL ES";
415 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"OpenGL vendor : %1").arg(
reinterpret_cast<const char*
>(glGetString(GL_VENDOR))));
416 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"OpenGL renderer : %1").arg(
reinterpret_cast<const char*
>(glGetString(GL_RENDERER))));
417 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"OpenGL version : %1").arg(
reinterpret_cast<const char*
>(glGetString(GL_VERSION))));
418 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Qt platform : %1").arg(QGuiApplication::platformName()));
420 bool eglfuncs =
IsEGL();
422 LOG(VB_PLAYBACK, LOG_INFO,
LOC + QString(
"EGL images : %1").arg(
GLYesNo(eglfuncs)));
424 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Qt OpenGL module : %1").arg(module));
425 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Qt OpenGL format : %1").arg(qtglversion));
426 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Qt OpenGL surface : %1").arg(qtglsurface));
428 LOG(VB_GENERAL, LOG_INFO,
LOC + QString(
"Shaders : %1").arg(shaders.join(
",")));
438 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"Warning: Insufficient texture units for some features.");
466 bool recommended =
true;
468 QString renderer =
reinterpret_cast<const char*
>(glGetString(GL_RENDERER));
470 if (!(openGLFeatures() & Shaders))
472 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"OpenGL has no shader support");
475 else if (!(openGLFeatures() & Framebuffers))
477 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"OpenGL has no framebuffer support");
480 else if (renderer.contains(
"Software Rasterizer", Qt::CaseInsensitive))
482 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"OpenGL is using software rasterizer.");
485 else if (renderer.contains(
"softpipe", Qt::CaseInsensitive))
487 LOG(VB_GENERAL, LOG_WARNING,
LOC +
"OpenGL seems to be using software "
488 "fallback. Please check your OpenGL driver installation, "
489 "configuration, and device permissions.");
495 LOG(VB_GENERAL, LOG_INFO,
LOC +
496 "OpenGL not recommended with this system's hardware/drivers.");
509 QOpenGLContext::swapBuffers(
m_window);
524 LOG(VB_GENERAL, LOG_CRIT,
LOC +
"No widget!");
530 QWidget* native = Widget->nativeParentWidget();
536 LOG(VB_GENERAL, LOG_CRIT,
LOC +
"No window surface!");
540#ifdef CONFIG_QTWEBENGINE
541 auto * globalcontext = QOpenGLContext::globalShareContext();
544 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Using global shared OpenGL context");
545 setShareContext(globalcontext);
551 LOG(VB_GENERAL, LOG_CRIT,
LOC +
"Failed to create OpenGLContext!");
555 Widget->setAttribute(Qt::WA_PaintOnScreen);
563 if (!QOpenGLContext::makeCurrent(
m_window))
564 LOG(VB_GENERAL, LOG_ERR,
LOC +
"makeCurrent failed");
573 LOG(VB_GENERAL, LOG_ERR,
LOC +
"Mis-matched calls to makeCurrent()");
613 int32_t tmp = (Red << 24) + (Green << 16) + (Blue << 8) + Alpha;
619 glClearColor(Red / 255.0F, Green / 255.0F, Blue / 255.0F, Alpha / 255.0F);
629 auto *texture =
new QOpenGLTexture(*Image, QOpenGLTexture::DontGenerateMipMaps);
630 if (!texture->textureId())
632 LOG(VB_GENERAL, LOG_INFO,
LOC +
"Failed to create texure");
636 texture->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Linear);
637 texture->setWrapMode(QOpenGLTexture::ClampToEdge);
639 result->m_texture = texture;
641 result->m_totalSize =
GetTextureSize(Image->size(), result->m_target != QOpenGLTexture::TargetRectangle);
643 result->m_pixelFormat = QOpenGLTexture::RGBA;
644 result->m_pixelType = QOpenGLTexture::UInt8;
645 result->m_bufferSize =
GetBufferSize(result->m_totalSize, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
646 result->m_size = Image->size();
647 result->m_crop =
true;
653 if (((
m_features & NPOTTextures) != 0U) || !Normalised)
658 while (w < Size.width())
660 while (h < Size.height())
682 Texture->
m_texture->setMinMagFilters(Filter, Filter);
687 glTexParameteri(Texture->
m_target, GL_TEXTURE_MIN_FILTER, Filter);
688 glTexParameteri(Texture->
m_target, GL_TEXTURE_MAG_FILTER, Filter);
689 glTexParameteri(Texture->
m_target, GL_TEXTURE_WRAP_S, Wrap);
690 glTexParameteri(Texture->
m_target, GL_TEXTURE_WRAP_T, Wrap);
703 glActiveTexture(ActiveTex);
717 delete [] Texture->
m_data;
718 delete Texture->
m_vbo;
730 QOpenGLFramebufferObject *framebuffer =
nullptr;
733 framebuffer =
new QOpenGLFramebufferObject(Size, QOpenGLFramebufferObject::NoAttachment,
734 GL_TEXTURE_2D, QOpenGLTexture::RGBA16_UNorm);
738 framebuffer =
new QOpenGLFramebufferObject(Size);
740 if (framebuffer->isValid())
742 if (framebuffer->isBound())
750 LOG(VB_GENERAL, LOG_ERR,
"Failed to create framebuffer object");
762 texture->m_size = texture->m_totalSize = Framebuffer->size();
764 texture->m_flip =
false;
785 if (Framebuffer ==
nullptr)
787 QOpenGLFramebufferObject::bindDefault();
801 glClear(GL_COLOR_BUFFER_BIT);
806 QOpenGLShaderProgram *Program,
float TimeVal)
817 Program->setUniformValue(
"u_time", TimeVal);
818 Program->setUniformValue(
"u_alpha",
static_cast<float>(Alpha / 255.0F));
819 Program->setUniformValue(
"u_res", QVector2D(
m_window->width(),
m_window->height()));
820 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
821 QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
827 const QRect
Source,
const QRect Destination,
828 QOpenGLShaderProgram *Program,
int Alpha, qreal Scale)
835 if (Program ==
nullptr)
841 GLenum textarget = Texture->
m_target;
842 Program->setUniformValue(
"s_texture0", 0);
849 QOpenGLBuffer* buffer = Texture->
m_vbo;
855 void* target = buffer->map(QOpenGLBuffer::WriteOnly);
859 static_cast<GLfloat*
>(target));
872 glVertexAttrib4f(
COLOR_INDEX, 1.0F, 1.0F, 1.0F, Alpha / 255.0F);
874 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
877 QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
882 QOpenGLFramebufferObject *Target,
883 const QRect
Source,
const QRect Destination,
884 QOpenGLShaderProgram *Program,
887 if (Textures.empty())
893 if (Program ==
nullptr)
903 for (
uint i = 0; i < Textures.size(); i++)
905 QString uniform = QString(
"s_texture%1").arg(i);
906 Program->setUniformValue(qPrintable(uniform), i);
908 if (Textures[i]->m_texture)
909 Textures[i]->m_texture->bind();
911 glBindTexture(textarget, Textures[i]->m_textureId);
914 QOpenGLBuffer* buffer = first->
m_vbo;
920 void* target = buffer->map(QOpenGLBuffer::WriteOnly);
924 static_cast<GLfloat*
>(target));
939 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
942 QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
958 glVertexAttrib4f(
COLOR_INDEX, color, color, color, Alpha / 255.0F);
963 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
965 QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
971 const QRect Area,
const QBrush &FillBrush,
972 const QPen &LinePen,
int Alpha)
979 const QRect Area,
int CornerRadius,
980 const QBrush &FillBrush,
981 const QPen &LinePen,
int Alpha)
983 bool fill = FillBrush.style() != Qt::NoBrush;
984 bool edge = LinePen.style() != Qt::NoPen;
988 auto SetColor = [&](
const QColor&
Color)
993 Color.blue() / 255.0F, (
Color.alpha() / 255.0F) * (Alpha / 255.0F));
999 (
Color.alpha() / 255.0F) * (Alpha / 255.0F));
1002 float halfwidth = Area.width() / 2.0F;
1003 float halfheight = Area.height() / 2.0F;
1004 float radius = CornerRadius;
1005 radius = std::max(radius, 1.0F);
1006 radius = std::min(radius, halfwidth);
1007 radius = std::min(radius, halfheight);
1026 SetColor(FillBrush.color());
1029 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1034 float innerradius = radius - LinePen.width();
1035 innerradius = std::max(innerradius, 1.0F);
1040 SetColor(LinePen.color());
1043 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
1046 QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
1052 GLsizei Stride,
const GLuint Value)
1054#pragma GCC diagnostic push
1055#pragma GCC diagnostic ignored "-Wint-to-pointer-cast"
1057 glVertexAttribPointer(Index, Size,
Type, Normalize, Stride,
reinterpret_cast<const char *
>(Value));
1058#pragma GCC diagnostic pop
1064 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1065 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1066 glDisable(GL_DEPTH_TEST);
1067 glDepthMask(GL_FALSE);
1068 glDisable(GL_CULL_FACE);
1069 glClearColor(0.0F, 0.0F, 0.0F, 0.0F);
1070 glClear(GL_COLOR_BUFFER_BIT);
1071 QOpenGLFramebufferObject::bindDefault();
1078 static const std::array<const QString,4> kExts {
"",
"ARB",
"EXT",
"OES" };
1079 QFunctionPointer result =
nullptr;
1080 for (
const auto & ext : kExts)
1082 result = getProcAddress((Proc + ext).toLocal8Bit().constData());
1086 if (result ==
nullptr)
1087 LOG(VB_GENERAL, LOG_DEBUG,
LOC + QString(
"Extension not found: %1").arg(Proc));
1094 auto* buffer =
new QOpenGLBuffer(QOpenGLBuffer::VertexBuffer);
1095 if (buffer->create())
1097 buffer->setUsagePattern(QOpenGLBuffer::StreamDraw);
1099 buffer->allocate(Size);
1101 QOpenGLBuffer::release(QOpenGLBuffer::VertexBuffer);
1118 extraFunctions()->glDeleteVertexArrays(1, &
m_vao);
1138 result.append(tr(
"QPA platform") +
"\t: " + QGuiApplication::platformName());
1139 result.append(tr(
"OpenGL vendor") +
"\t: " +
reinterpret_cast<const char*
>(glGetString(GL_VENDOR)));
1140 result.append(tr(
"OpenGL renderer") +
"\t: " +
reinterpret_cast<const char*
>(glGetString(GL_RENDERER)));
1141 result.append(tr(
"OpenGL version") +
"\t: " +
reinterpret_cast<const char*
>(glGetString(GL_VERSION)));
1142 QSurfaceFormat fmt = format();
1143 result.append(tr(
"Color depth (RGBA)") +
"\t: " + QString(
"%1:%2:%3:%4")
1144 .arg(fmt.redBufferSize()).arg(fmt.greenBufferSize())
1145 .arg(fmt.blueBufferSize()).arg(fmt.alphaBufferSize()));
1150 const QRect Destination,
int Rotation, qreal Scale)
1152 if (!Texture || Texture->
m_size.isEmpty())
1164 QSize size = Texture->
m_size;
1166 int width = Texture->
m_crop ? std::min(
Source.width(), size.width()) :
Source.width();
1167 int height = Texture->
m_crop ? std::min(
Source.height(), size.height()) :
Source.height();
1169 if (Texture->
m_target != QOpenGLTexture::TargetRectangle)
1172 data[(Texture->
m_flip ? 7 : 1) +
TEX_OFFSET] = (
Source.top() + height) /
static_cast<GLfloat
>(size.height());
1173 data[6 +
TEX_OFFSET] = (
Source.left() + width) /
static_cast<GLfloat
>(size.width());
1189 width = Texture->
m_crop ? std::min(
static_cast<int>(width * Scale), Destination.width()) : Destination.width();
1190 height = Texture->
m_crop ? std::min(
static_cast<int>(height * Scale), Destination.height()) : Destination.height();
1192 data[2] = data[0] = Destination.left();
1193 data[5] = data[1] = Destination.top();
1194 data[4] = data[6] = Destination.left() + width;
1195 data[3] = data[7] = Destination.top() + height;
1235 uint64_t ref = (
static_cast<uint64_t
>(Area.left()) & 0xfff) +
1236 ((
static_cast<uint64_t
>(Area.top()) & 0xfff) << 12) +
1237 ((
static_cast<uint64_t
>(Area.width()) & 0xfff) << 24) +
1238 ((
static_cast<uint64_t
>(Area.height()) & 0xfff) << 36) +
1239 ((
static_cast<uint64_t
>(
Type & 0xfff)) << 48);
1248 auto *vertices =
new GLfloat[8];
1250 vertices[2] = vertices[0] = Area.left();
1251 vertices[5] = vertices[1] = Area.top();
1252 vertices[4] = vertices[6] = Area.left() + Area.width();
1253 vertices[3] = vertices[7] = Area.top() + Area.height();
1255 if (
Type == GL_LINE_LOOP)
1257 vertices[7] = vertices[1];
1258 vertices[5] = vertices[3];
1274 GLfloat *vertices =
nullptr;
1284 uint64_t ref = (
static_cast<uint64_t
>(Area.left()) & 0xfff) +
1285 ((
static_cast<uint64_t
>(Area.top()) & 0xfff) << 12) +
1286 ((
static_cast<uint64_t
>(Area.width()) & 0xfff) << 24) +
1287 ((
static_cast<uint64_t
>(Area.height()) & 0xfff) << 36) +
1288 ((
static_cast<uint64_t
>(
Type & 0xfff)) << 48);
1305 void* target = vbo->map(QOpenGLBuffer::WriteOnly);
1339 case QOpenGLTexture::RGBA_Integer:
1340 case QOpenGLTexture::BGRA_Integer:
1341 case QOpenGLTexture::BGRA:
1342 case QOpenGLTexture::RGBA: bpp = 4;
break;
1343 case QOpenGLTexture::RGB_Integer:
1344 case QOpenGLTexture::BGR_Integer:
1345 case QOpenGLTexture::BGR:
1346 case QOpenGLTexture::RGB: bpp = 3;
break;
1347 case QOpenGLTexture::RG_Integer:
1348 case QOpenGLTexture::RG: bpp = 2;
break;
1349 case QOpenGLTexture::Red:
1350 case QOpenGLTexture::Red_Integer:
1351 case QOpenGLTexture::Alpha:
1352 case QOpenGLTexture::Luminance: bpp = 1;
break;
1358 case QOpenGLTexture::Int8:
bytes =
sizeof(GLbyte);
break;
1359 case QOpenGLTexture::UInt8:
bytes =
sizeof(GLubyte);
break;
1360 case QOpenGLTexture::Int16:
bytes =
sizeof(GLshort);
break;
1361 case QOpenGLTexture::UInt16:
bytes =
sizeof(GLushort);
break;
1362 case QOpenGLTexture::Int32:
bytes =
sizeof(GLint);
break;
1363 case QOpenGLTexture::UInt32:
bytes =
sizeof(GLuint);
break;
1364 case QOpenGLTexture::Float32:
bytes =
sizeof(GLfloat);
break;
1365 case QOpenGLTexture::UInt32_RGB10A2:
bytes =
sizeof(GLuint);
break;
1369 if (!bpp || !
bytes || Size.isEmpty())
1372 return Size.width() * Size.height() * bpp *
bytes;
1380 newtop.translate(
static_cast<GLfloat
>(Center.x()),
static_cast<GLfloat
>(Center.y()));
1382 newtop.rotate(Fx.
m_angle, 0, 0, 1);
1383 newtop.translate(
static_cast<GLfloat
>(-Center.x()),
static_cast<GLfloat
>(-Center.y()));
1395 QString
type =
Source.isEmpty() ?
"Shader link" :
"Shader compile";
1396 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"%1 error").arg(
type));
1397 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Log:"));
1398 LOG(VB_GENERAL, LOG_ERR,
"\n" + Shader->log());
1401 LOG(VB_GENERAL, LOG_ERR,
LOC + QString(
"Source:"));
1402 LOG(VB_GENERAL, LOG_ERR,
"\n" +
Source);
1416 auto *program =
new QOpenGLShaderProgram();
1417 if (!program->addShaderFromSourceCode(QOpenGLShader::Vertex, vertex))
1419 if (!program->addShaderFromSourceCode(QOpenGLShader::Fragment, fragment))
1423 QList<QOpenGLShader*> shaders = program->shaders();
1424 for (QOpenGLShader* shader : std::as_const(shaders))
1425 LOG(VB_GENERAL, LOG_DEBUG,
"\n" + shader->sourceCode());
1427 program->bindAttributeLocation(
"a_position",
VERTEX_INDEX);
1428 program->bindAttributeLocation(
"a_color",
COLOR_INDEX);
1429 program->bindAttributeLocation(
"a_texcoord0",
TEXTURE_INDEX);
1430 if (!program->link())
1441 auto *program =
new QOpenGLShaderProgram();
1442 if (!program->addShaderFromSourceCode(QOpenGLShader::Compute,
Source))
1447 QList<QOpenGLShader*> shaders = program->shaders();
1448 for (QOpenGLShader* shader : std::as_const(shaders))
1449 LOG(VB_GENERAL, LOG_DEBUG,
"\n" + shader->sourceCode());
1452 if (!program->link())
1498 QString tag = QString(
"%1-%2").arg(Program->programId()).arg(Uniform);
1502 else if (!qFuzzyCompare(Value, it.value()))
1508 QByteArray uniform(Uniform);
1511 if (uniforms.contains(uniform))
1513 location = uniforms[uniform];
1517 location = Program->uniformLocation(Uniform);
1518 uniforms.insert(uniform, location);
1521 Program->setUniformValue(location, Value);
1555 GLint dedicated = 0;
1556 GLint available = 0;
1560 return { total / 1024, dedicated / 1024, available / 1024 };
1578 QSize size{256, 256};
void * GetEGLDisplay(void)
MythGLTexture(QOpenGLTexture *Texture)
std::array< GLfloat, 16 > m_vertexData
QOpenGLTexture * m_texture
MythRender * GetRenderDevice()
static MythMainWindow * getMainWindow(bool UseDB=true)
Return the existing main window, or create one.
void ExpireVBOS(int Max=0)
void GetCachedVBO(GLuint Type, QRect Area)
void SetShaderProgramParams(QOpenGLShaderProgram *Program, const QMatrix4x4 &Value, const char *Uniform)
QList< uint64_t > m_vertexExpiry
QOpenGLFunctions::OpenGLFeatures m_features
void SetWidget(QWidget *Widget)
MythGLTexture * CreateTextureFromQImage(QImage *Image)
static constexpr GLuint kVertexSize
static int GetBufferSize(QSize Size, QOpenGLTexture::PixelFormat Format, QOpenGLTexture::PixelType Type)
QOpenGLDebugLogger * m_openglDebugger
void ClearRect(QOpenGLFramebufferObject *Target, QRect Area, int Color, int Alpha)
An optimised method to clear a QRect to the given color.
void ActiveTexture(GLuint ActiveTex)
int GetMaxTextureSize(void) const
void DrawProcedural(QRect Area, int Alpha, QOpenGLFramebufferObject *Target, QOpenGLShaderProgram *Program, float TimeVal)
void DrawRoundRect(QOpenGLFramebufferObject *Target, QRect Area, int CornerRadius, const QBrush &FillBrush, const QPen &LinePen, int Alpha)
void contextToBeDestroyed(void)
QStack< QMatrix4x4 > m_transforms
static MythRenderOpenGL * Create(QWidget *Widget)
int GetMaxTextureUnits(void) const
void DrawBitmap(MythGLTexture *Texture, QOpenGLFramebufferObject *Target, QRect Source, QRect Destination, QOpenGLShaderProgram *Program, int Alpha=255, qreal Scale=1.0)
void ClearFramebuffer(void)
QMap< uint64_t, QOpenGLBuffer * > m_cachedVBOS
QHash< QString, QMatrix4x4 > m_cachedMatrixUniforms
void SetViewPort(QRect Rect, bool ViewportOnly=false) override
void DeleteShaderProgram(QOpenGLShaderProgram *Program)
void BindFramebuffer(QOpenGLFramebufferObject *Framebuffer)
QOpenGLShaderProgram * m_activeProgram
void DeleteFramebuffer(QOpenGLFramebufferObject *Framebuffer)
MythRenderOpenGL(const QSurfaceFormat &Format, QWidget *Widget)
void DeleteDefaultShaders(void)
void MessageLogged(const QOpenGLDebugMessage &Message)
void PushTransformation(const UIEffects &Fx, QPointF &Center)
QOpenGLFunctions::OpenGLFeatures GetFeatures(void) const
void PopTransformation(void)
bool EnableShaderProgram(QOpenGLShaderProgram *Program)
void SetBlend(bool Enable)
bool IsRecommendedRenderer(void)
QOpenGLDebugMessage::Types m_openGLDebuggerFilter
QOpenGLBuffer * CreateVBO(int Size, bool Release=true)
~MythRenderOpenGL() override
void logDebugMarker(const QString &Message)
void Check16BitFBO(void)
Check for 16bit framebufferobject support.
GLfloat * GetCachedVertices(GLuint Type, QRect Area)
QHash< QOpenGLShaderProgram *, QHash< QByteArray, GLint > > m_cachedUniformLocations
GLuint m_activeFramebuffer
QOpenGLFramebufferObject * CreateFramebuffer(QSize &Size, bool SixteenBit=false)
void SetBackground(uint8_t Red, uint8_t Green, uint8_t Blue, uint8_t Alpha)
QOpenGLShaderProgram * CreateShaderProgram(const QString &Vertex, const QString &Fragment)
QFunctionPointer GetProcAddress(const QString &Proc) const
void glVertexAttribPointerI(GLuint Index, GLint Size, GLenum Type, GLboolean Normalize, GLsizei Stride, GLuint Value)
static bool UpdateTextureVertices(MythGLTexture *Texture, QRect Source, QRect Destination, int Rotation, qreal Scale=1.0)
QMap< uint64_t, GLfloat * > m_cachedVertices
void DeleteTexture(MythGLTexture *Texture)
static MythRenderOpenGL * GetOpenGLRender(void)
QSize GetTextureSize(QSize Size, bool Normalised)
void DrawRect(QOpenGLFramebufferObject *Target, QRect Area, const QBrush &FillBrush, const QPen &LinePen, int Alpha)
MythGLTexture * CreateFramebufferTexture(QOpenGLFramebufferObject *Framebuffer)
This is no longer used but will probably be needed for future UI enhancements.
std::tuple< int, int, int > GetGPUMemory()
int GetExtraFeatures(void) const
bool CreateDefaultShaders(void)
void SetShaderProjection(QOpenGLShaderProgram *Program)
QList< uint64_t > m_vboExpiry
std::array< QOpenGLShaderProgram *, kShaderCount > m_defaultPrograms
void SetTextureFilters(MythGLTexture *Texture, QOpenGLTexture::Filter Filter, QOpenGLTexture::WrapMode Wrap=QOpenGLTexture::ClampToEdge)
void ReleaseResources(void) override
void ExpireVertices(int Max=0)
QStringList GetDescription(void) override
static int GetTextureDataSize(MythGLTexture *Texture)
QOpenGLShaderProgram * CreateComputeShader(const QString &Source)
RenderType Type(void) const
static bool DisplayIsRemote()
Determine if we are running a remote X11 session.
OpenGLLocker(MythRenderOpenGL *Render)
MythRenderOpenGL * m_render
MythCoreContext * gCoreContext
This global variable contains the MythCoreContext instance for the app.
static bool VERBOSE_LEVEL_CHECK(uint64_t mask, LogLevel_t level)
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
bool HasMythMainWindow(void)
static constexpr QLatin1String GLYesNo(bool v)
static constexpr GLuint kTextureOffset
static const float kLimitedRangeScale
static constexpr GLint TEXTURE_SIZE
static constexpr GLuint TEXTURE_INDEX
static constexpr GLuint COLOR_INDEX
QOpenGLShaderProgram * ShaderError(QOpenGLShaderProgram *Shader, const QString &Source)
static const float kLimitedRangeOffset
static constexpr int MAX_VERTEX_CACHE
static constexpr GLuint VERTEX_INDEX
static constexpr GLuint kVertexOffset
static constexpr GLint VERTEX_SIZE
static constexpr size_t TEX_OFFSET
#define GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX
#define GPU_MEMORY_INFO_DEDICATED_VIDMEM_NVX
#define GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX
GLboolean(APIENTRY *)(GLenum target) MYTH_GLUNMAPBUFFERPROC
GLvoid *(APIENTRY *)(GLenum target, GLenum access) MYTH_GLMAPBUFFERPROC
static const QString kRoundedEdgeShader
static const QString kDefaultVertexShader
static const QString kRoundedRectShader
static const QString kDrawVertexShader
static const QString kDefaultFragmentShaderLimited
static const QString kSimpleVertexShader
static const QString kDefaultFragmentShader
static const QString kSimpleFragmentShader
MBASE_PUBLIC long long copy(QFile &dst, QFile &src, uint block_size=0)
Copies src file to dst file.
static QString Source(const QNetworkRequest &request)
VERBOSE_PREAMBLE Most true
VERBOSE_PREAMBLE Most debug(nodatabase, notimestamp, noextra)") VERBOSE_MAP(VB_GENERAL