summaryrefslogtreecommitdiffstats
path: root/video/out/opengl/utils.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-05-12 20:08:49 +0200
committerwm4 <wm4@nowhere>2016-05-12 21:22:28 +0200
commit84ccebd9b9fba47f1e08bbc263b87174a133ea01 (patch)
tree20c5f5ab35f4144d3b6b6addaf700fc3b0cc7124 /video/out/opengl/utils.c
parente68b510a942f033c629856a36df341e05aa44e50 (diff)
downloadmpv-84ccebd9b9fba47f1e08bbc263b87174a133ea01.tar.bz2
mpv-84ccebd9b9fba47f1e08bbc263b87174a133ea01.tar.xz
vo_opengl: reorganize texture format handling
This merges all knowledge about texture format into a central table. Most of the work done here is actually identifying which formats exactly are supported by OpenGL(ES) under which circumstances, and keeping this information in the format table in a somewhat declarative way. (Although only to the extend needed by mpv.) In particular, ES and float formats are a horrible mess. Again this is a big refactor that might cause regression on "obscure" configurations.
Diffstat (limited to 'video/out/opengl/utils.c')
-rw-r--r--video/out/opengl/utils.c113
1 files changed, 17 insertions, 96 deletions
diff --git a/video/out/opengl/utils.c b/video/out/opengl/utils.c
index 60e1792a14..1085110802 100644
--- a/video/out/opengl/utils.c
+++ b/video/out/opengl/utils.c
@@ -24,6 +24,7 @@
#include <assert.h>
#include "common/common.h"
+#include "formats.h"
#include "utils.h"
// GLU has this as gluErrorString (we don't use GLU, as it is legacy-OpenGL)
@@ -50,52 +51,6 @@ void glCheckError(GL *gl, struct mp_log *log, const char *info)
}
}
-// 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)
@@ -117,9 +72,10 @@ 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)
{
+ int bpp = gl_bytes_per_pixel(format, type);
const uint8_t *data = dataptr;
int y_max = y + h;
- if (w <= 0 || h <= 0)
+ if (w <= 0 || h <= 0 || !bpp)
return;
if (slice <= 0)
slice = h;
@@ -131,9 +87,9 @@ void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type,
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));
+ gl->PixelStorei(GL_UNPACK_ROW_LENGTH, stride / bpp);
} else {
- if (stride != glFmt2bpp(format, type) * w)
+ if (stride != bpp * w)
slice = 1; // very inefficient, but at least it works
}
for (; y + slice <= y_max; y += slice) {
@@ -153,10 +109,10 @@ void glUploadTex(GL *gl, GLenum target, GLenum format, GLenum type,
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 bpp = gl_bytes_per_pixel(format, type);
int stride = w * bpp;
int size = h * stride;
- if (size < 1)
+ if (size < 1 || !bpp)
return;
void *data = scratch ? *scratch : NULL;
if (talloc_get_size(data) < size)
@@ -307,32 +263,6 @@ void gl_vao_draw_data(struct gl_vao *vao, GLenum prim, void *ptr, size_t num)
gl_vao_unbind(vao);
}
-struct gl_format {
- GLenum format;
- GLenum type;
- GLint internal_format;
-};
-
-static const struct gl_format gl_formats[] = {
- // GLES 3.0
- {GL_RGB, GL_UNSIGNED_BYTE, GL_RGB},
- {GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA},
- {GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8},
- {GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8},
- {GL_RGB, GL_UNSIGNED_SHORT, GL_RGB16},
- {GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2},
- // not texture filterable in GLES 3.0
- {GL_RGB, GL_FLOAT, GL_RGB16F},
- {GL_RGBA, GL_FLOAT, GL_RGBA16F},
- {GL_RGB, GL_FLOAT, GL_RGB32F},
- {GL_RGBA, GL_FLOAT, GL_RGBA32F},
- // Desktop GL
- {GL_RGB, GL_UNSIGNED_SHORT, GL_RGB10},
- {GL_RGBA, GL_UNSIGNED_SHORT, GL_RGBA12},
- {GL_RGBA, GL_UNSIGNED_SHORT, GL_RGBA16},
- {0}
-};
-
// Create a texture and a FBO using the texture as color attachments.
// iformat: texture internal format
// Returns success.
@@ -373,19 +303,16 @@ bool fbotex_change(struct fbotex *fbo, GL *gl, struct mp_log *log, int w, int h,
if (flags & FBOTEX_FUZZY_H)
h = MP_ALIGN_UP(h, 256);
- GLenum filter = fbo->tex_filter;
+ mp_verbose(log, "Create FBO: %dx%d (%dx%d)\n", lw, lh, w, h);
- struct gl_format format = {
- .format = GL_RGBA,
- .type = GL_UNSIGNED_BYTE,
- .internal_format = iformat,
- };
- for (int n = 0; gl_formats[n].format; n++) {
- if (gl_formats[n].internal_format == format.internal_format) {
- format = gl_formats[n];
- break;
- }
+ const struct gl_format *format = gl_find_internal_format(gl, iformat);
+ if (!format || (format->flags & F_CF) != F_CF) {
+ mp_verbose(log, "Format 0x%x not supported.\n", (unsigned)iformat);
+ return false;
}
+ assert(gl->mpgl_caps & MPGL_CAP_FB);
+
+ GLenum filter = fbo->tex_filter;
*fbo = (struct fbotex) {
.gl = gl,
@@ -396,17 +323,11 @@ bool fbotex_change(struct fbotex *fbo, GL *gl, struct mp_log *log, int w, int h,
.iformat = iformat,
};
- mp_verbose(log, "Create FBO: %dx%d -> %dx%d\n", fbo->lw, fbo->lh,
- fbo->rw, fbo->rh);
-
- if (!(gl->mpgl_caps & MPGL_CAP_FB))
- return false;
-
gl->GenFramebuffers(1, &fbo->fbo);
gl->GenTextures(1, &fbo->texture);
gl->BindTexture(GL_TEXTURE_2D, fbo->texture);
- gl->TexImage2D(GL_TEXTURE_2D, 0, format.internal_format, fbo->rw, fbo->rh, 0,
- format.format, format.type, NULL);
+ gl->TexImage2D(GL_TEXTURE_2D, 0, format->internal_format, fbo->rw, fbo->rh, 0,
+ format->format, format->type, NULL);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
gl->BindTexture(GL_TEXTURE_2D, 0);