Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

LinuxRenderer fixes #1408

Merged
merged 2 commits into from

4 participants

@FernetMenta
Collaborator

This fixes/improves de-interlacing method weave when upscaling. Both fields are rendered into a fbo of original size first, then the fbo gets rendered and upscaled.

@elupus
this is follow-up from our discussion here: FernetMenta@975d03b

@FernetMenta
Collaborator

@elupus ping, do you have time to review this?

@elupus
Collaborator

Could you explain a bit more in detail what it improves?

@elupus
Collaborator

The first commit we can be merged as soon as merge window open. It could be improved I suppose by create a struct for holding the fbo properties, and having RenderFromFbo taking that as a parameter. But it is better than current code anyway.

@FernetMenta
Collaborator

There's two things it improves when doing a weave:

1)
Quality:
It renders both fields to the fbo at the same size as source. Then it renders the fbo (holding both fields) and does upscaling.

2)
Performance:
It first collects both fields into the fbo, then renders the fbo only once.

@elupus
Collaborator

How does that work. You can't scale a weaved image.. Each field need to be scaled separate.

@FernetMenta
Collaborator

Ok, then we need to distinguish between weaving/scaling of interlaced fields and fields of a progressive frame. The latter needs scaling after the fields have been combined.

@elupus
Collaborator

Yes, if we get separate fields for a progressive source we need to do that yes. It's only vdpau interrop that does so currently right?

@FernetMenta
Collaborator

Yes. Then I keep the first and 3rd commit in this PR and move the second (progressive weave) to #870?

@bobo1on1
Collaborator

For VDPAU interop I would write a shader that directly weaves the fields, most of the slower gpu's can't handle going through an fbo first at 1080p.

@FernetMenta
Collaborator

@bobo1on1
It won't go through the fbo it no upscaling is needed. Nevertheless I have written a prototype for this kind of shader (see link above), but then dropped this idea. If you think using a shader is better I have to put the pieces together.

@bobo1on1
Collaborator

Ah right, in that case it would be faster to render to an fbo first.

@elupus elupus was assigned
@FernetMenta
Collaborator

@elupus
I dropped the change on weave and created a struct for the fbo related parameters.

@ghost

ping

@fritsch
Collaborator

Can we please include at least the second commit: "proper cleanup"?

Yesterday there was somebody on IRC, that saw the scene from the played video before in his "black screensaver" - cause of the Renderer is not cleaned up properly ...

Afaik today (10th) the merge window is ending, right?

