diff options
author | Rainer Hochecker <fernetmenta@online.de> | 2017-09-27 08:05:54 +0200 |
---|---|---|
committer | Rainer Hochecker <fernetmenta@online.de> | 2017-10-05 18:06:26 +0200 |
commit | c4c88062582ca87d6df4e48aa4cf79a5adb3301c (patch) | |
tree | a7ff777a56acefc7fe4660a0616dac00c2eb01b6 | |
parent | 0a85f848e7986b4a995375cc66ddeec2987bd8ce (diff) |
VideoPlayer: OpenGL - drop fixed function pipeline
22 files changed, 1317 insertions, 587 deletions
diff --git a/system/shaders/gl_convolution-4x4.glsl b/system/shaders/gl_convolution-4x4.glsl new file mode 100644 index 0000000000..cf2a0f5378 --- /dev/null +++ b/system/shaders/gl_convolution-4x4.glsl @@ -0,0 +1,113 @@ +/* + * Copyright (C) 2010-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +uniform sampler2D img; +uniform vec2 stepxy; +uniform float m_stretch; +varying vec2 m_cord; + +#if (USE1DTEXTURE) + uniform sampler1D kernelTex; +#else + uniform sampler2D kernelTex; +#endif + +//nvidia's half is a 16 bit float and can bring some speed improvements +//without affecting quality +#ifndef __GLSL_CG_DATA_TYPES + #define half float + #define half3 vec3 + #define half4 vec4 +#endif + +half4 weight(float pos) +{ +#if (HAS_FLOAT_TEXTURE) + #if (USE1DTEXTURE) + return texture1D(kernelTex, pos); + #else + return texture2D(kernelTex, vec2(pos, 0.5)); + #endif +#else + #if (USE1DTEXTURE) + return texture1D(kernelTex, pos) * 2.0 - 1.0; + #else + return texture2D(kernelTex, vec2(pos, 0.5)) * 2.0 - 1.0; + #endif +#endif +} + +vec2 stretch(vec2 pos) +{ +#if (XBMC_STRETCH) + // our transform should map [0..1] to itself, with f(0) = 0, f(1) = 1, f(0.5) = 0.5, and f'(0.5) = b. + // a simple curve to do this is g(x) = b(x-0.5) + (1-b)2^(n-1)(x-0.5)^n + 0.5 + // where the power preserves sign. n = 2 is the simplest non-linear case (required when b != 1) + float x = pos.x - 0.5; + return vec2(mix(x * abs(x) * 2.0, x, m_stretch) + 0.5, pos.y); +#else + return pos; +#endif +} + +half3 pixel(float xpos, float ypos) +{ + return texture2D(img, vec2(xpos, ypos)).rgb; +} + +half3 line (float ypos, vec4 xpos, half4 linetaps) +{ + return + pixel(xpos.r, ypos) * linetaps.r + + pixel(xpos.g, ypos) * linetaps.g + + pixel(xpos.b, ypos) * linetaps.b + + pixel(xpos.a, ypos) * linetaps.a; +} + +vec4 process() +{ + vec4 rgb; + vec2 pos = stretch(m_cord) + stepxy * 0.5; + vec2 f = fract(pos / stepxy); + + half4 linetaps = weight(1.0 - f.x); + half4 columntaps = weight(1.0 - f.y); + + //make sure all taps added together is exactly 1.0, otherwise some (very small) distortion can occur + linetaps /= linetaps.r + linetaps.g + linetaps.b + linetaps.a; + columntaps /= columntaps.r + columntaps.g + columntaps.b + columntaps.a; + + vec2 xystart = (-1.5 - f) * stepxy + pos; + vec4 xpos = vec4(xystart.x, xystart.x + stepxy.x, xystart.x + stepxy.x * 2.0, xystart.x + stepxy.x * 3.0); + + rgb.rgb = + line(xystart.y , xpos, linetaps) * columntaps.r + + line(xystart.y + stepxy.y , xpos, linetaps) * columntaps.g + + line(xystart.y + stepxy.y * 2.0, xpos, linetaps) * columntaps.b + + line(xystart.y + stepxy.y * 3.0, xpos, linetaps) * columntaps.a; + +#ifdef GL_ES + rgb.a = m_alpha; +#else + rgb.a = gl_Color.a; +#endif + + return rgb; +} diff --git a/system/shaders/gl_convolution-6x6.glsl b/system/shaders/gl_convolution-6x6.glsl new file mode 100644 index 0000000000..c4f51fd431 --- /dev/null +++ b/system/shaders/gl_convolution-6x6.glsl @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2010-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +uniform sampler2D img; +uniform vec2 stepxy; +uniform float m_stretch; +varying vec2 m_cord; + +#if (USE1DTEXTURE) + uniform sampler1D kernelTex; +#else + uniform sampler2D kernelTex; +#endif + +//nvidia's half is a 16 bit float and can bring some speed improvements +//without affecting quality +#ifndef __GLSL_CG_DATA_TYPES + #define half float + #define half3 vec3 + #define half4 vec4 +#endif + +half3 weight(float pos) +{ +#if (HAS_FLOAT_TEXTURE) + #if (USE1DTEXTURE) + return texture1D(kernelTex, pos).rgb; + #else + return texture2D(kernelTex, vec2(pos, 0.5)).rgb; + #endif +#else + #if (USE1DTEXTURE) + return texture1D(kernelTex, pos).rgb * 2.0 - 1.0; + #else + return texture2D(kernelTex, vec2(pos, 0.5)).rgb * 2.0 - 1.0; + #endif +#endif +} + +vec2 stretch(vec2 pos) +{ +#if (XBMC_STRETCH) + // our transform should map [0..1] to itself, with f(0) = 0, f(1) = 1, f(0.5) = 0.5, and f'(0.5) = b. + // a simple curve to do this is g(x) = b(x-0.5) + (1-b)2^(n-1)(x-0.5)^n + 0.5 + // where the power preserves sign. n = 2 is the simplest non-linear case (required when b != 1) + float x = pos.x - 0.5; + return vec2(mix(x * abs(x) * 2.0, x, m_stretch) + 0.5, pos.y); +#else + return pos; +#endif +} + +half3 pixel(float xpos, float ypos) +{ + return texture2D(img, vec2(xpos, ypos)).rgb; +} + +half3 line (float ypos, vec3 xpos1, vec3 xpos2, half3 linetaps1, half3 linetaps2) +{ + return + pixel(xpos1.r, ypos) * linetaps1.r + + pixel(xpos1.g, ypos) * linetaps2.r + + pixel(xpos1.b, ypos) * linetaps1.g + + pixel(xpos2.r, ypos) * linetaps2.g + + pixel(xpos2.g, ypos) * linetaps1.b + + pixel(xpos2.b, ypos) * linetaps2.b; +} + +vec4 process() +{ + vec4 rgb; + vec2 pos = stretch(m_cord) + stepxy * 0.5; + vec2 f = fract(pos / stepxy); + + half3 linetaps1 = weight((1.0 - f.x) / 2.0); + half3 linetaps2 = weight((1.0 - f.x) / 2.0 + 0.5); + half3 columntaps1 = weight((1.0 - f.y) / 2.0); + half3 columntaps2 = weight((1.0 - f.y) / 2.0 + 0.5); + + //make sure all taps added together is exactly 1.0, otherwise some (very small) distortion can occur + half sum = linetaps1.r + linetaps1.g + linetaps1.b + linetaps2.r + linetaps2.g + linetaps2.b; + linetaps1 /= sum; + linetaps2 /= sum; + sum = columntaps1.r + columntaps1.g + columntaps1.b + columntaps2.r + columntaps2.g + columntaps2.b; + columntaps1 /= sum; + columntaps2 /= sum; + + vec2 xystart = (-2.5 - f) * stepxy + pos; + vec3 xpos1 = vec3(xystart.x, xystart.x + stepxy.x, xystart.x + stepxy.x * 2.0); + vec3 xpos2 = vec3(xystart.x + stepxy.x * 3.0, xystart.x + stepxy.x * 4.0, xystart.x + stepxy.x * 5.0); + + rgb.rgb = + line(xystart.y , xpos1, xpos2, linetaps1, linetaps2) * columntaps1.r + + line(xystart.y + stepxy.y , xpos1, xpos2, linetaps1, linetaps2) * columntaps2.r + + line(xystart.y + stepxy.y * 2.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps1.g + + line(xystart.y + stepxy.y * 3.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps2.g + + line(xystart.y + stepxy.y * 4.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps1.b + + line(xystart.y + stepxy.y * 5.0, xpos1, xpos2, linetaps1, linetaps2) * columntaps2.b; + +#ifdef GL_ES + rgb.a = m_alpha; +#else + rgb.a = gl_Color.a; +#endif + + return rgb; +} diff --git a/system/shaders/gl_output.glsl b/system/shaders/gl_output.glsl new file mode 100644 index 0000000000..d3294a8bb5 --- /dev/null +++ b/system/shaders/gl_output.glsl @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2010-2017 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + + +#if defined(XBMC_DITHER) +uniform sampler2D m_dither; +uniform float m_ditherquant; +uniform vec2 m_dithersize; +#endif +#if defined(KODI_3DLUT) +uniform float m_CLUTsize; +uniform sampler3D m_CLUT; +#endif + +void main() +{ + vec4 rgb = process(); + +#if defined(KODI_3DLUT) + // FIXME: can this be optimized? + rgb = texture3D(m_CLUT, (rgb.rgb*(m_CLUTsize-1.0) + 0.5) / m_CLUTsize); +#endif + +#if defined(XBMC_FULLRANGE) +#if __VERSION__ <= 120 + rgb = (rgb-(16.0/255.0)) * 255.0/219.0; +#else + rgb = clamp((rgb-(16.0/255.0)) * 255.0/219.0, 0, 1); +#endif +#endif + +#if defined(XBMC_DITHER) + vec2 ditherpos = gl_FragCoord.xy / m_dithersize; + // ditherval is multiplied by 65536/(dither_size^2) to make it [0,1[ + // FIXME: scale dither values before uploading? + float ditherval = texture2D(m_dither, ditherpos).r * 16.0; + rgb = floor(rgb * m_ditherquant + ditherval) / m_ditherquant; +#endif + + gl_FragColor = rgb; +} diff --git a/system/shaders/gl_streatch.glsl b/system/shaders/gl_streatch.glsl new file mode 100644 index 0000000000..dc42318d50 --- /dev/null +++ b/system/shaders/gl_streatch.glsl @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2010-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#version 120 + +uniform sampler2D img; +uniform float m_stretch; +varying vec2 m_cord; + +vec2 stretch(vec2 pos) +{ + // our transform should map [0..1] to itself, with f(0) = 0, f(1) = 1, f(0.5) = 0.5, and f'(0.5) = b. + // a simple curve to do this is g(x) = b(x-0.5) + (1-b)2^(n-1)(x-0.5)^n + 0.5 + // where the power preserves sign. n = 2 is the simplest non-linear case (required when b != 1) + float x = pos.x - 0.5; + return vec2(mix(x * abs(x) * 2.0, x, m_stretch) + 0.5, pos.y); +} + +void main() +{ + gl_FragColor.rgb = texture2D(img, stretch(m_cord)).rgb; + gl_FragColor.a = gl_Color.a; +} diff --git a/system/shaders/gl_videofilter_frag.glsl b/system/shaders/gl_videofilter_frag.glsl new file mode 100644 index 0000000000..ff7af3b678 --- /dev/null +++ b/system/shaders/gl_videofilter_frag.glsl @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2010-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#version 120 + +uniform sampler2D img; +varying vec2 m_cord; + +void main() +{ + gl_FragColor.rgb = texture2D(img, m_cord).rgb; + gl_FragColor.a = gl_Color.a; +} diff --git a/system/shaders/gl_videofilter_vertex.glsl b/system/shaders/gl_videofilter_vertex.glsl new file mode 100644 index 0000000000..aa124b5350 --- /dev/null +++ b/system/shaders/gl_videofilter_vertex.glsl @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2010-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#version 120 + +attribute vec4 m_attrpos; +attribute vec2 m_attrcord; +varying vec2 m_cord; +uniform mat4 m_proj; +uniform mat4 m_model; + +void main () +{ + mat4 mvp = m_proj * m_model; + gl_Position = mvp * m_attrpos; + m_cord = m_attrcord; +} diff --git a/system/shaders/gl_yuv2rgb_basic.glsl b/system/shaders/gl_yuv2rgb_basic.glsl new file mode 100644 index 0000000000..268d8c6682 --- /dev/null +++ b/system/shaders/gl_yuv2rgb_basic.glsl @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2010-2013 Team XBMC + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#if(XBMC_texture_rectangle) +# extension GL_ARB_texture_rectangle : enable +# define texture2D texture2DRect +# define sampler2D sampler2DRect +#endif + +uniform sampler2D m_sampY; +uniform sampler2D m_sampU; +uniform sampler2D m_sampV; +varying vec2 m_cordY; +varying vec2 m_cordU; +varying vec2 m_cordV; +uniform vec2 m_step; +uniform mat4 m_yuvmat; +uniform float m_stretch; + +vec2 stretch(vec2 pos) +{ +#if (XBMC_STRETCH) + // our transform should map [0..1] to itself, with f(0) = 0, f(1) = 1, f(0.5) = 0.5, and f'(0.5) = b. + // a simple curve to do this is g(x) = b(x-0.5) + (1-b)2^(n-1)(x-0.5)^n + 0.5 + // where the power preserves sign. n = 2 is the simplest non-linear case (required when b != 1) + #if(XBMC_texture_rectangle) + float x = (pos.x * m_step.x) - 0.5; + return vec2((mix(2.0 * x * abs(x), x, m_stretch) + 0.5) / m_step.x, pos.y); + #else + float x = pos.x - 0.5; + return vec2(mix(2.0 * x * abs(x), x, m_stretch) + 0.5, pos.y); + #endif +#else + return pos; +#endif +} + +vec4 process() +{ + vec4 rgb; +#if defined(XBMC_YV12) || defined(XBMC_NV12) + + vec4 yuv; + yuv.rgba = vec4( texture2D(m_sampY, stretch(m_cordY)).r + , texture2D(m_sampU, stretch(m_cordU)).g + , texture2D(m_sampV, stretch(m_cordV)).a + , 1.0 ); + + rgb = m_yuvmat * yuv; + rgb.a = gl_Color.a; + +#elif defined(XBMC_NV12_RRG) + + vec4 yuv; + yuv.rgba = vec4( texture2D(m_sampY, stretch(m_cordY)).r + , texture2D(m_sampU, stretch(m_cordU)).r + , texture2D(m_sampV, stretch(m_cordV)).g + , 1.0 ); + + rgb = m_yuvmat * yuv; + rgb.a = gl_Color.a; + +#elif defined(XBMC_YUY2) || defined(XBMC_UYVY) + +#if(XBMC_texture_rectangle) + vec2 stepxy = vec2(1.0, 1.0); + vec2 pos = stretch(m_cordY); + pos = vec2(pos.x - 0.25, pos.y); + vec2 f = fract(pos); +#else + vec2 stepxy = m_step; + vec2 pos = stretch(m_cordY); + pos = vec2(pos.x - stepxy.x * 0.25, pos.y); + vec2 f = fract(pos / stepxy); +#endif + + //y axis will be correctly interpolated by opengl + //x axis will not, so we grab two pixels at the center of two columns and interpolate ourselves + vec4 c1 = texture2D(m_sampY, vec2(pos.x + (0.5 - f.x) * stepxy.x, pos.y)); + vec4 c2 = texture2D(m_sampY, vec2(pos.x + (1.5 - f.x) * stepxy.x, pos.y)); + + /* each pixel has two Y subpixels and one UV subpixel + YUV Y YUV + check if we're left or right of the middle Y subpixel and interpolate accordingly*/ +#ifdef XBMC_YUY2 //BGRA = YUYV + float leftY = mix(c1.b, c1.r, f.x * 2.0); + float rightY = mix(c1.r, c2.b, f.x * 2.0 - 1.0); + vec2 outUV = mix(c1.ga, c2.ga, f.x); +#else //BGRA = UYVY + float leftY = mix(c1.g, c1.a, f.x * 2.0); + float rightY = mix(c1.a, c2.g, f.x * 2.0 - 1.0); + vec2 outUV = mix(c1.br, c2.br, f.x); +#endif //XBMC_YUY2 + + float outY = mix(leftY, rightY, step(0.5, f.x)); + + vec4 yuv = vec4(outY, outUV, 1.0); + rgb = m_yuvmat * yuv; + + rgb.a = gl_Color.a; + +#endif + + return rgb; +} diff --git a/system/shaders/yuv2rgb_vertex.glsl b/system/shaders/gl_yuv2rgb_vertex.glsl index 2225040f9c..cdf3c56a71 100644 --- a/system/shaders/yuv2rgb_vertex.glsl +++ b/system/shaders/gl_yuv2rgb_vertex.glsl @@ -18,21 +18,21 @@ * */ +attribute vec4 m_attrpos; +attribute vec2 m_attrcordY; +attribute vec2 m_attrcordU; +attribute vec2 m_attrcordV; varying vec2 m_cordY; varying vec2 m_cordU; varying vec2 m_cordV; +uniform mat4 m_proj; +uniform mat4 m_model; -void main() +void main () { -#if(XBMC_texture_rectangle_hack) - m_cordY = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0 / 2); - m_cordU = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord1 * 2); - m_cordV = vec2(gl_TextureMatrix[2] * gl_MultiTexCoord2); -#else - m_cordY = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0); - m_cordU = vec2(gl_TextureMatrix[1] * gl_MultiTexCoord1); - m_cordV = vec2(gl_TextureMatrix[2] * gl_MultiTexCoord2); -#endif - gl_Position = ftransform(); - gl_FrontColor = gl_Color; + mat4 mvp = m_proj * m_model; + gl_Position = mvp * m_attrpos; + m_cordY = m_attrcordY; + m_cordU = m_attrcordU; + m_cordV = m_attrcordV; } diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp index 632dab8296..0994d7c316 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.cpp @@ -590,7 +590,6 @@ void CBaseRenderer::SettingOptionsRenderMethodsFiller(std::shared_ptr<const CSet #endif #ifdef HAS_GL - list.push_back(make_pair(g_localizeStrings.Get(13417), RENDER_METHOD_ARB)); list.push_back(make_pair(g_localizeStrings.Get(13418), RENDER_METHOD_GLSL)); #endif } diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h index 949092cb51..606fa63619 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/BaseRenderer.h @@ -46,7 +46,6 @@ enum EFIELDSYNC enum RenderMethods { RENDER_METHOD_AUTO = 0, - RENDER_METHOD_ARB, RENDER_METHOD_GLSL, RENDER_METHOD_SOFTWARE, RENDER_METHOD_D3D_PS, diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp index 0c25e9e1a7..6a95b3c5dd 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.cpp @@ -132,8 +132,8 @@ CLinuxRendererGL::CLinuxRendererGL() m_iYV12RenderBuffer = 0; m_currentField = FIELD_FULL; m_reloadShaders = 0; - m_pYUVShader = NULL; - m_pVideoFilterShader = NULL; + m_pYUVShader = nullptr; + m_pVideoFilterShader = nullptr; m_scalingMethod = VS_SCALINGMETHOD_LINEAR; m_scalingMethodGui = (ESCALINGMETHOD)-1; m_useDithering = CServiceBroker::GetSettings().GetBool("videoscreen.dither"); @@ -168,14 +168,13 @@ CLinuxRendererGL::~CLinuxRendererGL() { m_pYUVShader->Free(); delete m_pYUVShader; - m_pYUVShader = NULL; + m_pYUVShader = nullptr; } if (m_pVideoFilterShader) { - m_pVideoFilterShader->Free(); delete m_pVideoFilterShader; - m_pVideoFilterShader = NULL; + m_pVideoFilterShader = nullptr; } } @@ -558,61 +557,140 @@ void CLinuxRendererGL::ClearBackBuffer() //since it only sets pixels to black that aren't going to be overwritten by the video void CLinuxRendererGL::DrawBlackBars() { - glColor4f(m_clearColour, m_clearColour, m_clearColour, 1.0f); glDisable(GL_BLEND); - glBegin(GL_QUADS); + + struct Svertex + { + float x,y,z; + }; + Svertex vertices[24]; + Svertex vertex; + GLubyte count = 0; + + //GLfloat vertex[4][3]; + //GLubyte idx[4] = {0, 1, 3, 2}; //determines order of triangle strip + + g_Windowing.EnableShader(SM_DEFAULT); + GLint posLoc = g_Windowing.ShaderGetPos(); + GLint uniCol = g_Windowing.ShaderGetUniCol(); + + glUniform4f(uniCol, m_clearColour / 255.0f, m_clearColour / 255.0f, m_clearColour / 255.0f, 1.0f); + glVertexAttribPointer(posLoc, 3, GL_FLOAT, GL_FALSE, sizeof(Svertex), (char*)(&vertices[0])); + glEnableVertexAttribArray(posLoc); //top quad if (m_rotatedDestCoords[0].y > 0.0) { - glVertex4f(0.0, 0.0, 0.0, 1.0); - glVertex4f(g_graphicsContext.GetWidth(), 0.0, 0.0, 1.0); - glVertex4f(g_graphicsContext.GetWidth(), m_rotatedDestCoords[0].y, 0.0, 1.0); - glVertex4f(0.0, m_rotatedDestCoords[0].y, 0.0, 1.0); + GLubyte quad = count; + vertices[quad].x = 0.0; + vertices[quad].y = 0.0; + vertices[quad].z = 0; + vertices[quad+1].x = g_graphicsContext.GetWidth(); + vertices[quad+1].y = 0; + vertices[quad+1].z = 0; + vertices[quad+2].x = g_graphicsContext.GetWidth(); + vertices[quad+2].y = m_rotatedDestCoords[0].y; + vertices[quad+2].z = 0; + vertices[quad+3] = vertices[quad+2]; + vertices[quad+4].x = 0; + vertices[quad+4].y = m_rotatedDestCoords[0].y; + vertices[quad+4].z = 0; + vertices[quad+5] = vertices[quad]; + count += 6; } //bottom quad if (m_rotatedDestCoords[2].y < g_graphicsContext.GetHeight()) { - glVertex4f(0.0, m_rotatedDestCoords[2].y, 0.0, 1.0); - glVertex4f(g_graphicsContext.GetWidth(), m_rotatedDestCoords[2].y, 0.0, 1.0); - glVertex4f(g_graphicsContext.GetWidth(), g_graphicsContext.GetHeight(), 0.0, 1.0); - glVertex4f(0.0, g_graphicsContext.GetHeight(), 0.0, 1.0); + GLubyte quad = count; + vertices[quad].x = 0.0; + vertices[quad].y = m_rotatedDestCoords[2].y; + vertices[quad].z = 0; + vertices[quad+1].x = g_graphicsContext.GetWidth(); + vertices[quad+1].y = m_rotatedDestCoords[2].y; + vertices[quad+1].z = 0; + vertices[quad+2].x = g_graphicsContext.GetWidth(); + vertices[quad+2].y = g_graphicsContext.GetHeight(); + vertices[quad+2].z = 0; + vertices[quad+3] = vertices[quad+2]; + vertices[quad+4].x = 0; + vertices[quad+4].y = g_graphicsContext.GetHeight(); + vertices[quad+4].z = 0; + vertices[quad+5] = vertices[quad]; + count += 6; } //left quad if (m_rotatedDestCoords[0].x > 0.0) { - glVertex4f(0.0, m_rotatedDestCoords[0].y, 0.0, 1.0); - glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0.0, 1.0); - glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[2].y, 0.0, 1.0); - glVertex4f(0.0, m_rotatedDestCoords[2].y, 0.0, 1.0); + GLubyte quad = count; + vertices[quad].x = 0.0; + vertices[quad].y = m_rotatedDestCoords[0].y; + vertices[quad].z = 0; + vertices[quad+1].x = m_rotatedDestCoords[0].x; + vertices[quad+1].y = m_rotatedDestCoords[0].y; + vertices[quad+1].z = 0; + vertices[quad+2].x = m_rotatedDestCoords[3].x; + vertices[quad+2].y = m_rotatedDestCoords[3].y; + vertices[quad+2].z = 0; + vertices[quad+3] = vertices[quad+2]; + vertices[quad+4].x = 0; + vertices[quad+4].y = m_rotatedDestCoords[3].y; + vertices[quad+4].z = 0; + vertices[quad+5] = vertices[quad]; + count += 6; } //right quad if (m_rotatedDestCoords[2].x < g_graphicsContext.GetWidth()) { - glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[0].y, 0.0, 1.0); - glVertex4f(g_graphicsContext.GetWidth(), m_rotatedDestCoords[0].y, 0.0, 1.0); - glVertex4f(g_graphicsContext.GetWidth(), m_rotatedDestCoords[2].y, 0.0, 1.0); - glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 0.0, 1.0); - } - - glEnd(); + GLubyte quad = count; + vertices[quad].x = m_rotatedDestCoords[1].x; + vertices[quad].y = m_rotatedDestCoords[1].y; + vertices[quad].z = 0; + vertices[quad+1].x = g_graphicsContext.GetWidth(); + vertices[quad+1].y = m_rotatedDestCoords[1].y; + vertices[quad+1].z = 0; + vertices[quad+2].x = g_graphicsContext.GetWidth(); + vertices[quad+2].y = m_rotatedDestCoords[2].y; + vertices[quad+2].z = 0; + vertices[quad+3] = vertices[quad+2]; + vertices[quad+4].x = m_rotatedDestCoords[1].x; + vertices[quad+4].y = m_rotatedDestCoords[2].y; + vertices[quad+4].z = 0; + vertices[quad+5] = vertices[quad]; + count += 6; + } + + glDrawArrays(GL_TRIANGLES, 0, count); + glDisableVertexAttribArray(posLoc); + + g_Windowing.DisableShader(); } void CLinuxRendererGL::UpdateVideoFilter() { - bool pixelRatioChanged = (CDisplaySettings::GetInstance().GetPixelRatio() > 1.001f || CDisplaySettings::GetInstance().GetPixelRatio() < 0.999f) != - (m_pixelRatio > 1.001f || m_pixelRatio < 0.999f); + if (!m_pVideoFilterShader) + { + m_pVideoFilterShader = new DefaultFilterShader(); + if (!m_pVideoFilterShader->CompileAndLink()) + { + CLog::Log(LOGERROR, "CLinuxRendererGL::UpdateVideoFilter: Error compiling and linking video filter shader"); + return; + } + } + + bool pixelRatioChanged = (CDisplaySettings::GetInstance().GetPixelRatio() > 1.001f || + CDisplaySettings::GetInstance().GetPixelRatio() < 0.999f) != + (m_pixelRatio > 1.001f || m_pixelRatio < 0.999f); bool nonLinStretchChanged = false; - bool cmsChanged = (m_cmsOn != m_ColorManager->IsEnabled()) - || (m_cmsOn && !m_ColorManager->CheckConfiguration(m_cmsToken, m_iFlags)); + bool cmsChanged = (m_cmsOn != m_ColorManager->IsEnabled()) || + (m_cmsOn && !m_ColorManager->CheckConfiguration(m_cmsToken, m_iFlags)); if (m_nonLinStretchGui != CDisplaySettings::GetInstance().IsNonLinearStretched() || pixelRatioChanged) { - m_nonLinStretchGui = CDisplaySettings::GetInstance().IsNonLinearStretched(); - m_pixelRatio = CDisplaySettings::GetInstance().GetPixelRatio(); - m_reloadShaders = 1; + m_nonLinStretchGui = CDisplaySettings::GetInstance().IsNonLinearStretched(); + m_pixelRatio = CDisplaySettings::GetInstance().GetPixelRatio(); + m_reloadShaders = 1; nonLinStretchChanged = true; if (m_nonLinStretchGui && (m_pixelRatio < 0.999f || m_pixelRatio > 1.001f) && Supports(RENDERFEATURE_NONLINSTRETCH)) @@ -655,9 +733,9 @@ void CLinuxRendererGL::UpdateVideoFilter() } m_scalingMethodGui = CMediaSettings::GetInstance().GetCurrentVideoSettings().m_ScalingMethod; - m_scalingMethod = m_scalingMethodGui; + m_scalingMethod = m_scalingMethodGui; - if(!Supports(m_scalingMethod)) + if (!Supports(m_scalingMethod)) { CLog::Log(LOGWARNING, "CLinuxRendererGL::UpdateVideoFilter - chosen scaling method %d, is not supported by renderer", (int)m_scalingMethod); m_scalingMethod = VS_SCALINGMETHOD_LINEAR; @@ -665,9 +743,8 @@ void CLinuxRendererGL::UpdateVideoFilter() if (m_pVideoFilterShader) { - m_pVideoFilterShader->Free(); delete m_pVideoFilterShader; - m_pVideoFilterShader = NULL; + m_pVideoFilterShader = nullptr; } m_fbo.fbo.Cleanup(); @@ -765,12 +842,17 @@ void CLinuxRendererGL::UpdateVideoFilter() CLog::Log(LOGERROR, "GL: Falling back to bilinear due to failure to init scaler"); if (m_pVideoFilterShader) { - m_pVideoFilterShader->Free(); delete m_pVideoFilterShader; - m_pVideoFilterShader = NULL; + m_pVideoFilterShader = nullptr; } m_fbo.fbo.Cleanup(); + m_pVideoFilterShader = new DefaultFilterShader(); + if (!m_pVideoFilterShader->CompileAndLink()) + { + CLog::Log(LOGERROR, "CLinuxRendererGL::UpdateVideoFilter: Error compiling and linking defauilt video filter shader"); + } + SetTextureFilter(GL_LINEAR); m_renderQuality = RQ_SINGLEPASS; } @@ -791,89 +873,33 @@ void CLinuxRendererGL::LoadShaders(int field) m_pYUVShader = NULL; } - bool tryGlsl = true; - switch(requestedMethod) + // create regular progressive scan shader + // if single pass, create GLSLOutput helper and pass it to YUV2RGB shader + GLSLOutput *out = nullptr; + if (m_renderQuality == RQ_SINGLEPASS) { - case RENDER_METHOD_AUTO: -#if defined(TARGET_POSIX) && !defined(TARGET_DARWIN) - //with render method set to auto, don't try glsl on ati if we're on linux - //it seems to be broken in a random way with every new driver release - tryGlsl = !StringUtils::StartsWithNoCase(g_Windowing.GetRenderVendor(), "ati"); -#endif - - case RENDER_METHOD_GLSL: - // Try GLSL shaders if supported and user requested auto or GLSL. - if (tryGlsl) - { - // create regular progressive scan shader - // if single pass, create GLSLOutput helper and pass it to YUV2RGB shader - GLSLOutput *out = nullptr; - if (m_renderQuality == RQ_SINGLEPASS) - { - out = new GLSLOutput(3, m_useDithering, m_ditherDepth, - m_cmsOn ? m_fullRange : false, - m_cmsOn ? m_tCLUTTex : 0, - m_CLUTsize); - } - EShaderFormat shaderFormat = GetShaderFormat(); - m_pYUVShader = new YUV2RGBProgressiveShader(m_textureTarget==GL_TEXTURE_RECTANGLE_ARB, m_iFlags, shaderFormat, - m_nonLinStretch && m_renderQuality == RQ_SINGLEPASS, - out); - if (!m_cmsOn) - m_pYUVShader->SetConvertFullColorRange(m_fullRange); - - CLog::Log(LOGNOTICE, "GL: Selecting Single Pass YUV 2 RGB shader"); - - if (m_pYUVShader && m_pYUVShader->CompileAndLink()) - { - m_renderMethod = RENDER_GLSL; - UpdateVideoFilter(); - break; - } - else if (m_pYUVShader) - { - m_pYUVShader->Free(); - delete m_pYUVShader; - m_pYUVShader = NULL; - } - CLog::Log(LOGERROR, "GL: Error enabling YUV2RGB GLSL shader"); - // drop through and try ARB - } - case RENDER_METHOD_ARB: - // Try ARB shaders if supported and user requested it or GLSL shaders failed. - if (g_Windowing.IsExtSupported("GL_ARB_fragment_program")) - { - CLog::Log(LOGNOTICE, "GL: ARB shaders support detected"); - m_renderMethod = RENDER_ARB ; + out = new GLSLOutput(3, m_useDithering, m_ditherDepth, + m_cmsOn ? m_fullRange : false, + m_cmsOn ? m_tCLUTTex : 0, + m_CLUTsize); + } + EShaderFormat shaderFormat = GetShaderFormat(); + m_pYUVShader = new YUV2RGBProgressiveShader(m_textureTarget==GL_TEXTURE_RECTANGLE_ARB, m_iFlags, shaderFormat, + m_nonLinStretch && m_renderQuality == RQ_SINGLEPASS, + out); + if (!m_cmsOn) + m_pYUVShader->SetConvertFullColorRange(m_fullRange); - // create regular progressive scan shader - EShaderFormat shaderFormat = GetShaderFormat(); - m_pYUVShader = new YUV2RGBProgressiveShaderARB(m_textureTarget==GL_TEXTURE_RECTANGLE_ARB, m_iFlags, shaderFormat); - m_pYUVShader->SetConvertFullColorRange(m_fullRange); - CLog::Log(LOGNOTICE, "GL: Selecting Single Pass ARB YUV2RGB shader"); + CLog::Log(LOGNOTICE, "GL: Selecting Single Pass YUV 2 RGB shader"); - if (m_pYUVShader && m_pYUVShader->CompileAndLink()) - { - m_renderMethod = RENDER_ARB; - UpdateVideoFilter(); - break; - } - else if (m_pYUVShader) - { - m_pYUVShader->Free(); - delete m_pYUVShader; - m_pYUVShader = NULL; - } - CLog::Log(LOGERROR, "GL: Error enabling YUV2RGB ARB shader"); - m_renderMethod = -1; - break; - } - default: - { - m_renderMethod = -1; - CLog::Log(LOGERROR, "GL: Shaders support not present"); - break; - } + if (m_pYUVShader && m_pYUVShader->CompileAndLink()) + { + m_renderMethod = RENDER_GLSL; + UpdateVideoFilter(); + } + else + { + CLog::Log(LOGERROR, "GL: Error enabling YUV2RGB GLSL shader"); } } @@ -961,14 +987,9 @@ bool CLinuxRendererGL::Render(DWORD flags, int renderBuffer) break; } } - else if (m_renderMethod & RENDER_ARB) - { - RenderSinglePass(renderBuffer, m_currentField); - } else { - RenderSoftware(renderBuffer, m_currentField); - VerifyGLState(); + return false; } AfterRenderHook(renderBuffer); @@ -1016,51 +1037,80 @@ void CLinuxRendererGL::RenderSinglePass(int index, int field) else m_pYUVShader->SetNonLinStretch(pow(CDisplaySettings::GetInstance().GetPixelRatio(), g_advancedSettings.m_videoNonLinStretchRatio)); - if (field == FIELD_TOP) + if (field == FIELD_TOP) m_pYUVShader->SetField(1); else if(field == FIELD_BOT) m_pYUVShader->SetField(0); + m_pYUVShader->SetMatrices(glMatrixProject.Get(), glMatrixModview.Get()); m_pYUVShader->Enable(); - glBegin(GL_QUADS); + GLubyte idx[4] = {0, 1, 3, 2}; //determines order of the vertices + GLfloat vertex[4][3]; + GLfloat texture[3][4][2]; + + GLint vertLoc = m_pYUVShader->GetVertexLoc(); + GLint Yloc = m_pYUVShader->GetYcoordLoc(); + GLint Uloc = m_pYUVShader->GetUcoordLoc(); + GLint Vloc = m_pYUVShader->GetVcoordLoc(); + + glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, 0, vertex); + glVertexAttribPointer(Yloc, 2, GL_FLOAT, 0, 0, texture[0]); + glVertexAttribPointer(Uloc, 2, GL_FLOAT, 0, 0, texture[1]); + glVertexAttribPointer(Vloc, 2, GL_FLOAT, 0, 0, texture[2]); + + glEnableVertexAttribArray(vertLoc); + glEnableVertexAttribArray(Yloc); + glEnableVertexAttribArray(Uloc); + glEnableVertexAttribArray(Vloc); - glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y1); - glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y1); - glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y1); - glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0, 1.0f );//top left + // Setup vertex position values + for(int i = 0; i < 4; i++) + { + vertex[i][0] = m_rotatedDestCoords[i].x; + vertex[i][1] = m_rotatedDestCoords[i].y; + vertex[i][2] = 0.0f;// set z to 0 + } - 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); - glVertex4f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y, 0, 1.0f );//top right + // Setup texture coordinates + for (int i=0; i<3; i++) + { + // bottom left + texture[i][0][0] = planes[i].rect.x1; + texture[i][0][1] = planes[i].rect.y1; - 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); - glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 0, 1.0f );//bottom right + // bottom right + texture[i][1][0] = planes[i].rect.x2; + texture[i][1][1] = planes[i].rect.y1; - 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); - glVertex4f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y, 0, 1.0f );//bottom left + // top right + texture[i][2][0] = planes[i].rect.x2; + texture[i][2][1] = planes[i].rect.y2; - glEnd(); + // top left + texture[i][3][0] = planes[i].rect.x1; + texture[i][3][1] = planes[i].rect.y2; + } + + glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx); VerifyGLState(); m_pYUVShader->Disable(); VerifyGLState(); - glActiveTextureARB(GL_TEXTURE1); - glDisable(m_textureTarget); + glDisableVertexAttribArray(vertLoc); + glDisableVertexAttribArray(Yloc); + glDisableVertexAttribArray(Uloc); + glDisableVertexAttribArray(Vloc); - glActiveTextureARB(GL_TEXTURE2); + glActiveTexture(GL_TEXTURE1); glDisable(m_textureTarget); - glActiveTextureARB(GL_TEXTURE0); + glActiveTexture(GL_TEXTURE2); glDisable(m_textureTarget); - glMatrixMode(GL_MODELVIEW); + glActiveTexture(GL_TEXTURE0); + glDisable(m_textureTarget); VerifyGLState(); } @@ -1128,9 +1178,10 @@ void CLinuxRendererGL::RenderToFBO(int index, int field, bool weave /*= false*/) m_pYUVShader->SetWidth(planes[0].texwidth); m_pYUVShader->SetHeight(planes[0].texheight); m_pYUVShader->SetNonLinStretch(1.0); - if (field == FIELD_TOP) + + if (field == FIELD_TOP) m_pYUVShader->SetField(1); - else if(field == FIELD_BOT) + else if (field == FIELD_BOT) m_pYUVShader->SetField(0); VerifyGLState(); @@ -1150,13 +1201,15 @@ void CLinuxRendererGL::RenderToFBO(int index, int field, bool weave /*= false*/) glViewport(0, 0, m_sourceWidth, m_sourceHeight); glScissor (0, 0, m_sourceWidth, m_sourceHeight); + m_pYUVShader->SetMatrices(glMatrixProject.Get(), glMatrixModview.Get()); if (!m_pYUVShader->Enable()) { CLog::Log(LOGERROR, "GL: Error enabling YUV shader"); } - m_fbo.width = planes[0].rect.x2 - planes[0].rect.x1; + 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) { m_fbo.width *= planes[0].texwidth; @@ -1168,29 +1221,63 @@ void CLinuxRendererGL::RenderToFBO(int index, int field, bool weave /*= false*/) m_fbo.height *= 2; // 1st Pass to video frame size - glBegin(GL_QUADS); + GLubyte idx[4] = {0, 1, 3, 2}; //determines order of the vertices + GLfloat vertex[4][3]; + GLfloat texture[3][4][2]; + + GLint vertLoc = m_pYUVShader->GetVertexLoc(); + GLint Yloc = m_pYUVShader->GetYcoordLoc(); + GLint Uloc = m_pYUVShader->GetUcoordLoc(); + GLint Vloc = m_pYUVShader->GetVcoordLoc(); + + glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, 0, vertex); + glVertexAttribPointer(Yloc, 2, GL_FLOAT, 0, 0, texture[0]); + glVertexAttribPointer(Uloc, 2, GL_FLOAT, 0, 0, texture[1]); + glVertexAttribPointer(Vloc, 2, GL_FLOAT, 0, 0, texture[2]); + + glEnableVertexAttribArray(vertLoc); + glEnableVertexAttribArray(Yloc); + glEnableVertexAttribArray(Uloc); + glEnableVertexAttribArray(Vloc); + + // Setup vertex position values + vertex[0][0] = 0.0f; + vertex[0][1] = 0.0f; + vertex[0][2] = 0.0f; + + vertex[1][0] = m_fbo.width; + vertex[1][1] = 0.0f; + vertex[1][2] = 0.0f; - glMultiTexCoord2fARB(GL_TEXTURE0, planes[0].rect.x1, planes[0].rect.y1); - glMultiTexCoord2fARB(GL_TEXTURE1, planes[1].rect.x1, planes[1].rect.y1); - glMultiTexCoord2fARB(GL_TEXTURE2, planes[2].rect.x1, planes[2].rect.y1); - glVertex2f(0.0f , 0.0f); + vertex[2][0] = m_fbo.width; + vertex[2][1] = m_fbo.height; + vertex[2][2] = 0.0f; - 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(m_fbo.width, 0.0f); + vertex[3][0] = 0.0f; + vertex[3][1] = m_fbo.height; + vertex[3][2] = 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(m_fbo.width, m_fbo.height); + // Setup texture coordinates + for (int i=0; i<3; i++) + { + // top left + texture[i][0][0] = planes[i].rect.x1; + texture[i][0][1] = planes[i].rect.y1; + + // top right + texture[i][1][0] = planes[i].rect.x2; + texture[i][1][1] = planes[i].rect.y1; - 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 , m_fbo.height); + // bottom right + texture[i][2][0] = planes[i].rect.x2; + texture[i][2][1] = planes[i].rect.y2; + + // bottom left + texture[i][3][0] = planes[i].rect.x1; + texture[i][3][1] = planes[i].rect.y2; + } - glEnd(); + glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx); VerifyGLState(); m_pYUVShader->Disable(); @@ -1219,57 +1306,78 @@ void CLinuxRendererGL::RenderFromFBO() VerifyGLState(); // Use regular normalized texture coordinates - // 2nd Pass to screen size with optional video filter - if (m_pVideoFilterShader) + if (!m_pVideoFilterShader) { - GLint filter; - if (!m_pVideoFilterShader->GetTextureFilter(filter)) - filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; + CLog::Log(LOGERROR, "CLinuxRendererGL::RenderFromFBO - no videofilter shader"); + return; + } - m_fbo.fbo.SetFiltering(GL_TEXTURE_2D, filter); - m_pVideoFilterShader->SetSourceTexture(0); - m_pVideoFilterShader->SetWidth(m_sourceWidth); - m_pVideoFilterShader->SetHeight(m_sourceHeight); + GLint filter; + if (!m_pVideoFilterShader->GetTextureFilter(filter)) + filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; - //disable non-linear stretch when a dvd menu is shown, parts of the menu are rendered through the overlay renderer - //having non-linear stretch on breaks the alignment - if (g_application.m_pPlayer->IsInMenu()) - m_pVideoFilterShader->SetNonLinStretch(1.0); - else - m_pVideoFilterShader->SetNonLinStretch(pow(CDisplaySettings::GetInstance().GetPixelRatio(), g_advancedSettings.m_videoNonLinStretchRatio)); + m_fbo.fbo.SetFiltering(GL_TEXTURE_2D, filter); + m_pVideoFilterShader->SetSourceTexture(0); + m_pVideoFilterShader->SetWidth(m_sourceWidth); + m_pVideoFilterShader->SetHeight(m_sourceHeight); - m_pVideoFilterShader->Enable(); - } + //disable non-linear stretch when a dvd menu is shown, parts of the menu are rendered through the overlay renderer + //having non-linear stretch on breaks the alignment + if (g_application.m_pPlayer->IsInMenu()) + m_pVideoFilterShader->SetNonLinStretch(1.0); else - { - GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; - m_fbo.fbo.SetFiltering(GL_TEXTURE_2D, filter); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - } + m_pVideoFilterShader->SetNonLinStretch(pow(CDisplaySettings::GetInstance().GetPixelRatio(), g_advancedSettings.m_videoNonLinStretchRatio)); + + m_pVideoFilterShader->SetMatrices(glMatrixProject.Get(), glMatrixModview.Get()); + m_pVideoFilterShader->Enable(); VerifyGLState(); float imgwidth = m_fbo.width / m_sourceWidth; float imgheight = m_fbo.height / m_sourceHeight; - glBegin(GL_QUADS); + GLubyte idx[4] = {0, 1, 3, 2}; //determines order of the vertices + GLfloat vertex[4][3]; + GLfloat texture[4][2]; - glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f, 0.0f); - glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0, 1.0f ); + GLint vertLoc = m_pVideoFilterShader->GetVertexLoc(); + GLint loc = m_pVideoFilterShader->GetCoordLoc(); - glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, 0.0f); - glVertex4f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y, 0, 1.0f ); + glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, 0, vertex); + glVertexAttribPointer(loc, 2, GL_FLOAT, 0, 0, texture); - glMultiTexCoord2fARB(GL_TEXTURE0, imgwidth, imgheight); - glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 0, 1.0f ); - - glMultiTexCoord2fARB(GL_TEXTURE0, 0.0f, imgheight); - glVertex4f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y, 0, 1.0f ); + glEnableVertexAttribArray(vertLoc); + glEnableVertexAttribArray(loc); + + // Setup vertex position values + vertex[0][0] = m_rotatedDestCoords[0].x; + vertex[0][1] = m_rotatedDestCoords[0].y; + vertex[0][2] = 0.0f; + + vertex[1][0] = m_rotatedDestCoords[1].x; + vertex[1][1] = m_rotatedDestCoords[1].y; + vertex[1][2] = 0.0f; + + vertex[2][0] = m_rotatedDestCoords[2].x; + vertex[2][1] = m_rotatedDestCoords[2].y; + vertex[2][2] = 0.0f; - glEnd(); + vertex[3][0] = m_rotatedDestCoords[3].x; + vertex[3][1] = m_rotatedDestCoords[3].y; + vertex[3][2] = 0.0f; + texture[0][0] = 0.0f; + texture[0][1] = 0.0f; + texture[1][0] = imgwidth; + texture[1][1] = 0.0f; + texture[2][0] = imgwidth; + texture[2][1] = imgheight; + texture[3][0] = 0.0f; + texture[3][1] = imgheight; + + glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx); VerifyGLState(); if (m_pVideoFilterShader) @@ -1320,97 +1428,78 @@ void CLinuxRendererGL::RenderRGB(int index, int field) // make sure we know the correct texture size GetPlaneTextureSize(plane); - // Try some clamping or wrapping - glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - - if (m_pVideoFilterShader) - { - GLint filter; - if (!m_pVideoFilterShader->GetTextureFilter(filter)) - filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; - - glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter); - glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter); - m_pVideoFilterShader->SetSourceTexture(0); - m_pVideoFilterShader->SetWidth(m_sourceWidth); - m_pVideoFilterShader->SetHeight(m_sourceHeight); - - //disable non-linear stretch when a dvd menu is shown, parts of the menu are rendered through the overlay renderer - //having non-linear stretch on breaks the alignment - if (g_application.m_pPlayer->IsInMenu()) - m_pVideoFilterShader->SetNonLinStretch(1.0); - else - m_pVideoFilterShader->SetNonLinStretch(pow(CDisplaySettings::GetInstance().GetPixelRatio(), g_advancedSettings.m_videoNonLinStretchRatio)); - - m_pVideoFilterShader->Enable(); - } - else + if (!m_pVideoFilterShader) { - GLint filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; - glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter); - glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter); + CLog::Log(LOGERROR, "CLinuxRendererGL::RenderRGB - no videofilter shader"); + return; } - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - VerifyGLState(); + GLint filter; + if (!m_pVideoFilterShader->GetTextureFilter(filter)) + filter = m_scalingMethod == VS_SCALINGMETHOD_NEAREST ? GL_NEAREST : GL_LINEAR; - glBegin(GL_QUADS); - if (m_textureTarget==GL_TEXTURE_2D) - { - glTexCoord2f(plane.rect.x1, plane.rect.y1); glVertex2f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y); - glTexCoord2f(plane.rect.x2, plane.rect.y1); glVertex2f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y); - glTexCoord2f(plane.rect.x2, plane.rect.y2); glVertex2f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y); - glTexCoord2f(plane.rect.x1, plane.rect.y2); glVertex2f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y); - } + glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, filter); + glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, filter); + m_pVideoFilterShader->SetSourceTexture(0); + m_pVideoFilterShader->SetWidth(m_sourceWidth); + m_pVideoFilterShader->SetHeight(m_sourceHeight); + + //disable non-linear stretch when a dvd menu is shown, parts of the menu are rendered through the overlay renderer + //having non-linear stretch on breaks the alignment + if (g_application.m_pPlayer->IsInMenu()) + m_pVideoFilterShader->SetNonLinStretch(1.0); else - { - glTexCoord2f(plane.rect.x1, plane.rect.y1); glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0.0f, 0.0f); - glTexCoord2f(plane.rect.x2, plane.rect.y1); glVertex4f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y, 1.0f, 0.0f); - glTexCoord2f(plane.rect.x2, plane.rect.y2); glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 1.0f, 1.0f); - glTexCoord2f(plane.rect.x1, plane.rect.y2); glVertex4f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y, 0.0f, 1.0f); - } - glEnd(); - VerifyGLState(); + m_pVideoFilterShader->SetNonLinStretch(pow(CDisplaySettings::GetInstance().GetPixelRatio(), g_advancedSettings.m_videoNonLinStretchRatio)); - if (m_pVideoFilterShader) - m_pVideoFilterShader->Disable(); + m_pVideoFilterShader->SetMatrices(glMatrixProject.Get(), glMatrixModview.Get()); + m_pVideoFilterShader->Enable(); - glBindTexture (m_textureTarget, 0); - glDisable(m_textureTarget); -} + GLubyte idx[4] = {0, 1, 3, 2}; //determines order of the vertices + GLfloat vertex[4][3]; + GLfloat texture[4][2]; -void CLinuxRendererGL::RenderSoftware(int index, int field) -{ - // used for textures uploaded from rgba or CVPixelBuffers. - YUVPLANE (&planes)[YuvImage::MAX_PLANES] = m_buffers[index].fields[field]; + GLint vertLoc = m_pVideoFilterShader->GetVertexLoc(); + GLint loc = m_pVideoFilterShader->GetCoordLoc(); - glDisable(GL_DEPTH_TEST); + glVertexAttribPointer(vertLoc, 3, GL_FLOAT, 0, 0, vertex); + glVertexAttribPointer(loc, 2, GL_FLOAT, 0, 0, texture); - glEnable(m_textureTarget); - glActiveTextureARB(GL_TEXTURE0); - glBindTexture(m_textureTarget, planes[0].id); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glEnableVertexAttribArray(vertLoc); + glEnableVertexAttribArray(loc); - glBegin(GL_QUADS); - glTexCoord2f(planes[0].rect.x1, planes[0].rect.y1); - glVertex4f(m_rotatedDestCoords[0].x, m_rotatedDestCoords[0].y, 0, 1.0f ); + // Setup vertex position values + vertex[0][0] = m_rotatedDestCoords[0].x; + vertex[0][1] = m_rotatedDestCoords[0].y; + vertex[0][2] = 0.0f; - glTexCoord2f(planes[0].rect.x2, planes[0].rect.y1); - glVertex4f(m_rotatedDestCoords[1].x, m_rotatedDestCoords[1].y, 0, 1.0f); + vertex[1][0] = m_rotatedDestCoords[1].x; + vertex[1][1] = m_rotatedDestCoords[1].y; + vertex[1][2] = 0.0f; - glTexCoord2f(planes[0].rect.x2, planes[0].rect.y2); - glVertex4f(m_rotatedDestCoords[2].x, m_rotatedDestCoords[2].y, 0, 1.0f); + vertex[2][0] = m_rotatedDestCoords[2].x; + vertex[2][1] = m_rotatedDestCoords[2].y; + vertex[2][2] = 0.0f; - glTexCoord2f(planes[0].rect.x1, planes[0].rect.y2); - glVertex4f(m_rotatedDestCoords[3].x, m_rotatedDestCoords[3].y, 0, 1.0f); + vertex[3][0] = m_rotatedDestCoords[3].x; + vertex[3][1] = m_rotatedDestCoords[3].y; + vertex[3][2] = 0.0f; - glEnd(); + texture[0][0] = plane.rect.x1; + texture[0][1] = plane.rect.y1; + texture[1][0] = plane.rect.x2; + texture[1][1] = plane.rect.y1; + texture[2][0] = plane.rect.x2; + texture[2][1] = plane.rect.y2; + texture[3][0] = plane.rect.x1; + texture[3][1] = plane.rect.y2; + glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_BYTE, idx); VerifyGLState(); + m_pVideoFilterShader->Disable(); + + glBindTexture(m_textureTarget, 0); glDisable(m_textureTarget); - VerifyGLState(); } bool CLinuxRendererGL::RenderCapture(CRenderCapture* capture) @@ -2366,16 +2455,16 @@ bool CLinuxRendererGL::Supports(ESCALINGMETHOD method) m_format != AV_PIX_FMT_UYVY422) return true; - if(method == VS_SCALINGMETHOD_LINEAR - || method == VS_SCALINGMETHOD_AUTO) + if (method == VS_SCALINGMETHOD_LINEAR || + method == VS_SCALINGMETHOD_AUTO) return true; - if(method == VS_SCALINGMETHOD_CUBIC - || method == VS_SCALINGMETHOD_LANCZOS2 - || method == VS_SCALINGMETHOD_SPLINE36_FAST - || method == VS_SCALINGMETHOD_LANCZOS3_FAST - || method == VS_SCALINGMETHOD_SPLINE36 - || method == VS_SCALINGMETHOD_LANCZOS3) + if (method == VS_SCALINGMETHOD_CUBIC || + method == VS_SCALINGMETHOD_LANCZOS2 || + method == VS_SCALINGMETHOD_SPLINE36_FAST || + method == VS_SCALINGMETHOD_LANCZOS3_FAST || + method == VS_SCALINGMETHOD_SPLINE36 || + method == VS_SCALINGMETHOD_LANCZOS3) { // if scaling is below level, avoid hq scaling float scaleX = fabs(((float)m_sourceWidth - m_destRect.Width())/m_sourceWidth)*100; diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h index 8a6a0684d6..2de14acfb7 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/LinuxRendererGL.h @@ -40,7 +40,7 @@ class CRenderCapture; class CBaseTexture; -namespace Shaders { class BaseYUV2RGBShader; } +namespace Shaders { class BaseYUV2RGBGLSLShader; } namespace Shaders { class BaseVideoFilterShader; } struct DRAWRECT @@ -158,7 +158,6 @@ protected: void RenderToFBO(int renderBuffer, int field, bool weave = false); 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 RenderRGB(int renderBuffer, int field); // render using vdpau/vaapi hardware void RenderProgressiveWeave(int renderBuffer, int field); // render using vdpau hardware @@ -227,7 +226,7 @@ protected: void GetPlaneTextureSize(YUVPLANE& plane); - Shaders::BaseYUV2RGBShader *m_pYUVShader; + Shaders::BaseYUV2RGBGLSLShader *m_pYUVShader; Shaders::BaseVideoFilterShader *m_pVideoFilterShader; ESCALINGMETHOD m_scalingMethod; ESCALINGMETHOD m_scalingMethodGui; diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/CMakeLists.txt b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/CMakeLists.txt index 49616e9751..ab6b1bc0dc 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/CMakeLists.txt +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/CMakeLists.txt @@ -27,10 +27,10 @@ if(OPENGLES_FOUND AND (CORE_PLATFORM_NAME_LC STREQUAL android OR CORE_PLATFORM_NAME_LC STREQUAL imx OR CORE_PLATFORM_NAME_LC STREQUAL mir OR CORE_PLATFORM_NAME_LC STREQUAL wayland)) - list(APPEND SOURCES GLSLOutput.cpp + list(APPEND SOURCES GLSLOutputGLES.cpp VideoFilterShaderGLES.cpp YUV2RGBShaderGLES.cpp) - list(APPEND HEADERS GLSLOutput.h + list(APPEND HEADERS GLSLOutputGLES.h VideoFilterShaderGLES.h YUV2RGBShaderGLES.h) endif() diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp index c01bf30d6e..3718bc8fe3 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutput.cpp @@ -62,10 +62,8 @@ std::string GLSLOutput::GetDefines() defines += "#define XBMC_DITHER\n"; if (m_fullRange) defines += "#define XBMC_FULLRANGE\n"; -#ifdef HAS_GL if (m_3DLUT) defines += "#define KODI_3DLUT\n"; -#endif //HAS_GL return defines; } @@ -84,10 +82,8 @@ void GLSLOutput::OnCompiledAndLinked(GLuint programHandle) // 3DLUT if (m_3DLUT) { -#ifdef HAS_GL m_hCLUT = glGetUniformLocation(programHandle, "m_CLUT"); m_hCLUTSize = glGetUniformLocation(programHandle, "m_CLUTsize"); -#endif //HAS_GL } if (m_dither) @@ -105,18 +101,14 @@ void GLSLOutput::OnCompiledAndLinked(GLuint programHandle) glActiveTexture(GL_TEXTURE0 + m_uDither); glBindTexture(GL_TEXTURE_2D, m_tDitherTex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); -#if defined(HAS_GL) glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); -#endif glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); -#if defined(HAS_GL) // load dither texture data glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, dither_size, dither_size, 0, GL_RED, GL_UNSIGNED_SHORT, dither_matrix); -#endif } glActiveTexture(GL_TEXTURE0); @@ -148,7 +140,6 @@ bool GLSLOutput::OnEnabled() if (m_3DLUT) { -#ifdef HAS_GL // set texture units glUniform1i(m_hCLUT, m_uCLUT); glUniform1f(m_hCLUTSize, m_uCLUTSize); @@ -159,7 +150,6 @@ bool GLSLOutput::OnEnabled() glBindTexture(GL_TEXTURE_3D, m_tCLUTTex); glActiveTexture(GL_TEXTURE0); VerifyGLState(); -#endif //HAS_GL } VerifyGLState(); @@ -176,10 +166,8 @@ void GLSLOutput::OnDisabled() } if (m_3DLUT) { -#ifdef HAS_GL glActiveTexture(GL_TEXTURE0 + m_uCLUT); glDisable(GL_TEXTURE_3D); -#endif //HAS_GL } glActiveTexture(GL_TEXTURE0); VerifyGLState(); diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutputGLES.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutputGLES.cpp new file mode 100644 index 0000000000..8a2798db9f --- /dev/null +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutputGLES.cpp @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2007 d4rk + * Copyright (C) 2007-2015 Team XBMC + * Copyright (C) 2015 Lauri Mylläri + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include "system_gl.h" +#include "utils/log.h" + +#include "GLSLOutputGLES.h" +#include "dither.h" + +using namespace Shaders; + +GLSLOutput::GLSLOutput(int texunit, bool useDithering, unsigned int ditherDepth, bool fullrange, GLuint clutTex, int clutSize) +{ + // set member variable initial values + m_1stTexUnit = texunit; + m_uDither = m_1stTexUnit+0; + m_uCLUT = m_1stTexUnit+1; + + // textures + m_tDitherTex = 0; + m_tCLUTTex = clutTex; + + // shader attribute handles + m_hDither = -1; + m_hDitherQuant = -1; + m_hDitherSize = -1; + m_hCLUT = -1; + m_hCLUTSize = -1; + + m_dither = useDithering; + m_ditherDepth = ditherDepth; + m_fullRange = fullrange; + // make sure CMS is enabled - this allows us to keep the texture + // around to quickly switch between CMS on and off + m_3DLUT = clutTex > 0; + m_uCLUTSize = clutSize; +} + +std::string GLSLOutput::GetDefines() +{ + std::string defines; + if (m_dither) + defines += "#define XBMC_DITHER\n"; + if (m_fullRange) + defines += "#define XBMC_FULLRANGE\n"; +#ifdef HAS_GL + if (m_3DLUT) + defines += "#define KODI_3DLUT\n"; +#endif //HAS_GL + return defines; +} + +void GLSLOutput::OnCompiledAndLinked(GLuint programHandle) +{ + FreeTextures(); + + // get uniform locations + // dithering + if (m_dither) + { + m_hDither = glGetUniformLocation(programHandle, "m_dither"); + m_hDitherQuant = glGetUniformLocation(programHandle, "m_ditherquant"); + m_hDitherSize = glGetUniformLocation(programHandle, "m_dithersize"); + } + // 3DLUT + if (m_3DLUT) + { +#ifdef HAS_GL + m_hCLUT = glGetUniformLocation(programHandle, "m_CLUT"); + m_hCLUTSize = glGetUniformLocation(programHandle, "m_CLUTsize"); +#endif //HAS_GL + } + + if (m_dither) + { + //! @todo create a dither pattern + + // create a dither texture + glGenTextures(1, &m_tDitherTex); + if ( m_tDitherTex <= 0 ) + { + CLog::Log(LOGERROR, "Error creating dither texture"); + return; + } + // bind and set texture parameters + glActiveTexture(GL_TEXTURE0 + m_uDither); + glBindTexture(GL_TEXTURE_2D, m_tDitherTex); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); +#if defined(HAS_GL) + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); +#endif + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + +#if defined(HAS_GL) + // load dither texture data + glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, dither_size, dither_size, 0, GL_RED, GL_UNSIGNED_SHORT, dither_matrix); +#endif + } + + glActiveTexture(GL_TEXTURE0); + + VerifyGLState(); +} + +bool GLSLOutput::OnEnabled() +{ + + if (m_dither) + { + // set texture units + glUniform1i(m_hDither, m_uDither); + VerifyGLState(); + + // bind textures + glActiveTexture(GL_TEXTURE0 + m_uDither); + glBindTexture(GL_TEXTURE_2D, m_tDitherTex); + glActiveTexture(GL_TEXTURE0); + VerifyGLState(); + + // dither settings + glUniform1f(m_hDitherQuant, (1<<m_ditherDepth)-1.0); + VerifyGLState(); + glUniform2f(m_hDitherSize, dither_size, dither_size); + VerifyGLState(); + } + + if (m_3DLUT) + { +#ifdef HAS_GL + // set texture units + glUniform1i(m_hCLUT, m_uCLUT); + glUniform1f(m_hCLUTSize, m_uCLUTSize); + VerifyGLState(); + + // bind textures + glActiveTexture(GL_TEXTURE0 + m_uCLUT); + glBindTexture(GL_TEXTURE_3D, m_tCLUTTex); + glActiveTexture(GL_TEXTURE0); + VerifyGLState(); +#endif //HAS_GL + } + + VerifyGLState(); + return true; +} + +void GLSLOutput::OnDisabled() +{ + // disable textures + if (m_dither) + { + glActiveTexture(GL_TEXTURE0 + m_uDither); + glDisable(GL_TEXTURE_2D); + } + if (m_3DLUT) + { +#ifdef HAS_GL + glActiveTexture(GL_TEXTURE0 + m_uCLUT); + glDisable(GL_TEXTURE_3D); +#endif //HAS_GL + } + glActiveTexture(GL_TEXTURE0); + VerifyGLState(); +} + +void GLSLOutput::Free() +{ + FreeTextures(); +} + +void GLSLOutput::FreeTextures() +{ + if (m_tDitherTex) + { + glDeleteTextures(1, &m_tDitherTex); + m_tDitherTex = 0; + } +} diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutputGLES.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutputGLES.h new file mode 100644 index 0000000000..047aba0361 --- /dev/null +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/GLSLOutputGLES.h @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2007-2015 Team XBMC + * Copyright (C) 2015 Lauri Mylläri + * http://xbmc.org + * + * This Program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This Program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBMC; see the file COPYING. If not, see + * <http://www.gnu.org/licenses/>. + * + */ +#pragma once + +#include "system.h" +#include "utils/GLUtils.h" + +namespace Shaders +{ + class GLSLOutput + { + public: + // take the 1st available texture unit as a parameter + GLSLOutput( + int texunit, + bool useDithering, + unsigned int ditherDepth, + bool fullrange, + GLuint clutTex, + int clutSize); + std::string GetDefines(); + void OnCompiledAndLinked(GLuint programHandle); + bool OnEnabled(); + void OnDisabled(); + void Free(); + + private: + void FreeTextures(); + + bool m_dither; + unsigned int m_ditherDepth; + bool m_fullRange; + bool m_3DLUT; + // first texture unit available to us + int m_1stTexUnit; + int m_uDither; + int m_uCLUT; + int m_uCLUTSize; + + // defines + + // attribute locations + GLint m_hDither; + GLint m_hDitherQuant; + GLint m_hDitherSize; + GLint m_hCLUT; + GLint m_hCLUTSize; + + // textures + GLuint m_tDitherTex; + GLuint m_tCLUTTex; + }; +} diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/VideoFilterShaderGL.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/VideoFilterShaderGL.cpp index 8db8e9a1cd..7d670f0128 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/VideoFilterShaderGL.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/VideoFilterShaderGL.cpp @@ -30,12 +30,8 @@ #include "ConvolutionKernels.h" #include "windowing/WindowingFactory.h" -#if defined(HAS_GL) - #define USE1DTEXTURE - #define TEXTARGET GL_TEXTURE_1D -#else - #define TEXTARGET GL_TEXTURE_2D -#endif +#define USE1DTEXTURE +#define TEXTARGET GL_TEXTURE_1D using namespace Shaders; @@ -52,30 +48,22 @@ BaseVideoFilterShader::BaseVideoFilterShader() m_stepY = 0; m_sourceTexUnit = 0; m_hSourceTex = 0; - m_stretch = 0.0f; - std::string shaderv = - "varying vec2 cord;" - "void main()" - "{" - "cord = vec2(gl_TextureMatrix[0] * gl_MultiTexCoord0);" - "gl_Position = ftransform();" - "gl_FrontColor = gl_Color;" - "}"; - VertexShader()->SetSource(shaderv); - - std::string shaderp = - "uniform sampler2D img;" - "varying vec2 cord;" - "void main()" - "{" - "gl_FragColor.rgb = texture2D(img, cord).rgb;" - "gl_FragColor.a = gl_Color.a;" - "}"; - PixelShader()->SetSource(shaderp); + VertexShader()->LoadSource("gl_videofilter_vertex.glsl"); + + PixelShader()->LoadSource("gl_videofilter_frag.glsl"); +} + +BaseVideoFilterShader::~BaseVideoFilterShader() +{ + Free(); } +////////////////////////////////////////////////////////////////////// +// ConvolutionFilterShader - base class for video filter shaders +////////////////////////////////////////////////////////////////////// + ConvolutionFilterShader::ConvolutionFilterShader(ESCALINGMETHOD method, bool stretch, GLSLOutput *output) { m_method = method; @@ -84,34 +72,28 @@ ConvolutionFilterShader::ConvolutionFilterShader(ESCALINGMETHOD method, bool str std::string shadername; std::string defines; -#if defined(HAS_GL) m_floattex = g_Windowing.IsExtSupported("GL_ARB_texture_float"); -#elif HAS_GLES >= 2 - m_floattex = false; -#endif if (m_method == VS_SCALINGMETHOD_CUBIC || m_method == VS_SCALINGMETHOD_LANCZOS2 || m_method == VS_SCALINGMETHOD_SPLINE36_FAST || m_method == VS_SCALINGMETHOD_LANCZOS3_FAST) { - shadername = "convolution-4x4.glsl"; -#if defined(HAS_GL) + shadername = "gl_convolution-4x4.glsl"; + if (m_floattex) m_internalformat = GL_RGBA16F_ARB; else -#endif m_internalformat = GL_RGBA; } else if (m_method == VS_SCALINGMETHOD_SPLINE36 || m_method == VS_SCALINGMETHOD_LANCZOS3) { - shadername = "convolution-6x6.glsl"; -#if defined(HAS_GL) + shadername = "gl_convolution-6x6.glsl"; + if (m_floattex) m_internalformat = GL_RGB16F_ARB; else -#endif m_internalformat = GL_RGB; } @@ -141,7 +123,7 @@ ConvolutionFilterShader::ConvolutionFilterShader(ESCALINGMETHOD method, bool str CLog::Log(LOGDEBUG, "GL: ConvolutionFilterShader: using %s defines:\n%s", shadername.c_str(), defines.c_str()); PixelShader()->LoadSource(shadername, defines); - PixelShader()->AppendSource("output.glsl"); + PixelShader()->AppendSource("gl_output.glsl"); } ConvolutionFilterShader::~ConvolutionFilterShader() @@ -153,9 +135,13 @@ void ConvolutionFilterShader::OnCompiledAndLinked() { // obtain shader attribute handles on successful compilation m_hSourceTex = glGetUniformLocation(ProgramHandle(), "img"); - m_hStepXY = glGetUniformLocation(ProgramHandle(), "stepxy"); - m_hKernTex = glGetUniformLocation(ProgramHandle(), "kernelTex"); - m_hStretch = glGetUniformLocation(ProgramHandle(), "m_stretch"); + m_hStepXY = glGetUniformLocation(ProgramHandle(), "stepxy"); + m_hKernTex = glGetUniformLocation(ProgramHandle(), "kernelTex"); + m_hStretch = glGetUniformLocation(ProgramHandle(), "m_stretch"); + m_hProj = glGetUniformLocation(ProgramHandle(), "m_proj"); + m_hModel = glGetUniformLocation(ProgramHandle(), "m_model"); + m_hVertex = glGetAttribLocation(ProgramHandle(), "m_attrpos"); + m_hCoord = glGetAttribLocation(ProgramHandle(), "m_attrcord"); CConvolutionKernel kernel(m_method, 256); @@ -222,6 +208,10 @@ bool ConvolutionFilterShader::OnEnabled() glUniform1i(m_hKernTex, 2); glUniform2f(m_hStepXY, m_stepX, m_stepY); glUniform1f(m_hStretch, m_stretch); + + glUniformMatrix4fv(m_hProj, 1, GL_FALSE, m_proj); + glUniformMatrix4fv(m_hModel, 1, GL_FALSE, m_model); + VerifyGLState(); if (m_glslOutput) m_glslOutput->OnEnabled(); return true; @@ -241,33 +231,53 @@ void ConvolutionFilterShader::Free() BaseVideoFilterShader::Free(); } +////////////////////////////////////////////////////////////////////// +// StretchFilterShader - base class for video filter shaders +////////////////////////////////////////////////////////////////////// + StretchFilterShader::StretchFilterShader() { - PixelShader()->LoadSource("stretch.glsl"); + PixelShader()->LoadSource("gl_stretch.glsl"); } void StretchFilterShader::OnCompiledAndLinked() { m_hSourceTex = glGetUniformLocation(ProgramHandle(), "img"); - m_hStretch = glGetUniformLocation(ProgramHandle(), "m_stretch"); + m_hStretch = glGetUniformLocation(ProgramHandle(), "m_stretch"); + m_hProj = glGetUniformLocation(ProgramHandle(), "m_proj"); + m_hModel = glGetUniformLocation(ProgramHandle(), "m_model"); + m_hVertex = glGetAttribLocation(ProgramHandle(), "m_attrpos"); + m_hCoord = glGetAttribLocation(ProgramHandle(), "m_attrcord"); } bool StretchFilterShader::OnEnabled() { glUniform1i(m_hSourceTex, m_sourceTexUnit); glUniform1f(m_hStretch, m_stretch); + glUniformMatrix4fv(m_hProj, 1, GL_FALSE, m_proj); + glUniformMatrix4fv(m_hModel, 1, GL_FALSE, m_model); VerifyGLState(); return true; } +////////////////////////////////////////////////////////////////////// +// DefaultFilterShader - base class for video filter shaders +////////////////////////////////////////////////////////////////////// + void DefaultFilterShader::OnCompiledAndLinked() { m_hSourceTex = glGetUniformLocation(ProgramHandle(), "img"); + m_hProj = glGetUniformLocation(ProgramHandle(), "m_proj"); + m_hModel = glGetUniformLocation(ProgramHandle(), "m_model"); + m_hVertex = glGetAttribLocation(ProgramHandle(), "m_attrpos"); + m_hCoord = glGetAttribLocation(ProgramHandle(), "m_attrcord"); } bool DefaultFilterShader::OnEnabled() { glUniform1i(m_hSourceTex, m_sourceTexUnit); + glUniformMatrix4fv(m_hProj, 1, GL_FALSE, m_proj); + glUniformMatrix4fv(m_hModel, 1, GL_FALSE, m_model); VerifyGLState(); return true; } diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/VideoFilterShaderGL.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/VideoFilterShaderGL.h index b9a7eaacb0..5d821516ec 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/VideoFilterShaderGL.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/VideoFilterShaderGL.h @@ -22,10 +22,7 @@ #include "system.h" -#if defined(HAS_GL) || HAS_GLES >= 2 #include "system_gl.h" - - #include "guilib/Shader.h" #include "settings/VideoSettings.h" #include "GLSLOutput.h" @@ -36,13 +33,18 @@ namespace Shaders { { public: BaseVideoFilterShader(); - void Free() override { CGLSLShaderProgram::Free(); } + virtual ~BaseVideoFilterShader(); virtual void SetSourceTexture(GLint ytex) { m_sourceTexUnit = ytex; } virtual void SetWidth(int w) { m_width = w; m_stepX = w>0?1.0f/w:0; } virtual void SetHeight(int h) { m_height = h; m_stepY = h>0?1.0f/h:0; } virtual void SetNonLinStretch(float stretch) { m_stretch = stretch; } virtual bool GetTextureFilter(GLint& filter) { return false; } + GLint GetVertexLoc() { return m_hVertex; } + GLint GetCoordLoc() { return m_hCoord; } + + void SetMatrices(GLfloat *p, GLfloat *m) { m_proj = p; m_model = m; } + protected: int m_width; int m_height; @@ -50,11 +52,17 @@ namespace Shaders { float m_stepY; float m_stretch; GLint m_sourceTexUnit; + GLfloat *m_proj = nullptr; + GLfloat *m_model = nullptr; // shader attribute handles GLint m_hSourceTex; GLint m_hStepXY; GLint m_hStretch = 0; + GLint m_hVertex = -1; + GLint m_hCoord = -1; + GLint m_hProj = -1; + GLint m_hModel = -1; }; class ConvolutionFilterShader : public BaseVideoFilterShader @@ -100,5 +108,4 @@ namespace Shaders { } // end namespace -#endif diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/VideoFilterShaderGLES.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/VideoFilterShaderGLES.h index 48520c59c2..243048264f 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/VideoFilterShaderGLES.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/VideoFilterShaderGLES.h @@ -28,7 +28,7 @@ #include "guilib/Shader.h" #include "settings/VideoSettings.h" -#include "GLSLOutput.h" +#include "GLSLOutputGLES.h" namespace Shaders { @@ -116,4 +116,3 @@ namespace Shaders { } // end namespace #endif - diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.cpp b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.cpp index 5549ff313f..38a8731d52 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.cpp +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.cpp @@ -60,24 +60,15 @@ static void CalculateYUVMatrixGL(GLfloat res[4][4] BaseYUV2RGBGLSLShader::BaseYUV2RGBGLSLShader(bool rect, unsigned flags, EShaderFormat format, bool stretch, GLSLOutput *output) { - m_width = 1; - m_height = 1; - m_field = 0; - m_flags = flags; - m_format = format; - - m_black = 0.0f; - m_contrast = 1.0f; - + m_width = 1; + m_height = 1; + m_field = 0; + m_flags = flags; + m_format = format; + m_black = 0.0f; + m_contrast = 1.0f; m_stretch = 0.0f; - // shader attribute handles - m_hYTex = -1; - m_hUTex = -1; - m_hVTex = -1; - m_hStretch = -1; - m_hStep = -1; - // get defines from the output stage if used m_glslOutput = output; if (m_glslOutput) { @@ -120,7 +111,7 @@ BaseYUV2RGBGLSLShader::BaseYUV2RGBGLSLShader(bool rect, unsigned flags, EShaderF else CLog::Log(LOGERROR, "GL: BaseYUV2RGBGLSLShader - unsupported format %d", m_format); - VertexShader()->LoadSource("yuv2rgb_vertex.glsl", m_defines); + VertexShader()->LoadSource("gl_yuv2rgb_vertex.glsl", m_defines); CLog::Log(LOGDEBUG, "GL: BaseYUV2RGBGLSLShader: defines:\n%s", m_defines.c_str()); } @@ -132,15 +123,23 @@ BaseYUV2RGBGLSLShader::~BaseYUV2RGBGLSLShader() void BaseYUV2RGBGLSLShader::OnCompiledAndLinked() { - m_hYTex = glGetUniformLocation(ProgramHandle(), "m_sampY"); - m_hUTex = glGetUniformLocation(ProgramHandle(), "m_sampU"); - m_hVTex = glGetUniformLocation(ProgramHandle(), "m_sampV"); - m_hMatrix = glGetUniformLocation(ProgramHandle(), "m_yuvmat"); + m_hYTex = glGetUniformLocation(ProgramHandle(), "m_sampY"); + m_hUTex = glGetUniformLocation(ProgramHandle(), "m_sampU"); + m_hVTex = glGetUniformLocation(ProgramHandle(), "m_sampV"); + m_hMatrix = glGetUniformLocation(ProgramHandle(), "m_yuvmat"); m_hStretch = glGetUniformLocation(ProgramHandle(), "m_stretch"); - m_hStep = glGetUniformLocation(ProgramHandle(), "m_step"); + m_hStep = glGetUniformLocation(ProgramHandle(), "m_step"); + m_hVertex = glGetAttribLocation(ProgramHandle(), "m_attrpos"); + m_hYcoord = glGetAttribLocation(ProgramHandle(), "m_attrcordY"); + m_hUcoord = glGetAttribLocation(ProgramHandle(), "m_attrcordU"); + m_hVcoord = glGetAttribLocation(ProgramHandle(), "m_attrcordV"); + m_hProj = glGetUniformLocation(ProgramHandle(), "m_proj"); + m_hModel = glGetUniformLocation(ProgramHandle(), "m_model"); + m_hAlpha = glGetUniformLocation(ProgramHandle(), "m_alpha"); VerifyGLState(); - if (m_glslOutput) m_glslOutput->OnCompiledAndLinked(ProgramHandle()); + if (m_glslOutput) + m_glslOutput->OnCompiledAndLinked(ProgramHandle()); } bool BaseYUV2RGBGLSLShader::OnEnabled() @@ -157,36 +156,26 @@ bool BaseYUV2RGBGLSLShader::OnEnabled() CalculateYUVMatrixGL(matrix, m_flags, m_format, m_black, m_contrast, !m_convertFullRange); glUniformMatrix4fv(m_hMatrix, 1, GL_FALSE, (GLfloat*)matrix); + glUniformMatrix4fv(m_hProj, 1, GL_FALSE, m_proj); + glUniformMatrix4fv(m_hModel, 1, GL_FALSE, m_model); + glUniform1f(m_hAlpha, m_alpha); VerifyGLState(); - if (m_glslOutput) m_glslOutput->OnEnabled(); + if (m_glslOutput) + m_glslOutput->OnEnabled(); return true; } void BaseYUV2RGBGLSLShader::OnDisabled() { - if (m_glslOutput) m_glslOutput->OnDisabled(); + if (m_glslOutput) + m_glslOutput->OnDisabled(); } void BaseYUV2RGBGLSLShader::Free() { - if (m_glslOutput) m_glslOutput->Free(); -} -////////////////////////////////////////////////////////////////////// -// BaseYUV2RGBGLSLShader - base class for GLSL YUV2RGB shaders -////////////////////////////////////////////////////////////////////// -BaseYUV2RGBARBShader::BaseYUV2RGBARBShader(unsigned flags, EShaderFormat format) -{ - m_width = 1; - m_height = 1; - m_field = 0; - m_flags = flags; - m_format = format; - - // shader attribute handles - m_hYTex = -1; - m_hUTex = -1; - m_hVTex = -1; + if (m_glslOutput) + m_glslOutput->Free(); } ////////////////////////////////////////////////////////////////////// @@ -198,101 +187,7 @@ YUV2RGBProgressiveShader::YUV2RGBProgressiveShader(bool rect, unsigned flags, ES GLSLOutput *output) : BaseYUV2RGBGLSLShader(rect, flags, format, stretch, output) { - PixelShader()->LoadSource("yuv2rgb_basic.glsl", m_defines); - PixelShader()->AppendSource("output.glsl"); -} - - -////////////////////////////////////////////////////////////////////// -// YUV2RGBBobShader - YUV2RGB with Bob deinterlacing -////////////////////////////////////////////////////////////////////// - -YUV2RGBBobShader::YUV2RGBBobShader(bool rect, unsigned flags, EShaderFormat format) - : BaseYUV2RGBGLSLShader(rect, flags, format, false) -{ - m_hStepX = -1; - m_hStepY = -1; - m_hField = -1; - PixelShader()->LoadSource("yuv2rgb_bob.glsl", m_defines); -} - -void YUV2RGBBobShader::OnCompiledAndLinked() -{ - BaseYUV2RGBGLSLShader::OnCompiledAndLinked(); - m_hStepX = glGetUniformLocation(ProgramHandle(), "m_stepX"); - m_hStepY = glGetUniformLocation(ProgramHandle(), "m_stepY"); - m_hField = glGetUniformLocation(ProgramHandle(), "m_field"); - VerifyGLState(); -} - -bool YUV2RGBBobShader::OnEnabled() -{ - if(!BaseYUV2RGBGLSLShader::OnEnabled()) - return false; - - glUniform1i(m_hField, m_field); - glUniform1f(m_hStepX, 1.0f / (float)m_width); - glUniform1f(m_hStepY, 1.0f / (float)m_height); - VerifyGLState(); - return true; -} - -////////////////////////////////////////////////////////////////////// -// YUV2RGBProgressiveShaderARB - YUV2RGB with no deinterlacing -////////////////////////////////////////////////////////////////////// -YUV2RGBProgressiveShaderARB::YUV2RGBProgressiveShaderARB(bool rect, unsigned flags, EShaderFormat format) - : BaseYUV2RGBARBShader(flags, format) -{ - m_black = 0.0f; - m_contrast = 1.0f; - - std::string shaderfile; - - if (m_format == SHADER_YUY2) - { - if(rect) - shaderfile = "yuv2rgb_basic_rect_YUY2.arb"; - else - shaderfile = "yuv2rgb_basic_2d_YUY2.arb"; - } - else if (m_format == SHADER_UYVY) - { - if(rect) - shaderfile = "yuv2rgb_basic_rect_UYVY.arb"; - else - shaderfile = "yuv2rgb_basic_2d_UYVY.arb"; - } - else - { - if(rect) - shaderfile = "yuv2rgb_basic_rect.arb"; - else - shaderfile = "yuv2rgb_basic_2d.arb"; - } - - CLog::Log(LOGDEBUG, "GL: YUV2RGBProgressiveShaderARB: loading %s", shaderfile.c_str()); - - PixelShader()->LoadSource(shaderfile); -} - -void YUV2RGBProgressiveShaderARB::OnCompiledAndLinked() -{ + PixelShader()->LoadSource("gl_yuv2rgb_basic.glsl", m_defines); + PixelShader()->AppendSource("gl_output.glsl"); } -bool YUV2RGBProgressiveShaderARB::OnEnabled() -{ - GLfloat matrix[4][4]; - CalculateYUVMatrixGL(matrix, m_flags, m_format, m_black, m_contrast, !m_convertFullRange); - - for(int i=0;i<4;i++) - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, i - , matrix[0][i] - , matrix[1][i] - , matrix[2][i] - , matrix[3][i]); - - glProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 4, - 1.0 / m_width, 1.0 / m_height, - m_width, m_height); - return true; -} diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.h index e8220f2c05..bb3fcd57a4 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGL.h @@ -40,47 +40,37 @@ void CalculateYUVMatrix(TransformMatrix &matrix namespace Shaders { - class BaseYUV2RGBShader : virtual public CShaderProgram + class BaseYUV2RGBGLSLShader : public CGLSLShaderProgram { public: - BaseYUV2RGBShader() : m_convertFullRange(false) {}; - ~BaseYUV2RGBShader() override = default; - virtual void SetField(int field) {}; - virtual void SetWidth(int width) {}; - virtual void SetHeight(int width) {}; + BaseYUV2RGBGLSLShader(bool rect, unsigned flags, EShaderFormat format, bool stretch, GLSLOutput *output=NULL); + ~BaseYUV2RGBGLSLShader(); + void Free() override; - virtual void SetBlack(float black) {}; - virtual void SetContrast(float contrast) {}; - virtual void SetNonLinStretch(float stretch) {}; + void SetField(int field) { m_field = field; } + void SetWidth(int w) { m_width = w; } + void SetHeight(int h) { m_height = h; } - void SetConvertFullColorRange(bool convertFullRange) { m_convertFullRange = convertFullRange; } - - protected: - bool m_convertFullRange; - }; + void SetBlack(float black) { m_black = black; } + void SetContrast(float contrast) { m_contrast = contrast; } + void SetNonLinStretch(float stretch) { m_stretch = stretch; } + void SetConvertFullColorRange(bool convertFullRange) { m_convertFullRange = convertFullRange; } - class BaseYUV2RGBGLSLShader - : public BaseYUV2RGBShader - , public CGLSLShaderProgram - { - public: - BaseYUV2RGBGLSLShader(bool rect, unsigned flags, EShaderFormat format, bool stretch, GLSLOutput *output=NULL); - ~BaseYUV2RGBGLSLShader() override; - void SetField(int field) override { m_field = field; } - void SetWidth(int w) override { m_width = w; } - void SetHeight(int h) override { m_height = h; } + GLint GetVertexLoc() { return m_hVertex; } + GLint GetYcoordLoc() { return m_hYcoord; } + GLint GetUcoordLoc() { return m_hUcoord; } + GLint GetVcoordLoc() { return m_hVcoord; } - void SetBlack(float black) override { m_black = black; } - void SetContrast(float contrast) override { m_contrast = contrast; } - void SetNonLinStretch(float stretch) override { m_stretch = stretch; } + void SetMatrices(GLfloat *p, GLfloat *m) { m_proj = p; m_model = m; } + void SetAlpha(GLfloat alpha) { m_alpha = alpha; } protected: void OnCompiledAndLinked() override; bool OnEnabled() override; void OnDisabled() override; - void Free() override; + bool m_convertFullRange; unsigned m_flags; EShaderFormat m_format; int m_width; @@ -91,55 +81,30 @@ namespace Shaders { float m_contrast; float m_stretch; + GLfloat *m_proj = nullptr; + GLfloat *m_model = nullptr; + GLfloat m_alpha = 1.0f; + std::string m_defines; Shaders::GLSLOutput *m_glslOutput; - // shader attribute handles - GLint m_hYTex; - GLint m_hUTex; - GLint m_hVTex; - GLint m_hMatrix; - GLint m_hStretch; - GLint m_hStep; - }; - - class BaseYUV2RGBARBShader - : public BaseYUV2RGBShader - , public CARBShaderProgram - { - public: - BaseYUV2RGBARBShader(unsigned flags, EShaderFormat format); - ~BaseYUV2RGBARBShader() override = default; - void SetField(int field) override { m_field = field; } - void SetWidth(int w) override { m_width = w; } - void SetHeight(int h) override { m_height = h; } - - void SetBlack(float black) override { m_black = black; } - void SetContrast(float contrast) override { m_contrast = contrast; } - - protected: - unsigned m_flags; - EShaderFormat m_format; - int m_width; - int m_height; - int m_field; - - float m_black; - float m_contrast; - - // shader attribute handles - GLint m_hYTex; - GLint m_hUTex; - GLint m_hVTex; - }; - - class YUV2RGBProgressiveShaderARB : public BaseYUV2RGBARBShader - { - public: - YUV2RGBProgressiveShaderARB(bool rect=false, unsigned flags=0, EShaderFormat format=SHADER_NONE); - void OnCompiledAndLinked() override; - bool OnEnabled() override; + // pixel shader attribute handles + GLint m_hYTex = -1; + GLint m_hUTex = -1; + GLint m_hVTex = -1; + GLint m_hMatrix = -1; + GLint m_hStretch = -1; + GLint m_hStep = -1; + + // vertex shader attribute handles + GLint m_hVertex = -1; + GLint m_hYcoord = -1; + GLint m_hUcoord = -1; + GLint m_hVcoord = -1; + GLint m_hProj = -1; + GLint m_hModel = -1; + GLint m_hAlpha = -1; }; class YUV2RGBProgressiveShader : public BaseYUV2RGBGLSLShader @@ -152,18 +117,6 @@ namespace Shaders { GLSLOutput *output=NULL); }; - class YUV2RGBBobShader : public BaseYUV2RGBGLSLShader - { - public: - YUV2RGBBobShader(bool rect=false, unsigned flags=0, EShaderFormat format=SHADER_NONE); - void OnCompiledAndLinked() override; - bool OnEnabled() override; - - GLint m_hStepX; - GLint m_hStepY; - GLint m_hField; - }; - } // end namespace #ifndef __GNUC__ diff --git a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.h b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.h index ff36c3c533..d376bfb271 100644 --- a/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.h +++ b/xbmc/cores/VideoPlayer/VideoRenderers/VideoShaders/YUV2RGBShaderGLES.h @@ -29,7 +29,7 @@ void CalculateYUVMatrix(TransformMatrix &matrix , float contrast , bool limited); -#include "GLSLOutput.h" +#include "GLSLOutputGLES.h" #ifndef __GNUC__ #pragma warning( push ) |