Skip to content

Commit

Permalink
MythRenderOpenGL: Remove Pixelbuffer Object support
Browse files Browse the repository at this point in the history
- I can't find a single implementation where using them is still faster
- looks like the world has moved on and I suspect most drivers are
mapping memory directly for texture uploads by default.
- wasn't available on GLES anyway
  • Loading branch information
mark-kendall committed Jan 28, 2019
1 parent 8233b32 commit 508e8a6
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 169 deletions.
90 changes: 48 additions & 42 deletions mythtv/libs/libmythtv/openglvideo.cpp
Expand Up @@ -150,14 +150,6 @@ bool OpenGLVideo::Init(MythRenderOpenGL *glcontext, VideoColourSpace *colourspac
else
m_extraFeatures &= ~kGLExtFBDiscard;
}
else
{
if ((m_extraFeatures & kGLExtPBufObj) && !enablePBOs)
{
LOG(VB_GENERAL, LOG_INFO, LOC + "Disabling Pixel Buffer Objects");
m_extraFeatures &= ~kGLExtPBufObj;
}
}

if (viewportControl)
gl_context->SetFence();
Expand Down Expand Up @@ -650,23 +642,22 @@ void OpenGLVideo::SetViewPort(const QSize &viewPortSize)
MythGLTexture* OpenGLVideo::CreateVideoTexture(QSize size, QSize &tex_size)
{
MythGLTexture *texture = nullptr;
bool pbo = m_extraFeatures & kGLExtPBufObj;
if (kGLYV12 == videoType)
{
size.setHeight((3 * size.height() + 1) / 2);
texture = gl_context->CreateTexture(size, pbo,
texture = gl_context->CreateTexture(size,
QOpenGLTexture::UInt8, QOpenGLTexture::Luminance,
QOpenGLTexture::Linear, QOpenGLTexture::ClampToEdge,
QOpenGLTexture::LuminanceFormat);
}
else if (kGLUYVY == videoType)
{
size.setWidth(size.width() >> 1);
texture = gl_context->CreateTexture(size, pbo);
texture = gl_context->CreateTexture(size);
}
else if ((kGLHQUYV == videoType) || (kGLGPU == videoType) || (kGLRGBA == videoType))
{
texture = gl_context->CreateTexture(size, pbo);
texture = gl_context->CreateTexture(size);
}

tex_size = gl_context->GetTextureSize(size);
Expand Down Expand Up @@ -703,43 +694,58 @@ void OpenGLVideo::UpdateInputFrame(const VideoFrame *frame)
if (hardwareDeinterlacing)
RotateTextures();

// We need to convert frames here to avoid dependencies in MythRenderOpenGL
MythGLTexture *texture = inputTextures[0];
if (!texture)
return;

// A buffer is not needed if we are transferring a YV12 frame directly without
// any conversion. If a Pixel Buffer Object is being used - that will however
// be returned and will need to be copied to.
bool usebuffer = !((kGLYV12 == videoType) && (video_dim.width() == frame->pitches[0]));
void* buf = gl_context->GetTextureBuffer(inputTextures[0], usebuffer);
if (!buf)
void* buf = nullptr;
if ((kGLYV12 == videoType) && (video_dim.width() == frame->pitches[0]))
{
buf = frame->buf;
}
else if (kGLYV12 == videoType)
{
copybuffer((uint8_t*)buf, frame, video_dim.width());
}
else if (kGLUYVY == videoType)
{
AVFrame img_out;
m_copyCtx.Copy(&img_out, frame, (unsigned char*)buf, AV_PIX_FMT_UYVY422);
}
else if (kGLRGBA == videoType)
{
AVFrame img_out;
m_copyCtx.Copy(&img_out, frame, (unsigned char*)buf, AV_PIX_FMT_RGBA);
}
else if (kGLHQUYV == videoType && frame->interlaced_frame)
{
pack_yv12interlaced(frame->buf, (unsigned char*)buf, frame->offsets,
frame->pitches, video_dim);
}
else if (kGLHQUYV == videoType)
else
{
pack_yv12progressive(frame->buf, (unsigned char*)buf, frame->offsets,
frame->pitches, video_dim);
// create a storage buffer
if (!texture->m_data)
{
unsigned char *scratch = new unsigned char[texture->m_bufferSize];
if (scratch)
{
memset(scratch, 0, texture->m_bufferSize);
texture->m_data = scratch;
}
}
if (!texture->m_data)
return;
buf = texture->m_data;

if (kGLYV12 == videoType)
{
copybuffer((uint8_t*)buf, frame, video_dim.width());
}
else if (kGLUYVY == videoType)
{
AVFrame img_out;
m_copyCtx.Copy(&img_out, frame, (unsigned char*)buf, AV_PIX_FMT_UYVY422);
}
else if (kGLRGBA == videoType)
{
AVFrame img_out;
m_copyCtx.Copy(&img_out, frame, (unsigned char*)buf, AV_PIX_FMT_RGBA);
}
else if (kGLHQUYV == videoType && frame->interlaced_frame)
{
pack_yv12interlaced(frame->buf, (unsigned char*)buf, frame->offsets,
frame->pitches, video_dim);
}
else if (kGLHQUYV == videoType)
{
pack_yv12progressive(frame->buf, (unsigned char*)buf, frame->offsets,
frame->pitches, video_dim);
}
}

gl_context->UpdateTexture(inputTextures[0], buf);
texture->m_texture->setData(texture->m_pixelFormat, texture->m_pixelType, buf);

if (VERBOSE_LEVEL_CHECK(VB_GPU, LOG_INFO))
gl_context->logDebugMarker(LOC + "UPDATE_FRAME_END");
Expand Down
25 changes: 14 additions & 11 deletions mythtv/libs/libmythtv/visualisations/videovisualgoom.cpp
Expand Up @@ -94,21 +94,24 @@ void VideoVisualGoom::Draw(const QRect &area, MythPainter */*painter*/,
if ((m_render->Type() == kRenderOpenGL))
{
MythRenderOpenGL *glrender = static_cast<MythRenderOpenGL*>(m_render);
if (!m_glSurface && glrender && m_buffer)
if (glrender && m_buffer)
{
m_glSurface = glrender->CreateTexture(m_area.size(), true);
}
glrender->makeCurrent();

if (m_glSurface && glrender && m_buffer)
{
if (m_buffer != last)
if (!m_glSurface)
m_glSurface = glrender->CreateTexture(m_area.size());

if (m_glSurface)
{
void* buf = glrender->GetTextureBuffer(m_glSurface, false);
if (buf)
memcpy(buf, m_buffer, m_area.width() * m_area.height() * 4);
glrender->UpdateTexture(m_glSurface, (void*)m_buffer);
if (m_buffer != last)
m_glSurface->m_texture->setData(m_glSurface->m_pixelFormat, m_glSurface->m_pixelType, m_buffer);
// goom doesn't render properly due to changes in video alpha blending
// so turn blend off
glrender->SetBlend(false);
glrender->DrawBitmap(&m_glSurface, 1, nullptr, m_area, area, nullptr);
glrender->SetBlend(true);
}
glrender->DrawBitmap(&m_glSurface, 1, nullptr, m_area, area, nullptr);
glrender->doneCurrent();
}
return;
}
Expand Down
94 changes: 1 addition & 93 deletions mythtv/libs/libmythui/mythrender_opengl.cpp
Expand Up @@ -51,7 +51,6 @@ MythGLTexture::MythGLTexture(QOpenGLTexture *Texture)
m_texture(Texture),
m_pixelFormat(QOpenGLTexture::RGBA),
m_pixelType(QOpenGLTexture::UInt8),
m_pbo(nullptr),
m_vbo(nullptr),
m_size(0,0),
m_totalSize(0,0),
Expand All @@ -70,7 +69,6 @@ MythGLTexture::MythGLTexture(GLuint Texture)
m_texture(nullptr),
m_pixelFormat(QOpenGLTexture::RGBA),
m_pixelType(QOpenGLTexture::UInt8),
m_pbo(nullptr),
m_vbo(nullptr),
m_size(0,0),
m_totalSize(0,0),
Expand Down Expand Up @@ -253,8 +251,6 @@ bool MythRenderOpenGL::Init(void)
// Pixel buffer objects
bool buffer_procs = (MYTH_GLMAPBUFFERPROC)GetProcAddress("glMapBuffer") &&
(MYTH_GLUNMAPBUFFERPROC)GetProcAddress("glUnmapBuffer");
if (!isOpenGLES() && hasExtension("GL_ARB_pixel_buffer_object") && buffer_procs)
m_extraFeatures |= kGLExtPBufObj;

// Buffers are available by default (GL and GLES).
// Buffer mapping is available by extension
Expand Down Expand Up @@ -321,7 +317,6 @@ void MythRenderOpenGL::DebugFeatures(void)
LOG(VB_GENERAL, LOG_INFO, LOC + QString("Buffer mapping : %1").arg(GLYesNo(m_extraFeatures & kGLBufferMap)));
LOG(VB_GENERAL, LOG_INFO, LOC + QString("Framebuffer objects : %1").arg(GLYesNo(m_features & Framebuffers)));
LOG(VB_GENERAL, LOG_INFO, LOC + QString("Framebuffer discard : %1").arg(GLYesNo(m_extraFeatures & kGLExtFBDiscard)));
LOG(VB_GENERAL, LOG_INFO, LOC + QString("Pixelbuffer objects : %1").arg(GLYesNo(m_extraFeatures & kGLExtPBufObj)));
LOG(VB_GENERAL, LOG_INFO, LOC + QString("Fence : %1")
.arg(GLYesNo((m_extraFeatures & kGLAppleFence) || (m_extraFeatures & kGLNVFence))));

Expand Down Expand Up @@ -528,60 +523,7 @@ void MythRenderOpenGL::DeleteFence(void)
}
}

void* MythRenderOpenGL::GetTextureBuffer(MythGLTexture *Texture, bool create_buffer)
{
if (!Texture || (Texture && !Texture->m_texture))
return nullptr;

makeCurrent(); // associated doneCurrent() in UpdateTexture
EnableTextures();

if (Texture->m_pbo)
{
Texture->m_pbo->bind();
return Texture->m_pbo->map(QOpenGLBuffer::WriteOnly);
}
else if (!create_buffer)
{
return nullptr;
}

if (Texture->m_data)
return Texture->m_data;
if (!Texture->m_bufferSize)
return nullptr;

unsigned char *scratch = new unsigned char[Texture->m_bufferSize];
if (scratch)
{
memset(scratch, 0, Texture->m_bufferSize);
Texture->m_data = scratch;
}
return scratch;
}

void MythRenderOpenGL::UpdateTexture(MythGLTexture *Texture, void *buf)
{
// N.B. GetTextureBuffer must be called first
if (!Texture)
return;

if (Texture->m_pbo)
{
Texture->m_pbo->unmap();
Texture->m_texture->setData(Texture->m_pixelFormat, Texture->m_pixelType, nullptr);
Texture->m_pbo->release(QOpenGLBuffer::PixelUnpackBuffer);
}
else
{
Texture->m_texture->setData(Texture->m_pixelFormat, Texture->m_pixelType, buf);
}

doneCurrent();
}

MythGLTexture* MythRenderOpenGL::CreateTexture(QSize Size,
bool UsePBO,
QOpenGLTexture::PixelType PixelType,
QOpenGLTexture::PixelFormat PixelFormat,
QOpenGLTexture::Filter Filter,
Expand Down Expand Up @@ -623,8 +565,6 @@ MythGLTexture* MythRenderOpenGL::CreateTexture(QSize Size,
result->m_totalSize = GetTextureSize(Size);
result->m_bufferSize = datasize;
result->m_size = Size;
if (UsePBO)
result->m_pbo = CreatePBO(datasize);
return result;
}

Expand Down Expand Up @@ -661,7 +601,7 @@ MythGLTexture* MythRenderOpenGL::CreateHelperTexture(void)
makeCurrent();

uint width = m_max_tex_size;
MythGLTexture *texture = CreateTexture(QSize(width, 1), false,
MythGLTexture *texture = CreateTexture(QSize(width, 1),
QOpenGLTexture::Float32,
QOpenGLTexture::RGBA,
QOpenGLTexture::Linear,
Expand Down Expand Up @@ -812,8 +752,6 @@ void MythRenderOpenGL::DeleteTexture(MythGLTexture *Texture)
delete Texture->m_texture;
if (Texture->m_data)
delete [] Texture->m_data;
if (Texture->m_pbo)
delete Texture->m_pbo;
if (Texture->m_vbo)
delete Texture->m_vbo;
delete Texture;
Expand Down Expand Up @@ -1396,36 +1334,6 @@ void MythRenderOpenGL::ResetProcs(void)
m_glDiscardFramebuffer = nullptr;
}

QOpenGLBuffer* MythRenderOpenGL::CreatePBO(uint BufferSize)
{
OpenGLLocker locker(this);
if (!(m_extraFeaturesUsed & kGLExtPBufObj) || !BufferSize)
return nullptr;

QOpenGLBuffer *buffer = new QOpenGLBuffer(QOpenGLBuffer::PixelUnpackBuffer);
if (buffer->create())
{
buffer->setUsagePattern(QOpenGLBuffer::StreamDraw);
buffer->bind();
buffer->allocate(BufferSize);
buffer->release(QOpenGLBuffer::PixelUnpackBuffer);
return buffer;
}
else
{
LOG(VB_GENERAL, LOG_WARNING, LOC + "Failed to create Pixel Buffer Object");
if (glCheck())
{
LOG(VB_GENERAL, LOG_INFO, LOC + "Pixel Buffer Objects unusable, disabling");
m_extraFeatures &= ~kGLExtPBufObj;
m_extraFeaturesUsed &= ~kGLExtPBufObj;
}
delete buffer;
buffer = nullptr;
}
return buffer;
}

QOpenGLBuffer* MythRenderOpenGL::CreateVBO(uint Size, bool Release /*=true*/)
{
OpenGLLocker locker(this);
Expand Down
15 changes: 5 additions & 10 deletions mythtv/libs/libmythui/mythrender_opengl.h
Expand Up @@ -30,11 +30,10 @@ typedef enum
{
kGLFeatNone = 0x0000,
kGLExtFBDiscard= 0x0001,
kGLExtPBufObj = 0x0002,
kGLNVFence = 0x0004,
kGLAppleFence = 0x0008,
kGLBufferMap = 0x0010,
kGLExtRGBA16 = 0x0020
kGLNVFence = 0x0002,
kGLAppleFence = 0x0004,
kGLBufferMap = 0x0008,
kGLExtRGBA16 = 0x0010
} GLFeatures;

#define TEX_OFFSET 8
Expand All @@ -52,7 +51,6 @@ class MUI_PUBLIC MythGLTexture
QOpenGLTexture *m_texture;
QOpenGLTexture::PixelFormat m_pixelFormat;
QOpenGLTexture::PixelType m_pixelType;
QOpenGLBuffer *m_pbo;
QOpenGLBuffer *m_vbo;
QSize m_size;
QSize m_totalSize;
Expand Down Expand Up @@ -114,10 +112,8 @@ class MUI_PUBLIC MythRenderOpenGL : public QOpenGLContext, protected QOpenGLFunc
void SetFence(void);
void DeleteFence(void);

void* GetTextureBuffer(MythGLTexture *Texture, bool create_buffer);
void UpdateTexture(MythGLTexture *Texture, void *buf);
MythGLTexture* CreateHelperTexture(void);
MythGLTexture* CreateTexture(QSize Size, bool UsePBO,
MythGLTexture* CreateTexture(QSize Size,
QOpenGLTexture::PixelType PixelType = QOpenGLTexture::UInt8,
QOpenGLTexture::PixelFormat PixelFormat = QOpenGLTexture::RGBA,
QOpenGLTexture::Filter Filter = QOpenGLTexture::Linear,
Expand Down Expand Up @@ -186,7 +182,6 @@ class MUI_PUBLIC MythRenderOpenGL : public QOpenGLContext, protected QOpenGLFunc
void ResetProcs(void);
void SetMatrixView(void);

QOpenGLBuffer* CreatePBO(uint BufferSize);
QOpenGLBuffer* CreateVBO(uint Size, bool Release = true);
void DeleteOpenGLResources(void);
void DeleteFramebuffers(void);
Expand Down
13 changes: 0 additions & 13 deletions mythtv/programs/mythfrontend/globalsettings.cpp
Expand Up @@ -143,17 +143,6 @@ static HostCheckBoxSetting *OpenGLDiscardFB()
gc->setValue(false);
return gc;
}

static HostCheckBoxSetting *OpenGLEnablePBO()
{
HostCheckBoxSetting *gc = new HostCheckBoxSetting("OpenGLEnablePBO");
gc->setLabel(PlaybackSettings::tr("Enable Pixel Buffer Objects for OpenGL video"));
gc->setHelpText(PlaybackSettings::tr(
"Pixel Buffer Objects are enabled by default to improve video playback "
"but on some integrated GPUs (e.g. Intel) they are not needed and will reduce performance."));
gc->setValue(true);
return gc;
}
#endif

#if CONFIG_DEBUGTYPE
Expand Down Expand Up @@ -4288,8 +4277,6 @@ void PlaybackSettings::Load(void)
advanced->addChild(OpenGLExtraStage());
if (isOpenGLES)
advanced->addChild(OpenGLDiscardFB());
else
advanced->addChild(OpenGLEnablePBO());
#endif
addChild(advanced);

Expand Down

0 comments on commit 508e8a6

Please sign in to comment.