@elupus
Collaborator
@FernetMenta FernetMenta merged commit 77a49e8 into xbmc:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
84 xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
@@ -256,6 +256,15 @@ bool CLinuxRendererGL::ValidateRenderTarget()
else
CLog::Log(LOGNOTICE,"Using GL_TEXTURE_2D");
+ // function pointer for texture might change in
+ // call to LoadShaders
+ glFinish();
+ for (int i = 0 ; i < m_NumYV12Buffers ; i++)
+ (this->*m_textureDelete)(i);
+
+ // trigger update of video filters
+ m_scalingMethodGui = (ESCALINGMETHOD)-1;
+
// create the yuv textures
LoadShaders();
@@ -593,6 +602,7 @@ void CLinuxRendererGL::Flush()
glFinish();
m_bValidated = false;
+ m_fbo.fbo.Cleanup();
}
void CLinuxRendererGL::Update(bool bPauseDrawing)
@@ -847,7 +857,7 @@ void CLinuxRendererGL::UpdateVideoFilter()
delete m_pVideoFilterShader;
m_pVideoFilterShader = NULL;
}
- m_fbo.Cleanup();
+ m_fbo.fbo.Cleanup();
VerifyGLState();
@@ -888,13 +898,13 @@ void CLinuxRendererGL::UpdateVideoFilter()
case VS_SCALINGMETHOD_CUBIC:
if (m_renderMethod & RENDER_GLSL)
{
- if (!m_fbo.Initialize())
+ if (!m_fbo.fbo.Initialize())
{
CLog::Log(LOGERROR, "GL: Error initializing FBO");
break;
}
- if (!m_fbo.CreateAndBindToTexture(GL_TEXTURE_2D, m_sourceWidth, m_sourceHeight, GL_RGBA))
+ if (!m_fbo.fbo.CreateAndBindToTexture(GL_TEXTURE_2D, m_sourceWidth, m_sourceHeight, GL_RGBA))
{
CLog::Log(LOGERROR, "GL: Error creating texture and binding to FBO");
break;
@@ -932,7 +942,7 @@ void CLinuxRendererGL::UpdateVideoFilter()
delete m_pVideoFilterShader;
m_pVideoFilterShader = NULL;
}
- m_fbo.Cleanup();
+ m_fbo.fbo.Cleanup();
SetTextureFilter(GL_LINEAR);
m_renderQuality = RQ_SINGLEPASS;
@@ -1141,7 +1151,7 @@ void CLinuxRendererGL::UnInit()
(this->*m_textureDelete)(i);
// cleanup framebuffer object if it was in use
- m_fbo.Cleanup();
+ m_fbo.fbo.Cleanup();
m_bValidated = false;
m_bImageReady = false;
m_bConfigured = false;
@@ -1299,6 +1309,12 @@ void CLinuxRendererGL::RenderSinglePass(int index, int field)
void CLinuxRendererGL::RenderMultiPass(int index, int field)
{
+ RenderToFBO(index, field);
+ RenderFromFBO();
+}
+
+void CLinuxRendererGL::RenderToFBO(int index, int field)
+{
YUVPLANES &planes = m_buffers[index].fields[field];
if (m_reloadShaders)
@@ -1307,6 +1323,21 @@ void CLinuxRendererGL::RenderMultiPass(int index, int field)
LoadShaders(m_currentField);
}
+ if (!m_fbo.fbo.IsValid())
+ {
+ if (!m_fbo.fbo.Initialize())
+ {
+ CLog::Log(LOGERROR, "GL: Error initializing FBO");
+ return;
+ }
+
+ if (!m_fbo.fbo.CreateAndBindToTexture(GL_TEXTURE_2D, m_sourceWidth, m_sourceHeight, GL_RGBA))
+ {
+ CLog::Log(LOGERROR, "GL: Error creating texture and binding to FBO");
+ return;
+ }
+ }
+
glDisable(GL_DEPTH_TEST);
// Y
@@ -1337,7 +1368,7 @@ void CLinuxRendererGL::RenderMultiPass(int index, int field)
return;
}
- m_fbo.BeginRender();
+ m_fbo.fbo.BeginRender();
VerifyGLState();
m_pYUVShader->SetBlack(g_settings.m_currentVideoSettings.m_Brightness * 0.01f - 0.5f);
@@ -1375,15 +1406,15 @@ void CLinuxRendererGL::RenderMultiPass(int index, int field)
CLog::Log(LOGERROR, "GL: Error enabling YUV shader");
}
- float imgwidth = planes[0].rect.x2 - planes[0].rect.x1;
- float imgheight = planes[0].rect.y2 - planes[0].rect.y1;
+ m_fbo.width = planes[0].rect.x2 - planes[0].rect.x1;
+ m_fbo.height = planes[0].rect.y2 - planes[0].rect.y1;
if (m_textureTarget == GL_TEXTURE_2D)
{
- imgwidth *= planes[0].texwidth;
- imgheight *= planes[0].texheight;
+ m_fbo.width *= planes[0].texwidth;
+ m_fbo.height *= planes[0].texheight;
}
- imgwidth *= planes[0].pixpertex_x;
- imgheight *= planes[0].pixpertex_y;
+ m_fbo.width *= planes[0].pixpertex_x;
+ m_fbo.height *= planes[0].pixpertex_y;
// 1st Pass to video frame size
glBegin(GL_QUADS);
@@ -1396,17 +1427,17 @@ void CLinuxRendererGL::RenderMultiPass(int index, int field)
glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y1);
glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y1);
glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y1);
- glVertex2f(imgwidth, 0.0f);
+ glVertex2f(m_fbo.width, 0.0f);
glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x2, planes[0].rect.y2);
glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x2, planes[1].rect.y2);
glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x2, planes[2].rect.y2);
- glVertex2f(imgwidth, imgheight);
+ glVertex2f(m_fbo.width, m_fbo.height);
glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y2);
glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y2);
glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y2);
- glVertex2f(0.0f , imgheight);
+ glVertex2f(0.0f , m_fbo.height);
glEnd();
VerifyGLState();
@@ -1422,7 +1453,7 @@ void CLinuxRendererGL::RenderMultiPass(int index, int field)
glMatrixMode(GL_MODELVIEW);
VerifyGLState();
- m_fbo.EndRender();
+ m_fbo.fbo.EndRender();
glActiveTextureARB(GL_TEXTURE1);
glDisable(m_textureTarget);
@@ -1430,9 +1461,12 @@ void CLinuxRendererGL::RenderMultiPass(int index, int field)
glDisable(m_textureTarget);
glActiveTextureARB(GL_TEXTURE0);
glDisable(m_textureTarget);
+}
- glEnable(GL_TEXTURE_2D);
- glBindTexture(GL_TEXTURE_2D, m_fbo.Texture());
+void CLinuxRendererGL::RenderFromFBO()
+{
+ glEnable(m_textureTarget);
+ glActiveTextureARB(GL_TEXTURE0);
VerifyGLState();
// Use regular normalized texture coordinates
@@ -1445,7 +1479,7 @@ void CLinuxRendererGL::RenderMultiPass(int index, int field)
if (!m_pVideoFilterShader->GetTextureFilter(filter))
filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR;
- m_fbo.SetFiltering(GL_TEXTURE_2D, filter);
+ m_fbo.fbo.SetFiltering(m_textureTarget, filter);
m_pVideoFilterShader->SetSourceTexture(0);
m_pVideoFilterShader->SetWidth(m_sourceWidth);
m_pVideoFilterShader->SetHeight(m_sourceHeight);
@@ -1462,17 +1496,18 @@ void CLinuxRendererGL::RenderMultiPass(int index, int field)
else
{
GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR;
- m_fbo.SetFiltering(GL_TEXTURE_2D, filter);
+ m_fbo.fbo.SetFiltering(m_textureTarget, filter);
+ glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
VerifyGLState();
- imgwidth /= m_sourceWidth;
- imgheight /= m_sourceHeight;
+ float imgwidth = m_fbo.width / m_sourceWidth;
+ float imgheight = m_fbo.height / m_sourceHeight;
glBegin(GL_QUADS);
- glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , 0.0f);
+ glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f, 0.0f);
glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0, 1.0f );
glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, 0.0f);
@@ -1481,7 +1516,7 @@ void CLinuxRendererGL::RenderMultiPass(int index, int field)
glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, imgheight);
glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 0, 1.0f );
- glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f , imgheight);
+ glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f, imgheight);
glVertex4f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y, 0, 1.0f );
glEnd();
@@ -1493,6 +1528,7 @@ void CLinuxRendererGL::RenderMultiPass(int index, int field)
VerifyGLState();
+ glBindTexture(m_textureTarget, 0);
glDisable(m_textureTarget);
VerifyGLState();
}
View
8 xbmc/cores/VideoRenderers/LinuxRendererGL.h
@@ -213,12 +213,18 @@ class CLinuxRendererGL : public CBaseRenderer
// renderers
void RenderMultiPass(int renderBuffer, int field); // multi pass glsl renderer
+ void RenderToFBO(int renderBuffer, int field);
+ void RenderFromFBO();
void RenderSinglePass(int renderBuffer, int field); // single pass glsl renderer
void RenderSoftware(int renderBuffer, int field); // single pass s/w yuv2rgb renderer
void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware
void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware
- CFrameBufferObject m_fbo;
+ struct
+ {
+ CFrameBufferObject fbo;
+ float width, height;
+ } m_fbo;
int m_iYV12RenderBuffer;
int m_NumYV12Buffers;
Something went wrong with that request. Please try again.