aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordavilla <davilla@4pi.com>2013-10-17 19:12:06 -0400
committerdavilla <davilla@4pi.com>2013-10-17 19:22:25 -0400
commit0b24f567b687fd715c1e6f41ce2f324c6292fda7 (patch)
tree6cdab7b6a3433f3ea66f4c0fe3e2133ca2667190
parent525a527ebc216883c938ba0f98663f21c3b48c61 (diff)
gles: fixed, add missing nv12 render format
-rw-r--r--system/shaders/yuv2rgb_basic_gles.glsl6
-rw-r--r--xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp249
-rw-r--r--xbmc/cores/VideoRenderers/LinuxRendererGLES.h4
-rw-r--r--xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp6
4 files changed, 257 insertions, 8 deletions
diff --git a/system/shaders/yuv2rgb_basic_gles.glsl b/system/shaders/yuv2rgb_basic_gles.glsl
index 963b1de881..07bae91e8b 100644
--- a/system/shaders/yuv2rgb_basic_gles.glsl
+++ b/system/shaders/yuv2rgb_basic_gles.glsl
@@ -28,10 +28,14 @@ varying vec2 m_cordV;
uniform float m_alpha;
uniform mat4 m_yuvmat;
+// handles both YV12 and NV12 formats
void main()
{
vec4 yuv, rgb;
- yuv.rgba = vec4(texture2D(m_sampY, m_cordY).r, texture2D(m_sampU, m_cordU).r, texture2D(m_sampV, m_cordV).r, 1.0);
+ yuv.rgba = vec4( texture2D(m_sampY, m_cordY).r
+ , texture2D(m_sampU, m_cordU).g
+ , texture2D(m_sampV, m_cordV).a
+ , 1.0);
rgb = m_yuvmat * yuv;
rgb.a = m_alpha;
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
index 505f1949e2..196e460fd1 100644
--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.cpp
@@ -569,6 +569,7 @@ unsigned int CLinuxRendererGLES::PreInit()
m_NumYV12Buffers = 2;
m_formats.push_back(RENDER_FMT_YUV420P);
+ m_formats.push_back(RENDER_FMT_NV12);
m_formats.push_back(RENDER_FMT_BYPASS);
#if defined(HAVE_LIBOPENMAX)
m_formats.push_back(RENDER_FMT_OMXEGL);
@@ -779,7 +780,12 @@ void CLinuxRendererGLES::LoadShaders(int field)
m_textureCreate = &CLinuxRendererGLES::CreateSurfaceTexture;
m_textureDelete = &CLinuxRendererGLES::DeleteSurfaceTexture;
}
-
+ else if (m_format == RENDER_FMT_NV12)
+ {
+ m_textureUpload = &CLinuxRendererGLES::UploadNV12Texture;
+ m_textureCreate = &CLinuxRendererGLES::CreateNV12Texture;
+ m_textureDelete = &CLinuxRendererGLES::DeleteNV12Texture;
+ }
else
{
// default to YV12 texture handlers
@@ -1729,7 +1735,7 @@ void CLinuxRendererGLES::UploadYV12Texture(int source)
, im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
, im->stride[1]*2, im->plane[1] );
- LoadPlane( fields[FIELD_TOP][2], GL_LUMINANCE, buf.flipindex
+ 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->plane[2] );
@@ -1738,7 +1744,7 @@ void CLinuxRendererGLES::UploadYV12Texture(int source)
, im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
, im->stride[1]*2, im->plane[1] + im->stride[1] );
- LoadPlane( fields[FIELD_BOT][2], GL_LUMINANCE, buf.flipindex
+ 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->plane[2] + im->stride[2] );
@@ -1749,7 +1755,7 @@ void CLinuxRendererGLES::UploadYV12Texture(int source)
, im->width >> im->cshift_x, im->height >> im->cshift_y
, im->stride[1], im->plane[1] );
- LoadPlane( fields[FIELD_FULL][2], GL_LUMINANCE, buf.flipindex
+ LoadPlane( fields[FIELD_FULL][2], GL_ALPHA, buf.flipindex
, im->width >> im->cshift_x, im->height >> im->cshift_y
, im->stride[2], im->plane[2] );
}
@@ -1881,12 +1887,201 @@ bool CLinuxRendererGLES::CreateYV12Texture(int index)
}
else
{
+ GLenum format;
+ GLint internalformat;
+ if (p == 2) //V plane needs an alpha texture
+ {
+ format = GL_ALPHA;
+ internalformat = GL_ALPHA;
+ }
+ else
+ {
+ format = GL_LUMINANCE;
+ internalformat = GL_LUMINANCE;
+ }
+
if(m_renderMethod & RENDER_POT)
CLog::Log(LOGDEBUG, "GL: Creating YUV POT texture of size %d x %d", plane.texwidth, plane.texheight);
else
CLog::Log(LOGDEBUG, "GL: Creating YUV NPOT texture of size %d x %d", plane.texwidth, plane.texheight);
- glTexImage2D(m_textureTarget, 0, GL_LUMINANCE, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
+ glTexImage2D(m_textureTarget, 0, internalformat, plane.texwidth, plane.texheight, 0, format, GL_UNSIGNED_BYTE, NULL);
+ }
+
+ glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(m_textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(m_textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ VerifyGLState();
+ }
+ }
+ glDisable(m_textureTarget);
+ return true;
+}
+
+//********************************************************************************************************
+// NV12 Texture loading, creation and deletion
+//********************************************************************************************************
+void CLinuxRendererGLES::UploadNV12Texture(int source)
+{
+ YUVBUFFER& buf = m_buffers[source];
+ YV12Image* im = &buf.image;
+ YUVFIELDS& fields = buf.fields;
+
+ if (!(im->flags & IMAGE_FLAG_READY))
+ return;
+ bool deinterlacing;
+ if (m_currentField == FIELD_FULL)
+ deinterlacing = false;
+ else
+ deinterlacing = true;
+
+ glEnable(m_textureTarget);
+ VerifyGLState();
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, im->bpp);
+
+ if (deinterlacing)
+ {
+ // Load Odd Y field
+ LoadPlane( fields[FIELD_TOP][0] , GL_LUMINANCE, buf.flipindex
+ , im->width, im->height >> 1
+ , im->stride[0]*2, im->plane[0] );
+
+ // Load Even Y field
+ LoadPlane( fields[FIELD_BOT][0], GL_LUMINANCE, buf.flipindex
+ , im->width, im->height >> 1
+ , im->stride[0]*2, im->plane[0] + im->stride[0]) ;
+
+ // Load Odd UV Fields
+ LoadPlane( fields[FIELD_TOP][1], GL_LUMINANCE_ALPHA, buf.flipindex
+ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
+ , im->stride[1]*2, im->plane[1] );
+
+ // Load Even UV Fields
+ LoadPlane( fields[FIELD_BOT][1], GL_LUMINANCE_ALPHA, buf.flipindex
+ , im->width >> im->cshift_x, im->height >> (im->cshift_y + 1)
+ , im->stride[1]*2, im->plane[1] + im->stride[1] );
+
+ }
+ else
+ {
+ // Load Y plane
+ LoadPlane( fields[FIELD_FULL][0], GL_LUMINANCE, buf.flipindex
+ , im->width, im->height
+ , im->stride[0], im->plane[0] );
+
+ // Load UV plane
+ LoadPlane( fields[FIELD_FULL][1], GL_LUMINANCE_ALPHA, buf.flipindex
+ , im->width >> im->cshift_x, im->height >> im->cshift_y
+ , im->stride[1], im->plane[1] );
+ }
+
+ VerifyGLState();
+
+ CalculateTextureSourceRects(source, 3);
+
+ glDisable(m_textureTarget);
+ return;
+}
+
+bool CLinuxRendererGLES::CreateNV12Texture(int index)
+{
+ // since we also want the field textures, pitch must be texture aligned
+ YV12Image &im = m_buffers[index].image;
+ YUVFIELDS &fields = m_buffers[index].fields;
+
+ // Delete any old texture
+ DeleteNV12Texture(index);
+
+ im.height = m_sourceHeight;
+ im.width = m_sourceWidth;
+ im.cshift_x = 1;
+ im.cshift_y = 1;
+ im.bpp = 1;
+
+ im.stride[0] = im.width;
+ im.stride[1] = im.width;
+ im.stride[2] = 0;
+
+ im.plane[0] = NULL;
+ im.plane[1] = NULL;
+ im.plane[2] = NULL;
+
+ // Y plane
+ im.planesize[0] = im.stride[0] * im.height;
+ // packed UV plane
+ im.planesize[1] = im.stride[1] * im.height / 2;
+ // third plane is not used
+ im.planesize[2] = 0;
+
+ for (int i = 0; i < 2; i++)
+ im.plane[i] = new BYTE[im.planesize[i]];
+
+ glEnable(m_textureTarget);
+ for(int f = 0;f<MAX_FIELDS;f++)
+ {
+ for(int p = 0;p<2;p++)
+ {
+ if (!glIsTexture(fields[f][p].id))
+ {
+ glGenTextures(1, &fields[f][p].id);
+ VerifyGLState();
+ }
+ }
+ fields[f][2].id = fields[f][1].id;
+ }
+
+ // YUV
+ for (int f = FIELD_FULL; f<=FIELD_BOT ; f++)
+ {
+ int fieldshift = (f==FIELD_FULL) ? 0 : 1;
+ YUVPLANES &planes = fields[f];
+
+ planes[0].texwidth = im.width;
+ planes[0].texheight = im.height >> fieldshift;
+
+ if (m_renderMethod & RENDER_SW)
+ {
+ planes[1].texwidth = 0;
+ planes[1].texheight = 0;
+ planes[2].texwidth = 0;
+ planes[2].texheight = 0;
+ }
+ else
+ {
+ planes[1].texwidth = planes[0].texwidth >> im.cshift_x;
+ planes[1].texheight = planes[0].texheight >> im.cshift_y;
+ planes[2].texwidth = planes[1].texwidth;
+ planes[2].texheight = planes[1].texheight;
+ }
+
+ if(m_renderMethod & RENDER_POT)
+ {
+ for(int p = 0; p < 3; p++)
+ {
+ planes[p].texwidth = NP2(planes[p].texwidth);
+ planes[p].texheight = NP2(planes[p].texheight);
+ }
+ }
+
+ for(int p = 0; p < 2; p++)
+ {
+ YUVPLANE &plane = planes[p];
+ if (plane.texwidth * plane.texheight == 0)
+ continue;
+
+ glBindTexture(m_textureTarget, plane.id);
+ if (m_renderMethod & RENDER_SW)
+ {
+ glTexImage2D(m_textureTarget, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
+ }
+ else
+ {
+ if (p == 1)
+ glTexImage2D(m_textureTarget, 0, GL_LUMINANCE_ALPHA, plane.texwidth, plane.texheight, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, NULL);
+ else
+ glTexImage2D(m_textureTarget, 0, GL_LUMINANCE, plane.texwidth, plane.texheight, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);
}
glTexParameteri(m_textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
@@ -1897,8 +2092,44 @@ bool CLinuxRendererGLES::CreateYV12Texture(int index)
}
}
glDisable(m_textureTarget);
+
return true;
}
+void CLinuxRendererGLES::DeleteNV12Texture(int index)
+{
+ YV12Image &im = m_buffers[index].image;
+ YUVFIELDS &fields = m_buffers[index].fields;
+
+ if( fields[FIELD_FULL][0].id == 0 ) return;
+
+ // finish up all textures, and delete them
+ g_graphicsContext.BeginPaint(); //FIXME
+ for(int f = 0;f<MAX_FIELDS;f++)
+ {
+ for(int p = 0;p<2;p++)
+ {
+ if( fields[f][p].id )
+ {
+ if (glIsTexture(fields[f][p].id))
+ {
+ glDeleteTextures(1, &fields[f][p].id);
+ }
+ fields[f][p].id = 0;
+ }
+ }
+ fields[f][2].id = 0;
+ }
+ g_graphicsContext.EndPaint();
+
+ for(int p = 0;p<2;p++)
+ {
+ if (im.plane[p])
+ {
+ delete[] im.plane[p];
+ im.plane[p] = NULL;
+ }
+ }
+}
//********************************************************************************************************
// CoreVideoRef Texture creation, deletion, copying + clearing
@@ -2131,14 +2362,16 @@ void CLinuxRendererGLES::UploadSurfaceTexture(int index)
#if defined(TARGET_ANDROID)
#ifdef DEBUG_VERBOSE
unsigned int time = XbmcThreads::SystemClockMillis();
+ int mindex = -1;
#endif
- int mindex = -1;
YUVBUFFER &buf = m_buffers[index];
if (buf.mediacodec)
{
+#ifdef DEBUG_VERBOSE
mindex = buf.mediacodec->GetIndex();
+#endif
buf.fields[0][0].id = buf.mediacodec->GetTextureID();
buf.mediacodec->UpdateTexImage();
buf.mediacodec->GetTransformMatrix(m_textureMatrix);
@@ -2397,14 +2630,16 @@ void CLinuxRendererGLES::AddProcessor(CDVDMediaCodecInfo *mediacodec, int index)
{
#ifdef DEBUG_VERBOSE
unsigned int time = XbmcThreads::SystemClockMillis();
+ int mindex = -1;
#endif
- int mindex = -1;
YUVBUFFER &buf = m_buffers[index];
if (mediacodec)
{
buf.mediacodec = mediacodec->Retain();
+#ifdef DEBUG_VERBOSE
mindex = buf.mediacodec->GetIndex();
+#endif
// releaseOutputBuffer must be in same thread as
// dequeueOutputBuffer. We are in DVDPlayerVideo
// thread here, so we are safe.
diff --git a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
index 7742145b43..687b7c9ce1 100644
--- a/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
+++ b/xbmc/cores/VideoRenderers/LinuxRendererGLES.h
@@ -192,6 +192,10 @@ protected:
void DeleteYV12Texture(int index);
bool CreateYV12Texture(int index);
+ void UploadNV12Texture(int index);
+ void DeleteNV12Texture(int index);
+ bool CreateNV12Texture(int index);
+
void UploadCVRefTexture(int index);
void DeleteCVRefTexture(int index);
bool CreateCVRefTexture(int index);
diff --git a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp
index 48302ff64a..21a4ee2161 100644
--- a/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp
+++ b/xbmc/cores/VideoRenderers/VideoShaders/YUV2RGBShader.cpp
@@ -228,6 +228,12 @@ BaseYUV2RGBGLSLShader::BaseYUV2RGBGLSLShader(bool rect, unsigned flags, ERenderF
m_hProj = -1;
m_hModel = -1;
m_hAlpha = -1;
+ if (m_format == RENDER_FMT_YUV420P)
+ m_defines += "#define XBMC_YV12\n";
+ else if (m_format == RENDER_FMT_NV12)
+ m_defines += "#define XBMC_NV12\n";
+ else
+ CLog::Log(LOGERROR, "GL: BaseYUV2RGBGLSLShader - unsupported format %d", m_format);
VertexShader()->LoadSource("yuv2rgb_vertex_gles.glsl", m_defines);
#endif