OpenGL (mostly GLES) spec compliance fixes
This commit is contained in:
parent
c8e057e388
commit
4a440ab79b
11 changed files with 238 additions and 50 deletions
|
@ -1091,6 +1091,7 @@ RendererBackend _r_backend_gl33 = {
|
|||
.custom = &(GLBackendData) {
|
||||
.vtable = {
|
||||
.texture_type_info = gl33_texture_type_info,
|
||||
.texture_format_caps = gl33_texture_format_caps,
|
||||
.init_context = gl33_init_context,
|
||||
}
|
||||
},
|
||||
|
|
|
@ -14,7 +14,21 @@
|
|||
#include "gl33.h"
|
||||
#include "../glcommon/debug.h"
|
||||
|
||||
static GLuint r_filter_to_gl_filter(TextureFilterMode mode) {
|
||||
static GLenum linear_to_nearest(GLenum filter) {
|
||||
switch(filter) {
|
||||
case GL_LINEAR:
|
||||
return GL_NEAREST;
|
||||
|
||||
case GL_LINEAR_MIPMAP_LINEAR:
|
||||
case GL_LINEAR_MIPMAP_NEAREST:
|
||||
return GL_NEAREST_MIPMAP_NEAREST;
|
||||
|
||||
default:
|
||||
return GL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static GLuint r_filter_to_gl_filter(TextureFilterMode mode, GLenum for_format) {
|
||||
static GLuint map[] = {
|
||||
[TEX_FILTER_LINEAR] = GL_LINEAR,
|
||||
[TEX_FILTER_LINEAR_MIPMAP_NEAREST] = GL_LINEAR_MIPMAP_NEAREST,
|
||||
|
@ -25,7 +39,35 @@ static GLuint r_filter_to_gl_filter(TextureFilterMode mode) {
|
|||
};
|
||||
|
||||
assert((uint)mode < sizeof(map)/sizeof(*map));
|
||||
return map[mode];
|
||||
GLenum filter = map[mode];
|
||||
GLenum alt_filter = linear_to_nearest(filter);
|
||||
|
||||
if(alt_filter != GL_NONE && !(GLVT.texture_format_caps(for_format) & GLTEX_FILTERABLE)) {
|
||||
filter = alt_filter;
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
GLTexFormatCapabilities gl33_texture_format_caps(GLenum internal_fmt) {
|
||||
GLTexFormatCapabilities caps = 0;
|
||||
|
||||
GLenum base_fmt = glcommon_texture_base_format(internal_fmt);
|
||||
|
||||
switch(base_fmt) {
|
||||
case GL_RED:
|
||||
case GL_RG:
|
||||
case GL_RGB:
|
||||
case GL_RGBA:
|
||||
caps |= GLTEX_COLOR_RENDERABLE | GLTEX_FILTERABLE;
|
||||
break;
|
||||
|
||||
case GL_DEPTH_COMPONENT:
|
||||
caps |= GLTEX_DEPTH_RENDERABLE | GLTEX_FILTERABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
static GLuint r_wrap_to_gl_wrap(TextureWrapMode mode) {
|
||||
|
@ -197,10 +239,12 @@ Texture* gl33_texture_create(const TextureParams *params) {
|
|||
gl33_bind_texture(tex, false);
|
||||
gl33_sync_texunit(tex->binding_unit, false, true);
|
||||
|
||||
tex->type_info = GLVT.texture_type_info(p->type);
|
||||
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, r_wrap_to_gl_wrap(p->wrap.s));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, r_wrap_to_gl_wrap(p->wrap.t));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, r_filter_to_gl_filter(p->filter.min));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, r_filter_to_gl_filter(p->filter.mag));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, r_filter_to_gl_filter(p->filter.min, tex->type_info->internal_fmt));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, r_filter_to_gl_filter(p->filter.mag, tex->type_info->internal_fmt));
|
||||
|
||||
if(!glext.version.is_es || GLES_ATLEAST(3, 0)) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, p->mipmaps - 1);
|
||||
|
@ -210,8 +254,6 @@ Texture* gl33_texture_create(const TextureParams *params) {
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY, p->anisotropy);
|
||||
}
|
||||
|
||||
tex->type_info = GLVT.texture_type_info(p->type);
|
||||
|
||||
if(p->stream && glext.pixel_buffer_object) {
|
||||
glGenBuffers(1, &tex->pbo);
|
||||
}
|
||||
|
@ -245,14 +287,14 @@ void gl33_texture_set_filter(Texture *tex, TextureFilterMode fmin, TextureFilter
|
|||
gl33_bind_texture(tex, false);
|
||||
gl33_sync_texunit(tex->binding_unit, false, true);
|
||||
tex->params.filter.min = fmin;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, r_filter_to_gl_filter(fmin));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, r_filter_to_gl_filter(fmin, tex->type_info->internal_fmt));
|
||||
}
|
||||
|
||||
if(tex->params.filter.mag != fmag) {
|
||||
gl33_bind_texture(tex, false);
|
||||
gl33_sync_texunit(tex->binding_unit, false, true);
|
||||
tex->params.filter.mag = fmag;
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, r_filter_to_gl_filter(fmag));
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, r_filter_to_gl_filter(fmag, tex->type_info->internal_fmt));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,5 +44,6 @@ void gl33_texture_clear(Texture *tex, const Color *clr);
|
|||
void gl33_texture_destroy(Texture *tex);
|
||||
|
||||
GLTextureTypeInfo* gl33_texture_type_info(TextureType type);
|
||||
GLTexFormatCapabilities gl33_texture_format_caps(GLenum internal_fmt);
|
||||
|
||||
#endif // IGUARD_renderer_gl33_texture_h
|
||||
|
|
|
@ -502,7 +502,7 @@ void glcommon_check_extensions(void) {
|
|||
glext.version.is_es = strstartswith(glv, "OpenGL ES");
|
||||
|
||||
if(glext.version.is_es) {
|
||||
glext.version.is_ANGLE = GL_ANGLE_translated_shader_source;
|
||||
glext.version.is_ANGLE = strstr(glv, "(ANGLE ");
|
||||
}
|
||||
|
||||
log_info("OpenGL version: %s", glv);
|
||||
|
|
|
@ -82,3 +82,90 @@ GLTextureFormatTuple* glcommon_find_best_pixformat(TextureType textype, PixmapFo
|
|||
GLTextureFormatTuple *formats = GLVT.texture_type_info(textype)->external_formats;
|
||||
return glcommon_find_best_pixformat_internal(formats, pxfmt);
|
||||
}
|
||||
|
||||
GLenum glcommon_texture_base_format(GLenum internal_fmt) {
|
||||
switch(internal_fmt) {
|
||||
// NOTE: semi-generated code
|
||||
case GL_COMPRESSED_RED: return GL_RED;
|
||||
case GL_COMPRESSED_RED_RGTC1: return GL_RED;
|
||||
case GL_COMPRESSED_RG: return GL_RG;
|
||||
case GL_COMPRESSED_RGB: return GL_RGB;
|
||||
case GL_COMPRESSED_RGBA: return GL_RGBA;
|
||||
case GL_COMPRESSED_RG_RGTC2: return GL_RG;
|
||||
case GL_COMPRESSED_SIGNED_RED_RGTC1: return GL_RED;
|
||||
case GL_COMPRESSED_SIGNED_RG_RGTC2: return GL_RG;
|
||||
case GL_COMPRESSED_SRGB: return GL_RGB;
|
||||
case GL_COMPRESSED_SRGB_ALPHA: return GL_RGBA;
|
||||
case GL_DEPTH24_STENCIL8: return GL_DEPTH_STENCIL;
|
||||
case GL_DEPTH32F_STENCIL8: return GL_DEPTH_STENCIL;
|
||||
case GL_DEPTH_COMPONENT16: return GL_DEPTH_COMPONENT;
|
||||
case GL_DEPTH_COMPONENT24: return GL_DEPTH_COMPONENT;
|
||||
case GL_DEPTH_COMPONENT32: return GL_DEPTH_COMPONENT;
|
||||
case GL_DEPTH_COMPONENT32F: return GL_DEPTH_COMPONENT;
|
||||
case GL_R11F_G11F_B10F: return GL_RGB;
|
||||
case GL_R16: return GL_RED;
|
||||
case GL_R16F: return GL_RED;
|
||||
case GL_R16I: return GL_RED;
|
||||
case GL_R16UI: return GL_RED;
|
||||
case GL_R16_SNORM: return GL_RED;
|
||||
case GL_R32F: return GL_RED;
|
||||
case GL_R32I: return GL_RED;
|
||||
case GL_R32UI: return GL_RED;
|
||||
case GL_R3_G3_B2: return GL_RGB;
|
||||
case GL_R8: return GL_RED;
|
||||
case GL_R8I: return GL_RED;
|
||||
case GL_R8UI: return GL_RED;
|
||||
case GL_R8_SNORM: return GL_RED;
|
||||
case GL_RG16: return GL_RG;
|
||||
case GL_RG16F: return GL_RG;
|
||||
case GL_RG16I: return GL_RG;
|
||||
case GL_RG16UI: return GL_RG;
|
||||
case GL_RG16_SNORM: return GL_RG;
|
||||
case GL_RG32F: return GL_RG;
|
||||
case GL_RG32I: return GL_RG;
|
||||
case GL_RG32UI: return GL_RG;
|
||||
case GL_RG8: return GL_RG;
|
||||
case GL_RG8I: return GL_RG;
|
||||
case GL_RG8UI: return GL_RG;
|
||||
case GL_RG8_SNORM: return GL_RG;
|
||||
case GL_RGB10: return GL_RGB;
|
||||
case GL_RGB10_A2: return GL_RGBA;
|
||||
case GL_RGB10_A2UI: return GL_RGBA;
|
||||
case GL_RGB12: return GL_RGB;
|
||||
case GL_RGB16: return GL_RGB;
|
||||
case GL_RGB16F: return GL_RGB;
|
||||
case GL_RGB16I: return GL_RGB;
|
||||
case GL_RGB16UI: return GL_RGB;
|
||||
case GL_RGB16_SNORM: return GL_RGB;
|
||||
case GL_RGB32F: return GL_RGB;
|
||||
case GL_RGB32I: return GL_RGB;
|
||||
case GL_RGB32UI: return GL_RGB;
|
||||
case GL_RGB4: return GL_RGB;
|
||||
case GL_RGB5: return GL_RGB;
|
||||
case GL_RGB5_A1: return GL_RGBA;
|
||||
case GL_RGB8: return GL_RGB;
|
||||
case GL_RGB8I: return GL_RGB;
|
||||
case GL_RGB8UI: return GL_RGB;
|
||||
case GL_RGB8_SNORM: return GL_RGB;
|
||||
case GL_RGB9_E5: return GL_RGB;
|
||||
case GL_RGBA12: return GL_RGBA;
|
||||
case GL_RGBA16: return GL_RGBA;
|
||||
case GL_RGBA16F: return GL_RGBA;
|
||||
case GL_RGBA16I: return GL_RGBA;
|
||||
case GL_RGBA16UI: return GL_RGBA;
|
||||
case GL_RGBA16_SNORM: return GL_RGBA;
|
||||
case GL_RGBA2: return GL_RGBA;
|
||||
case GL_RGBA32F: return GL_RGBA;
|
||||
case GL_RGBA32I: return GL_RGBA;
|
||||
case GL_RGBA32UI: return GL_RGBA;
|
||||
case GL_RGBA4: return GL_RGBA;
|
||||
case GL_RGBA8: return GL_RGBA;
|
||||
case GL_RGBA8I: return GL_RGBA;
|
||||
case GL_RGBA8UI: return GL_RGBA;
|
||||
case GL_RGBA8_SNORM: return GL_RGBA;
|
||||
case GL_SRGB8: return GL_RGB;
|
||||
case GL_SRGB8_ALPHA8: return GL_RGBA;
|
||||
}
|
||||
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
|
|
@ -28,5 +28,6 @@ typedef struct GLTextureTypeInfo {
|
|||
} GLTextureTypeInfo;
|
||||
|
||||
GLTextureFormatTuple* glcommon_find_best_pixformat(TextureType textype, PixmapFormat pxfmt);
|
||||
GLenum glcommon_texture_base_format(GLenum internal_fmt);
|
||||
|
||||
#endif // IGUARD_renderer_glcommon_texture_h
|
||||
|
|
|
@ -15,8 +15,15 @@
|
|||
#include "../common/backend.h"
|
||||
#include "texture.h"
|
||||
|
||||
typedef enum GLTexFormatCapabilities {
|
||||
GLTEX_COLOR_RENDERABLE,
|
||||
GLTEX_DEPTH_RENDERABLE,
|
||||
GLTEX_FILTERABLE,
|
||||
} GLTexFormatCapabilities;
|
||||
|
||||
typedef struct GLVTable {
|
||||
GLTextureTypeInfo* (*texture_type_info)(TextureType type);
|
||||
GLTexFormatCapabilities (*texture_format_caps)(GLenum internal_fmt);
|
||||
void (*init_context)(SDL_Window *window);
|
||||
} GLVTable;
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ RendererBackend _r_backend_gles20 = {
|
|||
.custom = &(GLBackendData) {
|
||||
.vtable = {
|
||||
.texture_type_info = gles_texture_type_info,
|
||||
.texture_format_caps = gles_texture_format_caps,
|
||||
.init_context = gles20_init_context,
|
||||
}
|
||||
},
|
||||
|
|
|
@ -25,6 +25,7 @@ RendererBackend _r_backend_gles30 = {
|
|||
.custom = &(GLBackendData) {
|
||||
.vtable = {
|
||||
.texture_type_info = gles_texture_type_info,
|
||||
.texture_format_caps = gles_texture_format_caps,
|
||||
.init_context = gles_init_context,
|
||||
}
|
||||
},
|
||||
|
|
|
@ -50,9 +50,9 @@ static GLTextureTypeInfo gles_texformats[] = {
|
|||
[TEX_TYPE_RGBA_32_FLOAT] = MAKEFMT(GL_RGBA8, FMT_RGBA8),
|
||||
|
||||
// WARNING: ANGLE bug(?): texture binding fails if a sized format is used here.
|
||||
[TEX_TYPE_DEPTH_8] = MAKEFMT(GL_DEPTH_COMPONENT, FMT_DEPTH),
|
||||
[TEX_TYPE_DEPTH_16] = MAKEFMT(GL_DEPTH_COMPONENT, FMT_DEPTH),
|
||||
[TEX_TYPE_DEPTH_32_FLOAT] = MAKEFMT(GL_DEPTH_COMPONENT, FMT_DEPTH),
|
||||
[TEX_TYPE_DEPTH_8] = MAKEFMT(GL_DEPTH_COMPONENT16, FMT_DEPTH),
|
||||
[TEX_TYPE_DEPTH_16] = MAKEFMT(GL_DEPTH_COMPONENT16, FMT_DEPTH),
|
||||
[TEX_TYPE_DEPTH_32_FLOAT] = MAKEFMT(GL_DEPTH_COMPONENT16, FMT_DEPTH),
|
||||
};
|
||||
|
||||
static inline void set_format(TextureType t, GLenum internal, GLTextureFormatTuple external) {
|
||||
|
@ -63,11 +63,19 @@ static inline void set_format(TextureType t, GLenum internal, GLTextureFormatTup
|
|||
|
||||
void gles_init_texformats_table(void) {
|
||||
bool is_gles3 = GLES_ATLEAST(3, 0);
|
||||
bool is_angle = glext.version.is_ANGLE;
|
||||
bool have_rg = glext.texture_rg;
|
||||
bool have_16bit = glext.texture_norm16;
|
||||
bool have_renderable_float = glext.color_buffer_float;
|
||||
bool have_float16 = glext.texture_half_float_linear && have_renderable_float;
|
||||
bool have_float32 = glext.texture_float_linear && have_renderable_float && glext.float_blend;
|
||||
bool have_float16 = /* glext.texture_half_float_linear && */ have_renderable_float;
|
||||
bool have_float32 = /* glext.texture_float_linear && */ have_renderable_float && glext.float_blend;
|
||||
|
||||
// XXX: Workaround for an ANGLE bug
|
||||
if(is_angle) {
|
||||
set_format(TEX_TYPE_DEPTH_8, GL_DEPTH_COMPONENT, FMTSTRUCT(FMT_DEPTH));
|
||||
set_format(TEX_TYPE_DEPTH_16, GL_DEPTH_COMPONENT, FMTSTRUCT(FMT_DEPTH));
|
||||
set_format(TEX_TYPE_DEPTH_32_FLOAT, GL_DEPTH_COMPONENT, FMTSTRUCT(FMT_DEPTH));
|
||||
}
|
||||
|
||||
// WARNING: GL_RGB* is generally not color-renderable, except for GL_RGB8
|
||||
// So use GL_RGBA instead, where appropriate.
|
||||
|
@ -123,42 +131,7 @@ void gles_init_texformats_table(void) {
|
|||
gles_texformats[i].external_formats[0] = gles_texformats[i].primary_external_format;
|
||||
|
||||
if(!is_gles3) {
|
||||
switch(gles_texformats[i].internal_fmt) {
|
||||
case GL_R8:
|
||||
case GL_R16:
|
||||
case GL_R16F:
|
||||
case GL_R32F:
|
||||
gles_texformats[i].internal_fmt = GL_RED;
|
||||
break;
|
||||
|
||||
case GL_RG8:
|
||||
case GL_RG16:
|
||||
case GL_RG16F:
|
||||
case GL_RG32F:
|
||||
gles_texformats[i].internal_fmt = GL_RG;
|
||||
break;
|
||||
|
||||
case GL_RGB8:
|
||||
case GL_RGB16:
|
||||
case GL_RGB16F:
|
||||
case GL_RGB32F:
|
||||
gles_texformats[i].internal_fmt = GL_RGB;
|
||||
break;
|
||||
|
||||
case GL_RGBA8:
|
||||
case GL_RGBA16:
|
||||
case GL_RGBA16F:
|
||||
case GL_RGBA32F:
|
||||
gles_texformats[i].internal_fmt = GL_RGBA;
|
||||
break;
|
||||
|
||||
case GL_DEPTH_COMPONENT:
|
||||
break;
|
||||
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
gles_texformats[i].internal_fmt = glcommon_texture_base_format(gles_texformats[i].internal_fmt);
|
||||
assert(gles_texformats[i].internal_fmt == gles_texformats[i].primary_external_format.gl_fmt);
|
||||
}
|
||||
}
|
||||
|
@ -168,3 +141,75 @@ GLTextureTypeInfo* gles_texture_type_info(TextureType type) {
|
|||
assert((uint)type < sizeof(gles_texformats)/sizeof(*gles_texformats));
|
||||
return gles_texformats + type;
|
||||
}
|
||||
|
||||
GLTexFormatCapabilities gles_texture_format_caps(GLenum internal_fmt) {
|
||||
GLTexFormatCapabilities caps = 0;
|
||||
|
||||
/*
|
||||
* Some formats we don't care about were omitted here
|
||||
*/
|
||||
|
||||
switch(internal_fmt) {
|
||||
case GL_R8:
|
||||
case GL_RG8:
|
||||
case GL_RGB8:
|
||||
case GL_RGBA8:
|
||||
caps |= GLTEX_COLOR_RENDERABLE | GLTEX_FILTERABLE;
|
||||
break;
|
||||
|
||||
case GL_R16:
|
||||
case GL_RG16:
|
||||
case GL_RGBA16:
|
||||
if(glext.texture_norm16) {
|
||||
caps |= GLTEX_COLOR_RENDERABLE | GLTEX_FILTERABLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_RGB16:
|
||||
if(glext.texture_norm16) {
|
||||
caps |= GLTEX_FILTERABLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_R16F:
|
||||
case GL_RG16F:
|
||||
case GL_RGBA16F:
|
||||
if(glext.color_buffer_float) {
|
||||
caps |= GLTEX_COLOR_RENDERABLE;
|
||||
}
|
||||
// fallthrough
|
||||
case GL_RGB16F:
|
||||
if(glext.texture_half_float_linear) {
|
||||
caps |= GLTEX_FILTERABLE;
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_R32F:
|
||||
case GL_RG32F:
|
||||
case GL_RGB32F:
|
||||
case GL_RGBA32F:
|
||||
if(glext.float_blend) {
|
||||
if(glext.color_buffer_float && internal_fmt != GL_RGB32F) {
|
||||
caps |= GLTEX_COLOR_RENDERABLE;
|
||||
}
|
||||
|
||||
if(glext.texture_float_linear) {
|
||||
caps |= GLTEX_FILTERABLE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GL_DEPTH_COMPONENT16:
|
||||
case GL_DEPTH_COMPONENT24:
|
||||
// FIXME: Is there an extension that makes it filterable?
|
||||
// It seems to work on Mesa and ANGLE at least.
|
||||
caps |= GLTEX_DEPTH_RENDERABLE;
|
||||
break;
|
||||
|
||||
case GL_DEPTH_COMPONENT32F:
|
||||
caps |= GLTEX_DEPTH_RENDERABLE | GLTEX_FILTERABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
|
|
@ -12,8 +12,10 @@
|
|||
#include "taisei.h"
|
||||
|
||||
#include "../glcommon/texture.h"
|
||||
#include "../glcommon/vtable.h"
|
||||
|
||||
void gles_init_texformats_table(void);
|
||||
GLTextureTypeInfo* gles_texture_type_info(TextureType type);
|
||||
GLTexFormatCapabilities gles_texture_format_caps(GLenum internal_fmt);
|
||||
|
||||
#endif // IGUARD_renderer_glescommon_texture_h
|
||||
|
|
Loading…
Reference in a new issue