diff options
-rw-r--r-- | system/shaders/yuv2rgb_bob_gles.glsl | 33 | ||||
-rw-r--r-- | xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp | 181 | ||||
-rw-r--r-- | xbmc/cores/VideoRenderers/LinuxRendererGLES.h | 4 |
3 files changed, 112 insertions, 106 deletions
diff --git a/system/shaders/yuv2rgb_bob_gles.glsl b/system/shaders/yuv2rgb_bob_gles.glsl index 292541aa77..f76b5a5ebc 100644 --- a/system/shaders/yuv2rgb_bob_gles.glsl +++ b/system/shaders/yuv2rgb_bob_gles.glsl @@ -18,7 +18,7 @@ * */ -precision mediump float; +precision highp float; uniform sampler2D m_sampY; uniform sampler2D m_sampU; uniform sampler2D m_sampV; @@ -38,18 +38,37 @@ void main() vec2 offsetY; vec2 offsetU; vec2 offsetV; - float temp1 = mod(m_cordY.y, 2*m_stepY); + float temp1 = mod(m_cordY.y, 2.0*m_stepY); offsetY = m_cordY; offsetU = m_cordU; offsetV = m_cordV; - offsetY.y -= (temp1 - m_stepY/2 + float(m_field)*m_stepY); - offsetU.y -= (temp1 - m_stepY/2 + float(m_field)*m_stepY)/2; - offsetV.y -= (temp1 - m_stepY/2 + float(m_field)*m_stepY)/2; + offsetY.y -= (temp1 - m_stepY/2.0 + float(m_field)*m_stepY); + offsetU.y -= (temp1 - m_stepY/2.0 + float(m_field)*m_stepY)/2.0; + offsetV.y -= (temp1 - m_stepY/2.0 + float(m_field)*m_stepY)/2.0; - yuv.rgba = vec4(texture2D(m_sampY, offsetY).r, texture2D(m_sampU, offsetU).r, texture2D(m_sampV, offsetV).r, 1.0); + float bstep = step(m_stepY, temp1); + + // Blend missing line + vec2 belowY, belowU, belowV; + + belowY.x = offsetY.x; + belowY.y = offsetY.y + (2.0*m_stepY*bstep); + belowU.x = offsetU.x; + belowU.y = offsetU.y + (m_stepY*bstep); + belowV.x = offsetV.x; + belowV.y = offsetV.y + (m_stepY*bstep); + + vec4 yuvBelow, rgbBelow; + + yuv.rgba = vec4(texture2D(m_sampY, offsetY).r, texture2D(m_sampU, offsetU).g, texture2D(m_sampV, offsetV).a, 1.0); rgb = m_yuvmat * yuv; rgb.a = m_alpha; - gl_FragColor = rgb; + + yuvBelow.rgba = vec4(texture2D(m_sampY, belowY).r, texture2D(m_sampU, belowU).g, texture2D(m_sampV, belowV).a, 1.0); + rgbBelow = m_yuvmat * yuvBelow; + rgbBelow.a = m_alpha; + + gl_FragColor.rgba = mix(rgb, rgbBelow, 0.5); } diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp index 1d99eca7fb..7c94afcc81 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp @@ -143,7 +143,8 @@ CLinuxRendererGLES::CLinuxRendererGLES() m_flipindex = 0; m_currentField = FIELD_FULL; m_reloadShaders = 0; - m_pYUVShader = NULL; + m_pYUVProgShader = NULL; + m_pYUVBobShader = NULL; m_pVideoFilterShader = NULL; m_scalingMethod = VS_SCALINGMETHOD_LINEAR; m_scalingMethodGui = (ESCALINGMETHOD)-1; @@ -203,12 +204,7 @@ CLinuxRendererGLES::~CLinuxRendererGLES() m_rgbBuffer = NULL; } - if (m_pYUVShader) - { - m_pYUVShader->Free(); - delete m_pYUVShader; - m_pYUVShader = NULL; - } + ReleaseShaders(); } bool CLinuxRendererGLES::ValidateRenderTarget() @@ -585,14 +581,18 @@ void CLinuxRendererGLES::RenderUpdate(bool clear, DWORD flags, DWORD alpha) { glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - if (m_pYUVShader) - m_pYUVShader->SetAlpha(alpha / 255.0f); + if (m_pYUVProgShader) + m_pYUVProgShader->SetAlpha(alpha / 255.0f); + if (m_pYUVBobShader) + m_pYUVBobShader->SetAlpha(alpha / 255.0f); } else { glDisable(GL_BLEND); - if (m_pYUVShader) - m_pYUVShader->SetAlpha(1.0f); + if (m_pYUVProgShader) + m_pYUVProgShader->SetAlpha(1.0f); + if (m_pYUVBobShader) + m_pYUVBobShader->SetAlpha(1.0f); } if ((flags & RENDER_FLAG_TOP) && (flags & RENDER_FLAG_BOT)) @@ -728,12 +728,7 @@ void CLinuxRendererGLES::LoadShaders(int field) int requestedMethod = CSettings::Get().GetInt("videoplayer.rendermethod"); CLog::Log(LOGDEBUG, "GL: Requested render method: %d", requestedMethod); - if (m_pYUVShader) - { - m_pYUVShader->Free(); - delete m_pYUVShader; - m_pYUVShader = NULL; - } + ReleaseShaders(); switch(requestedMethod) { @@ -786,21 +781,21 @@ void CLinuxRendererGLES::LoadShaders(int field) // Try GLSL shaders if supported and user requested auto or GLSL. if (glCreateProgram) { - // create regular progressive scan shader - m_pYUVShader = new YUV2RGBProgressiveShader(false, m_iFlags, m_format); + // create regular scan shader CLog::Log(LOGNOTICE, "GL: Selecting Single Pass YUV 2 RGB shader"); - if (m_pYUVShader && m_pYUVShader->CompileAndLink()) + m_pYUVProgShader = new YUV2RGBProgressiveShader(false, m_iFlags, m_format); + m_pYUVBobShader = new YUV2RGBBobShader(false, m_iFlags, m_format); + if ((m_pYUVProgShader && m_pYUVProgShader->CompileAndLink()) + && (m_pYUVBobShader && m_pYUVBobShader->CompileAndLink())) { m_renderMethod = RENDER_GLSL; UpdateVideoFilter(); break; } - else if (m_pYUVShader) + else { - m_pYUVShader->Free(); - delete m_pYUVShader; - m_pYUVShader = NULL; + ReleaseShaders(); CLog::Log(LOGERROR, "GL: Error enabling YUV2RGB GLSL shader"); // drop through and try SW } @@ -883,6 +878,22 @@ void CLinuxRendererGLES::LoadShaders(int field) } } +void CLinuxRendererGLES::ReleaseShaders() +{ + if (m_pYUVProgShader) + { + m_pYUVProgShader->Free(); + delete m_pYUVProgShader; + m_pYUVProgShader = NULL; + } + if (m_pYUVBobShader) + { + m_pYUVBobShader->Free(); + delete m_pYUVBobShader; + m_pYUVBobShader = NULL; + } +} + void CLinuxRendererGLES::UnInit() { CLog::Log(LOGDEBUG, "LinuxRendererGL: Cleaning up GL resources"); @@ -1044,7 +1055,8 @@ void CLinuxRendererGLES::RenderSinglePass(int index, int field) { YV12Image &im = m_buffers[index].image; YUVFIELDS &fields = m_buffers[index].fields; - YUVPLANES &planes = fields[field]; + YUVPLANES &planes = fields[FIELD_FULL]; + YUVPLANES &planesf = fields[field]; if (m_reloadShaders) { @@ -1072,26 +1084,32 @@ void CLinuxRendererGLES::RenderSinglePass(int index, int field) glActiveTexture(GL_TEXTURE0); VerifyGLState(); - m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f); - m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f); - m_pYUVShader->SetWidth(im.width); - m_pYUVShader->SetHeight(im.height); + Shaders::BaseYUV2RGBShader *pYUVShader; + if (field != FIELD_FULL) + pYUVShader = m_pYUVBobShader; + else + pYUVShader = m_pYUVProgShader; + + pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f); + pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f); + pYUVShader->SetWidth(im.width); + pYUVShader->SetHeight(im.height); if (field == FIELD_TOP) - m_pYUVShader->SetField(1); + pYUVShader->SetField(1); else if(field == FIELD_BOT) - m_pYUVShader->SetField(0); + pYUVShader->SetField(0); - m_pYUVShader->SetMatrices(glMatrixProject.Get(), glMatrixModview.Get()); - m_pYUVShader->Enable(); + pYUVShader->SetMatrices(glMatrixProject.Get(), glMatrixModview.Get()); + pYUVShader->Enable(); GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip GLfloat m_vert[4][3]; GLfloat m_tex[3][4][2]; - GLint vertLoc = m_pYUVShader->GetVertexLoc(); - GLint Yloc = m_pYUVShader->GetYcoordLoc(); - GLint Uloc = m_pYUVShader->GetUcoordLoc(); - GLint Vloc = m_pYUVShader->GetVcoordLoc(); + GLint vertLoc = pYUVShader->GetVertexLoc(); + GLint Yloc = pYUVShader->GetYcoordLoc(); + GLint Uloc = pYUVShader->GetUcoordLoc(); + GLint Vloc = pYUVShader->GetVcoordLoc(); glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, 0, m_vert); glVertexAttribPointer(Yloc, 2, GL_FLOAT, 0, 0, m_tex[0]); @@ -1114,17 +1132,17 @@ void CLinuxRendererGLES::RenderSinglePass(int index, int field) // Setup texture coordinates for (int i=0; i<3; i++) { - m_tex[i][0][0] = m_tex[i][3][0] = planes[i].rect.x1; - m_tex[i][0][1] = m_tex[i][1][1] = planes[i].rect.y1; - m_tex[i][1][0] = m_tex[i][2][0] = planes[i].rect.x2; - m_tex[i][2][1] = m_tex[i][3][1] = planes[i].rect.y2; + m_tex[i][0][0] = m_tex[i][3][0] = planesf[i].rect.x1; + m_tex[i][0][1] = m_tex[i][1][1] = planesf[i].rect.y1; + m_tex[i][1][0] = m_tex[i][2][0] = planesf[i].rect.x2; + m_tex[i][2][1] = m_tex[i][3][1] = planesf[i].rect.y2; } glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx); VerifyGLState(); - m_pYUVShader->Disable(); + pYUVShader->Disable(); VerifyGLState(); glDisableVertexAttribArray(vertLoc); @@ -1183,7 +1201,7 @@ void CLinuxRendererGLES::RenderMultiPass(int index, int field) VerifyGLState(); // make sure the yuv shader is loaded and ready to go - if (!m_pYUVShader || (!m_pYUVShader->OK())) + if (!m_pYUVProgShader || (!m_pYUVProgShader->OK())) { CLog::Log(LOGERROR, "GL: YUV shader not active, cannot do multipass render"); return; @@ -1192,14 +1210,14 @@ void CLinuxRendererGLES::RenderMultiPass(int index, int field) m_fbo.BeginRender(); VerifyGLState(); - m_pYUVShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f); - m_pYUVShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f); - m_pYUVShader->SetWidth(im.width); - m_pYUVShader->SetHeight(im.height); + m_pYUVProgShader->SetBlack(CMediaSettings::Get().GetCurrentVideoSettings().m_Brightness * 0.01f - 0.5f); + m_pYUVProgShader->SetContrast(CMediaSettings::Get().GetCurrentVideoSettings().m_Contrast * 0.02f); + m_pYUVProgShader->SetWidth(im.width); + m_pYUVProgShader->SetHeight(im.height); if (field == FIELD_TOP) - m_pYUVShader->SetField(1); + m_pYUVProgShader->SetField(1); else if(field == FIELD_BOT) - m_pYUVShader->SetField(0); + m_pYUVProgShader->SetField(0); VerifyGLState(); //TODO @@ -1217,7 +1235,7 @@ void CLinuxRendererGLES::RenderMultiPass(int index, int field) VerifyGLState(); - if (!m_pYUVShader->Enable()) + if (!m_pYUVProgShader->Enable()) { CLog::Log(LOGERROR, "GL: Error enabling YUV shader"); } @@ -1257,7 +1275,7 @@ void CLinuxRendererGLES::RenderMultiPass(int index, int field) // glEnd(); // VerifyGLState(); - m_pYUVShader->Disable(); + m_pYUVProgShader->Disable(); glMatrixModview.PopLoad(); glMatrixProject.PopLoad(); @@ -1905,7 +1923,7 @@ void CLinuxRendererGLES::UploadYV12Texture(int source) } } - bool deinterlacing; + bool deinterlacing = false; if (m_currentField == FIELD_FULL) deinterlacing = false; else @@ -1938,53 +1956,20 @@ void CLinuxRendererGLES::UploadYV12Texture(int source) { glPixelStorei(GL_UNPACK_ALIGNMENT,1); - if (deinterlacing) - { - // Load Even Y Field - LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex - , im->width, im->height >> 1 - , im->stride[0]*2, im->bpp, im->plane[0] ); - - // Load Odd Y fields - LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex - , im->width, im->height >> 1 - , im->stride[0]*2, im->bpp, im->plane[0] + im->stride[0]) ; - - // Load Even U & V Fields - LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE, buf.flipindex - , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) - , im->stride[1]*2, im->bpp, im->plane[1] ); - - LoadPlane( fields[FIELD_TOP][2], GL_ALPHA, buf.flipindex - , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) - , im->stride[2]*2, im->bpp, im->plane[2] ); - - // Load Odd U & V Fields - LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE, buf.flipindex - , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) - , im->stride[1]*2, im->bpp, im->plane[1] + im->stride[1] ); - - LoadPlane( fields[FIELD_BOT][2], GL_ALPHA, buf.flipindex - , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1) - , im->stride[2]*2, im->bpp, im->plane[2] + im->stride[2] ); - } - else - { - // Load Y plane - LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex - , im->width, im->height - , im->stride[0], im->bpp, im->plane[0] ); + // Load Y plane + LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex + , im->width, im->height + , im->stride[0], im->bpp, im->plane[0] ); - //load U plane - LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex - , im->width >> im->cshift_x, im->height >> im->cshift_y - , im->stride[1], im->bpp, im->plane[1] ); + //load U plane + LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE, buf.flipindex + , im->width >> im->cshift_x, im->height >> im->cshift_y + , im->stride[1], im->bpp, im->plane[1] ); - //load V plane - LoadPlane( fields[FIELD_FULL][2], GL_ALPHA, buf.flipindex - , im->width >> im->cshift_x, im->height >> im->cshift_y - , im->stride[2], im->bpp, im->plane[2] ); - } + //load V plane + LoadPlane( fields[FIELD_FULL][2], GL_ALPHA, buf.flipindex + , im->width >> im->cshift_x, im->height >> im->cshift_y + , im->stride[2], im->bpp, im->plane[2] ); } VerifyGLState(); @@ -3015,7 +3000,7 @@ EINTERLACEMETHOD CLinuxRendererGLES::AutoInterlaceMethod() #if !defined(TARGET_ANDROID) && (defined(__i386__) || defined(__x86_64__)) return VS_INTERLACEMETHOD_DEINTERLACE_HALF; #else - return VS_INTERLACEMETHOD_SW_BLEND; + return VS_INTERLACEMETHOD_RENDER_BOB; #endif } diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h index d8bf35dfda..c761d7da5b 100644 --- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h +++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h @@ -181,6 +181,7 @@ protected: int NextYV12Texture(); virtual bool ValidateRenderTarget(); virtual void LoadShaders(int field=FIELD_FULL); + virtual void ReleaseShaders(); void SetTextureFilter(GLenum method); void UpdateVideoFilter(); @@ -313,7 +314,8 @@ protected: , unsigned width, unsigned height , unsigned int stride, int bpp, void* data ); - Shaders::BaseYUV2RGBShader *m_pYUVShader; + Shaders::BaseYUV2RGBShader *m_pYUVProgShader; + Shaders::BaseYUV2RGBShader *m_pYUVBobShader; Shaders::BaseVideoFilterShader *m_pVideoFilterShader; ESCALINGMETHOD m_scalingMethod; ESCALINGMETHOD m_scalingMethodGui; |