From 3583559164b922673b2ccdb31f810befae613779 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 28 Jan 2015 19:40:46 +0100 Subject: vo_opengl: move utility functions from loader to a separate file gl_common.c contained the function loader (which is big) and additional utility functions (not so big, but will grow when moving more out of gl_video.c). Just split them. There are no changes other than some modifications to comments. --- video/out/gl_common.c | 201 ------------------------------------------ video/out/gl_common.h | 13 --- video/out/gl_hwdec_vdpau.c | 1 + video/out/gl_osd.c | 1 + video/out/gl_utils.c | 213 +++++++++++++++++++++++++++++++++++++++++++++ video/out/gl_utils.h | 46 ++++++++++ video/out/gl_video.c | 1 + video/out/vo_opengl.c | 1 + 8 files changed, 263 insertions(+), 214 deletions(-) create mode 100644 video/out/gl_utils.c create mode 100644 video/out/gl_utils.h (limited to 'video/out') diff --git a/video/out/gl_common.c b/video/out/gl_common.c index 20d68fd029..6b2bc388ed 100644 --- a/video/out/gl_common.c +++ b/video/out/gl_common.c @@ -45,44 +45,6 @@ #include "options/options.h" #include "options/m_option.h" -//! \defgroup glgeneral OpenGL general helper functions - -// GLU has this as gluErrorString (we don't use GLU, as it is legacy-OpenGL) -static const char *gl_error_to_string(GLenum error) -{ - switch (error) { - case GL_INVALID_ENUM: return "INVALID_ENUM"; - case GL_INVALID_VALUE: return "INVALID_VALUE"; - case GL_INVALID_OPERATION: return "INVALID_OPERATION"; - case GL_INVALID_FRAMEBUFFER_OPERATION: - return "INVALID_FRAMEBUFFER_OPERATION"; - case GL_OUT_OF_MEMORY: return "OUT_OF_MEMORY"; - default: return "unknown"; - } -} - -void glCheckError(GL *gl, struct mp_log *log, const char *info) -{ - for (;;) { - GLenum error = gl->GetError(); - if (error == GL_NO_ERROR) - break; - mp_msg(log, MSGL_ERR, "%s: OpenGL error %s.\n", info, - gl_error_to_string(error)); - } -} - -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; -} - struct feature { int id; const char *name; @@ -564,153 +526,6 @@ void mpgl_load_functions(GL *gl, void *(*getProcAddress)(const GLubyte *), mpgl_load_functions2(gl, get_procaddr_wrapper, getProcAddress, ext2, log); } -/** - * \brief return the number of bytes per pixel for the given format - * \param format OpenGL format - * \param type OpenGL type - * \return bytes per pixel - * \ingroup glgeneral - * - * Does not handle all possible variants, just those used by MPlayer - */ -int glFmt2bpp(GLenum format, GLenum type) -{ - int component_size = 0; - switch (type) { - case GL_UNSIGNED_BYTE_3_3_2: - case GL_UNSIGNED_BYTE_2_3_3_REV: - return 1; - case GL_UNSIGNED_SHORT_5_5_5_1: - case GL_UNSIGNED_SHORT_1_5_5_5_REV: - case GL_UNSIGNED_SHORT_5_6_5: - case GL_UNSIGNED_SHORT_5_6_5_REV: - return 2; - case GL_UNSIGNED_BYTE: - component_size = 1; - break; - case GL_UNSIGNED_SHORT: - component_size = 2; - break; - } - switch (format) { - case GL_LUMINANCE: - case GL_ALPHA: - return component_size; - case GL_RGB_422_APPLE: - return 2; - case GL_RGB: - case GL_BGR: - case GL_RGB_INTEGER: - return 3 * component_size; - case GL_RGBA: - case GL_BGRA: - case GL_RGBA_INTEGER: - return 4 * component_size; - case GL_RED: - case GL_RED_INTEGER: - return component_size; - case GL_RG: - case GL_LUMINANCE_ALPHA: - case GL_RG_INTEGER: - return 2 * component_size; - } - abort(); // unknown -} - -/** - * \brief upload a texture, handling things like stride and slices - * \param target texture target, usually GL_TEXTURE_2D - * \param format OpenGL format of data - * \param type OpenGL type of data - * \param dataptr data to upload - * \param stride data stride - * \param x x offset in texture - * \param y y offset in texture - * \param w width of the texture part to upload - * \param h height of the texture part to upload - * \param slice height of an upload slice, 0 for all at once - * \ingroup gltexture - */ -void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type, - const void *dataptr, int stride, - int x, int y, int w, int h, int slice) -{ - const uint8_t *data = dataptr; - int y_max = y + h; - if (w <= 0 || h <= 0) - return; - if (slice <= 0) - slice = h; - if (stride < 0) { - data += (h - 1) * stride; - stride = -stride; - } - 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. -// If scratch is not NULL, points to a resizeable talloc memory block than can -// be freely used by the function (for avoiding temporary memory allocations). -void glClearTex(GL *gl, GLenum target, GLenum format, GLenum type, - int x, int y, int w, int h, uint8_t val, void **scratch) -{ - int bpp = glFmt2bpp(format, type); - int stride = w * bpp; - int size = h * stride; - if (size < 1) - return; - void *data = scratch ? *scratch : NULL; - if (talloc_get_size(data) < size) - data = talloc_realloc(NULL, data, char *, size); - memset(data, val, size); - 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 { - talloc_free(data); - } -} - -mp_image_t *glGetWindowScreenshot(GL *gl) -{ - if (gl->es) - return NULL; // ES can't read from front buffer - GLint vp[4]; //x, y, w, h - gl->GetIntegerv(GL_VIEWPORT, vp); - mp_image_t *image = mp_image_alloc(IMGFMT_RGB24, vp[2], vp[3]); - if (!image) - return NULL; - gl->PixelStorei(GL_PACK_ALIGNMENT, 1); - gl->ReadBuffer(GL_FRONT); - //flip image while reading (and also avoid stride-related trouble) - for (int y = 0; y < vp[3]; y++) { - gl->ReadPixels(vp[0], vp[1] + vp[3] - y - 1, vp[2], 1, - GL_RGB, GL_UNSIGNED_BYTE, - image->planes[0] + y * image->stride[0]); - } - gl->PixelStorei(GL_PACK_ALIGNMENT, 4); - return image; -} - typedef void (*MPGLSetBackendFn)(MPGLContext *ctx); struct backend { @@ -876,19 +691,3 @@ bool mpgl_is_thread_safe(MPGLContext *ctx) { return !!ctx->set_current; } - -void mp_log_source(struct mp_log *log, int lev, const char *src) -{ - int line = 1; - if (!src) - return; - while (*src) { - const char *end = strchr(src, '\n'); - const char *next = end + 1; - if (!end) - next = end = src + strlen(src); - mp_msg(log, lev, "[%3d] %.*s\n", line, (int)(end - src), src); - line++; - src = next; - } -} diff --git a/video/out/gl_common.h b/video/out/gl_common.h index 97e319556d..0143fea843 100644 --- a/video/out/gl_common.h +++ b/video/out/gl_common.h @@ -53,15 +53,6 @@ struct GL; typedef struct GL GL; -int glFmt2bpp(GLenum format, GLenum type); -void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type, - const void *dataptr, int stride, - int x, int y, int w, int h, int slice); -void glClearTex(GL *gl, GLenum target, GLenum format, GLenum type, - int x, int y, int w, int h, uint8_t val, void **scratch); -void glCheckError(GL *gl, struct mp_log *log, const char *info); -mp_image_t *glGetWindowScreenshot(GL *gl); - enum { MPGL_CAP_ROW_LENGTH = (1 << 4), // GL_[UN]PACK_ROW_LENGTH MPGL_CAP_FB = (1 << 5), @@ -159,10 +150,6 @@ void mpgl_load_functions(GL *gl, void *(*getProcAddress)(const GLubyte *), void mpgl_load_functions2(GL *gl, void *(*get_fn)(void *ctx, const char *n), void *fn_ctx, const char *ext2, struct mp_log *log); -// print a multi line string with line numbers (e.g. for shader sources) -// log, lev: module and log level, as in mp_msg() -void mp_log_source(struct mp_log *log, int lev, const char *src); - typedef void (GLAPIENTRY *MP_GLDEBUGPROC)(GLenum, GLenum, GLuint, GLenum, GLsizei, const GLchar *,const void *); diff --git a/video/out/gl_hwdec_vdpau.c b/video/out/gl_hwdec_vdpau.c index 49f8e7c7b5..3028fa10e1 100644 --- a/video/out/gl_hwdec_vdpau.c +++ b/video/out/gl_hwdec_vdpau.c @@ -21,6 +21,7 @@ #include #include "gl_hwdec.h" +#include "gl_utils.h" #include "video/vdpau.h" #include "video/vdpau_mixer.h" diff --git a/video/out/gl_osd.c b/video/out/gl_osd.c index 8a92d3ee8c..14c6cc4824 100644 --- a/video/out/gl_osd.c +++ b/video/out/gl_osd.c @@ -21,6 +21,7 @@ #include "bitmap_packer.h" +#include "gl_utils.h" #include "gl_osd.h" struct osd_fmt_entry { diff --git a/video/out/gl_utils.c b/video/out/gl_utils.c new file mode 100644 index 0000000000..4ab0479062 --- /dev/null +++ b/video/out/gl_utils.c @@ -0,0 +1,213 @@ +/* + * This file is part of mpv. + * Parts based on MPlayer code by Reimar Döffinger. + * + * mpv 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 of the License, or + * (at your option) any later version. + * + * mpv 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 mpv. If not, see . + * + * You can alternatively redistribute this file and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include + +#include "common/common.h" +#include "gl_utils.h" + +// GLU has this as gluErrorString (we don't use GLU, as it is legacy-OpenGL) +static const char *gl_error_to_string(GLenum error) +{ + switch (error) { + case GL_INVALID_ENUM: return "INVALID_ENUM"; + case GL_INVALID_VALUE: return "INVALID_VALUE"; + case GL_INVALID_OPERATION: return "INVALID_OPERATION"; + case GL_INVALID_FRAMEBUFFER_OPERATION: return "INVALID_FRAMEBUFFER_OPERATION"; + case GL_OUT_OF_MEMORY: return "OUT_OF_MEMORY"; + default: return "unknown"; + } +} + +void glCheckError(GL *gl, struct mp_log *log, const char *info) +{ + for (;;) { + GLenum error = gl->GetError(); + if (error == GL_NO_ERROR) + break; + mp_msg(log, MSGL_ERR, "%s: OpenGL error %s.\n", info, + gl_error_to_string(error)); + } +} + +// return the number of bytes per pixel for the given format +// does not handle all possible variants, just those used by mpv +int glFmt2bpp(GLenum format, GLenum type) +{ + int component_size = 0; + switch (type) { + case GL_UNSIGNED_BYTE_3_3_2: + case GL_UNSIGNED_BYTE_2_3_3_REV: + return 1; + case GL_UNSIGNED_SHORT_5_5_5_1: + case GL_UNSIGNED_SHORT_1_5_5_5_REV: + case GL_UNSIGNED_SHORT_5_6_5: + case GL_UNSIGNED_SHORT_5_6_5_REV: + return 2; + case GL_UNSIGNED_BYTE: + component_size = 1; + break; + case GL_UNSIGNED_SHORT: + component_size = 2; + break; + } + switch (format) { + case GL_LUMINANCE: + case GL_ALPHA: + return component_size; + case GL_RGB_422_APPLE: + return 2; + case GL_RGB: + case GL_BGR: + case GL_RGB_INTEGER: + return 3 * component_size; + case GL_RGBA: + case GL_BGRA: + case GL_RGBA_INTEGER: + return 4 * component_size; + case GL_RED: + case GL_RED_INTEGER: + return component_size; + case GL_RG: + case GL_LUMINANCE_ALPHA: + case GL_RG_INTEGER: + return 2 * component_size; + } + abort(); // unknown +} + +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; +} + +// upload a texture, handling things like stride and slices +// target: texture target, usually GL_TEXTURE_2D +// format, type: texture parameters +// dataptr, stride: image data +// x, y, width, height: part of the image to upload +// slice: height of an upload slice, 0 for all at once +void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type, + const void *dataptr, int stride, + int x, int y, int w, int h, int slice) +{ + const uint8_t *data = dataptr; + int y_max = y + h; + if (w <= 0 || h <= 0) + return; + if (slice <= 0) + slice = h; + if (stride < 0) { + data += (h - 1) * stride; + stride = -stride; + } + 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. +// If scratch is not NULL, points to a resizeable talloc memory block than can +// be freely used by the function (for avoiding temporary memory allocations). +void glClearTex(GL *gl, GLenum target, GLenum format, GLenum type, + int x, int y, int w, int h, uint8_t val, void **scratch) +{ + int bpp = glFmt2bpp(format, type); + int stride = w * bpp; + int size = h * stride; + if (size < 1) + return; + void *data = scratch ? *scratch : NULL; + if (talloc_get_size(data) < size) + data = talloc_realloc(NULL, data, char *, size); + memset(data, val, size); + 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 { + talloc_free(data); + } +} + +mp_image_t *glGetWindowScreenshot(GL *gl) +{ + if (gl->es) + return NULL; // ES can't read from front buffer + GLint vp[4]; //x, y, w, h + gl->GetIntegerv(GL_VIEWPORT, vp); + mp_image_t *image = mp_image_alloc(IMGFMT_RGB24, vp[2], vp[3]); + if (!image) + return NULL; + gl->PixelStorei(GL_PACK_ALIGNMENT, 1); + gl->ReadBuffer(GL_FRONT); + //flip image while reading (and also avoid stride-related trouble) + for (int y = 0; y < vp[3]; y++) { + gl->ReadPixels(vp[0], vp[1] + vp[3] - y - 1, vp[2], 1, + GL_RGB, GL_UNSIGNED_BYTE, + image->planes[0] + y * image->stride[0]); + } + gl->PixelStorei(GL_PACK_ALIGNMENT, 4); + return image; +} + +void mp_log_source(struct mp_log *log, int lev, const char *src) +{ + int line = 1; + if (!src) + return; + while (*src) { + const char *end = strchr(src, '\n'); + const char *next = end + 1; + if (!end) + next = end = src + strlen(src); + mp_msg(log, lev, "[%3d] %.*s\n", line, (int)(end - src), src); + line++; + src = next; + } +} diff --git a/video/out/gl_utils.h b/video/out/gl_utils.h new file mode 100644 index 0000000000..4f32e5ff56 --- /dev/null +++ b/video/out/gl_utils.h @@ -0,0 +1,46 @@ +/* + * This file is part of mpv. + * Parts based on MPlayer code by Reimar Döffinger. + * + * mpv 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 of the License, or + * (at your option) any later version. + * + * mpv 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 mpv. If not, see . + * + * You can alternatively redistribute this file and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + */ + +#ifndef MP_GL_UTILS_ +#define MP_GL_UTILS_ + +#include "gl_common.h" + +struct mp_log; + +void glCheckError(GL *gl, struct mp_log *log, const char *info); + +int glFmt2bpp(GLenum format, GLenum type); +void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type, + const void *dataptr, int stride, + int x, int y, int w, int h, int slice); +void glClearTex(GL *gl, GLenum target, GLenum format, GLenum type, + int x, int y, int w, int h, uint8_t val, void **scratch); + +mp_image_t *glGetWindowScreenshot(GL *gl); + +// print a multi line string with line numbers (e.g. for shader sources) +// log, lev: module and log level, as in mp_msg() +void mp_log_source(struct mp_log *log, int lev, const char *src); + +#endif diff --git a/video/out/gl_video.c b/video/out/gl_video.c index 805df58de6..e518a9233a 100644 --- a/video/out/gl_video.c +++ b/video/out/gl_video.c @@ -32,6 +32,7 @@ #include "misc/bstr.h" #include "gl_common.h" +#include "gl_utils.h" #include "gl_hwdec.h" #include "gl_osd.h" #include "filter_kernels.h" diff --git a/video/out/vo_opengl.c b/video/out/vo_opengl.c index 910ebb8ca3..9da92e3858 100644 --- a/video/out/vo_opengl.c +++ b/video/out/vo_opengl.c @@ -44,6 +44,7 @@ #include "sub/osd.h" #include "gl_common.h" +#include "gl_utils.h" #include "gl_hwdec.h" #include "gl_osd.h" #include "filter_kernels.h" -- cgit v1.2.3