diff options
author | wm4 <wm4@nowhere> | 2014-12-19 00:58:56 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2014-12-19 01:21:18 +0100 |
commit | fe35130ba9079c09c74a5f5334584f1ccca15e52 (patch) | |
tree | 8e03910ea175b91aa46d12e97ef211b684f1b62a /video/out/gl_common.c | |
parent | de3e26bc846eee938248c9be3a688091f0eab49c (diff) | |
download | mpv-fe35130ba9079c09c74a5f5334584f1ccca15e52.tar.bz2 mpv-fe35130ba9079c09c74a5f5334584f1ccca15e52.tar.xz |
vo_opengl: mess with PixelStorei state management
This is needed for GLES 2 support. GLES 2 doesn't support
GL_UNPACK_ROW_LENGTH, and we shouldn't even use this constant, since a
GLES implementation could raise an error.
So set it only if neccessary, and leave it in the default state
otherwise. This also smuggles in a ES 2 fallback for glUploadTex(),
and querying an extension relevant for ES 2. For the alignment state
(GL_[UN]PACK_ALIGNMENT) do the same for symmetry. All 4 states
(alignment/rows x pack/unpack) are now assumed to be in their initial
states by default.
Also redo the PixelStorei handling in the function table. I could rebase
this, but look at the commit time.
Diffstat (limited to 'video/out/gl_common.c')
-rw-r--r-- | video/out/gl_common.c | 71 |
1 files changed, 40 insertions, 31 deletions
diff --git a/video/out/gl_common.c b/video/out/gl_common.c index 7389d90370..aa5cd763ae 100644 --- a/video/out/gl_common.c +++ b/video/out/gl_common.c @@ -72,28 +72,21 @@ void glCheckError(GL *gl, struct mp_log *log, const char *info) } } -//! \defgroup glcontext OpenGL context management helper functions - -//! \defgroup gltexture OpenGL texture handling helper functions - -//! \defgroup glconversion OpenGL conversion helper functions +static int get_alignment(int stride) +{ + if (stride % 8 == 0) + return 8; + if (stride % 4 == 0) + return 4; + if (stride % 2 == 0) + return 2; + return 1; +} -/** - * \brief adjusts the GL_UNPACK_ALIGNMENT to fit the stride. - * \param stride number of bytes per line for which alignment should fit. - * \ingroup glgeneral - */ +// adjusts the GL_UNPACK_ALIGNMENT to fit the stride. void glAdjustAlignment(GL *gl, int stride) { - GLint gl_alignment; - if (stride % 8 == 0) - gl_alignment = 8; - else if (stride % 4 == 0) - gl_alignment = 4; - else if (stride % 2 == 0) - gl_alignment = 2; - else - gl_alignment = 1; + GLint gl_alignment = get_alignment(stride); gl->PixelStorei(GL_UNPACK_ALIGNMENT, gl_alignment); gl->PixelStorei(GL_PACK_ALIGNMENT, gl_alignment); } @@ -190,6 +183,7 @@ static const struct gl_functions gl_functions[] = { DEF_FN(GetError), DEF_FN(GetIntegerv), DEF_FN(GetString), + DEF_FN(PixelStorei), DEF_FN(ReadPixels), DEF_FN(TexImage2D), DEF_FN(TexParameteri), @@ -203,6 +197,7 @@ static const struct gl_functions gl_functions[] = { // GL 1.1+ desktop only { .ver_core = 110, + .provides = MPGL_CAP_ROW_LENGTH, .functions = (const struct gl_function[]) { DEF_FN(DrawBuffer), DEF_FN(GetTexImage), @@ -210,9 +205,6 @@ static const struct gl_functions gl_functions[] = { DEF_FN(ReadBuffer), DEF_FN(TexEnvi), DEF_FN(TexImage1D), - // This is actually in ES 2.0, but quite useless, because it doesn't - // support GL_[UN]PACK_ROW_LENGTH. - DEF_FN(PixelStorei), {0} }, }, @@ -282,11 +274,16 @@ static const struct gl_functions gl_functions[] = { // for ES 3.0 DEF_FN(ReadBuffer), DEF_FN(UnmapBuffer), - // ES 3.0 adds support for GL_[UN]PACK_ROW_LENGTH. - DEF_FN(PixelStorei), {0} }, }, + // Useful for ES 2.0 + { + .ver_core = 110, + .ver_es_core = 300, + .extension = "GL_EXT_unpack_subimage", + .provides = MPGL_CAP_ROW_LENGTH, + }, // Framebuffers, extension in GL 2.x, core in GL 3.x core. { .ver_core = 300, @@ -754,15 +751,24 @@ void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type, data += (h - 1) * stride; stride = -stride; } - // this is not always correct, but should work for MPlayer - glAdjustAlignment(gl, stride); - gl->PixelStorei(GL_UNPACK_ROW_LENGTH, stride / glFmt2bpp(format, type)); + gl->PixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(stride)); + bool use_rowlength = slice > 1 && (gl->mpgl_caps & MPGL_CAP_ROW_LENGTH); + if (use_rowlength) { + // this is not always correct, but should work for MPlayer + gl->PixelStorei(GL_UNPACK_ROW_LENGTH, stride / glFmt2bpp(format, type)); + } else { + if (stride != glFmt2bpp(format, type) * w) + slice = 1; // very inefficient, but at least it works + } for (; y + slice <= y_max; y += slice) { gl->TexSubImage2D(target, 0, x, y, w, slice, format, type, data); data += stride * slice; } if (y < y_max) gl->TexSubImage2D(target, 0, x, y, w, y_max - y, format, type, data); + if (use_rowlength) + gl->PixelStorei(GL_UNPACK_ROW_LENGTH, 0); + gl->PixelStorei(GL_UNPACK_ALIGNMENT, 4); } // Like glUploadTex, but upload a byte array with all elements set to val. @@ -780,9 +786,9 @@ void glClearTex(GL *gl, GLenum target, GLenum format, GLenum type, if (talloc_get_size(data) < size) data = talloc_realloc(NULL, data, char *, size); memset(data, val, size); - glAdjustAlignment(gl, stride); - gl->PixelStorei(GL_UNPACK_ROW_LENGTH, w); + gl->PixelStorei(GL_UNPACK_ALIGNMENT, get_alignment(stride)); gl->TexSubImage2D(target, 0, x, y, w, h, format, type, data); + gl->PixelStorei(GL_UNPACK_ALIGNMENT, 4); if (scratch) { *scratch = data; } else { @@ -804,10 +810,13 @@ void glDownloadTex(GL *gl, GLenum target, GLenum format, GLenum type, { if (!gl->GetTexImage) abort(); + assert(gl->mpgl_caps & MPGL_CAP_ROW_LENGTH); // this is not always correct, but should work for MPlayer - glAdjustAlignment(gl, stride); + gl->PixelStorei(GL_PACK_ALIGNMENT, get_alignment(stride)); gl->PixelStorei(GL_PACK_ROW_LENGTH, stride / glFmt2bpp(format, type)); gl->GetTexImage(target, 0, format, type, dataptr); + gl->PixelStorei(GL_PACK_ROW_LENGTH, 0); + gl->PixelStorei(GL_PACK_ALIGNMENT, 4); } mp_image_t *glGetWindowScreenshot(GL *gl) @@ -820,7 +829,6 @@ mp_image_t *glGetWindowScreenshot(GL *gl) if (!image) return NULL; gl->PixelStorei(GL_PACK_ALIGNMENT, 1); - gl->PixelStorei(GL_PACK_ROW_LENGTH, 0); gl->ReadBuffer(GL_FRONT); //flip image while reading (and also avoid stride-related trouble) for (int y = 0; y < vp[3]; y++) { @@ -828,6 +836,7 @@ mp_image_t *glGetWindowScreenshot(GL *gl) GL_RGB, GL_UNSIGNED_BYTE, image->planes[0] + y * image->stride[0]); } + gl->PixelStorei(GL_PACK_ALIGNMENT, 4); return image; } |