diff --git a/common/render_api.h b/common/render_api.h index 49b51fb3..c59f4683 100644 --- a/common/render_api.h +++ b/common/render_api.h @@ -107,6 +107,7 @@ typedef enum TF_ARB_FLOAT = (1<<26), // float textures TF_NOCOMPARE = (1<<27), // disable comparing for depth textures TF_ARB_16BIT = (1<<28), // keep image as 16-bit (not 24) + TF_MULTISAMPLE = (1<<29) // multisampling texture } texFlags_t; typedef enum diff --git a/ref_gl/gl_export.h b/ref_gl/gl_export.h index 491cc908..6652c0f5 100644 --- a/ref_gl/gl_export.h +++ b/ref_gl/gl_export.h @@ -687,6 +687,7 @@ typedef float GLmatrix[16]; #define GL_SAMPLE_COVERAGE_VALUE_ARB 0x80AA #define GL_SAMPLE_COVERAGE_INVERT_ARB 0x80AB #define GL_MULTISAMPLE_BIT_ARB 0x20000000 +#define GL_TEXTURE_2D_MULTISAMPLE 0x9100 #define GL_COLOR_SUM_ARB 0x8458 #define GL_VERTEX_PROGRAM_ARB 0x8620 @@ -1181,6 +1182,7 @@ APIENTRY_LINKAGE void GL_FUNCTION( glTexGeni )(GLenum coord, GLenum pname, GLint APIENTRY_LINKAGE void GL_FUNCTION( glTexGeniv )(GLenum coord, GLenum pname, const GLint *params); APIENTRY_LINKAGE void GL_FUNCTION( glTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels); APIENTRY_LINKAGE void GL_FUNCTION( glTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); +APIENTRY_LINKAGE void GL_FUNCTION( glTexImage2DMultisample )(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations); APIENTRY_LINKAGE void GL_FUNCTION( glTexParameterf )(GLenum target, GLenum pname, GLfloat param); APIENTRY_LINKAGE void GL_FUNCTION( glTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params); APIENTRY_LINKAGE void GL_FUNCTION( glTexParameteri )(GLenum target, GLenum pname, GLint param); diff --git a/ref_gl/gl_image.c b/ref_gl/gl_image.c index 8d0f91ef..4fdeeada 100644 --- a/ref_gl/gl_image.c +++ b/ref_gl/gl_image.c @@ -49,6 +49,8 @@ static const char *GL_TargetToString( GLenum target ) return "1D"; case GL_TEXTURE_2D: return "2D"; + case GL_TEXTURE_2D_MULTISAMPLE: + return "2D Multisample"; case GL_TEXTURE_3D: return "3D"; case GL_TEXTURE_CUBE_MAP_ARB: @@ -117,6 +119,10 @@ void GL_ApplyTextureParams( gl_texture_t *tex ) Assert( tex != NULL ); + // multisample textures does not support any sampling state changing + if( FBitSet( tex->flags, TF_MULTISAMPLE )) + return; + // set texture filter if( FBitSet( tex->flags, TF_DEPTHMAP )) { @@ -523,6 +529,7 @@ static void GL_SetTextureDimensions( gl_texture_t *tex, int width, int height, i { case GL_TEXTURE_1D: case GL_TEXTURE_2D: + case GL_TEXTURE_2D_MULTISAMPLE: maxTextureSize = glConfig.max_2d_texture_size; break; case GL_TEXTURE_2D_ARRAY_EXT: @@ -626,6 +633,8 @@ static void GL_SetTextureTarget( gl_texture_t *tex, rgbdata_t *pic ) tex->target = GL_TEXTURE_3D; else if( FBitSet( tex->flags, TF_RECTANGLE )) tex->target = GL_TEXTURE_RECTANGLE_EXT; + else if( FBitSet(tex->flags, TF_MULTISAMPLE )) + tex->target = GL_TEXTURE_2D_MULTISAMPLE; else tex->target = GL_TEXTURE_2D; // default case // check for hardware support @@ -648,6 +657,9 @@ static void GL_SetTextureTarget( gl_texture_t *tex, rgbdata_t *pic ) // depth cubemaps only allowed when GL_EXT_gpu_shader4 is supported if( tex->target == GL_TEXTURE_CUBE_MAP_ARB && !GL_Support( GL_EXT_GPU_SHADER4 ) && FBitSet( tex->flags, TF_DEPTHMAP )) tex->target = GL_NONE; + + if(( tex->target == GL_TEXTURE_2D_MULTISAMPLE ) && !GL_Support( GL_TEXTURE_MULTISAMPLE )) + tex->target = GL_NONE; } /* @@ -1006,6 +1018,7 @@ static void GL_TextureImageRAW( gl_texture_t *tex, GLint side, GLint level, GLin qboolean subImage = FBitSet( tex->flags, TF_IMG_UPLOADED ); GLenum inFormat = gEngfuncs.Image_GetPFDesc(type)->glFormat; GLint dataType = GL_UNSIGNED_BYTE; + GLsizei samplesCount = 0; Assert( tex != NULL ); @@ -1032,6 +1045,21 @@ static void GL_TextureImageRAW( gl_texture_t *tex, GLint side, GLint level, GLin if( subImage ) pglTexSubImage3D( tex->target, level, 0, 0, 0, width, height, depth, inFormat, dataType, data ); else pglTexImage3D( tex->target, level, tex->format, width, height, depth, 0, inFormat, dataType, data ); } + else if( tex->target == GL_TEXTURE_2D_MULTISAMPLE ) + { + samplesCount = (GLsizei)gEngfuncs.pfnGetCvarFloat("gl_msaa_samples"); + switch (samplesCount) + { + case 2: + case 4: + case 8: + case 16: + break; + default: + samplesCount = 1; + } + pglTexImage2DMultisample( tex->target, samplesCount, tex->format, width, height, GL_TRUE ); + } else // 2D or RECT { if( subImage ) pglTexSubImage2D( tex->target, level, 0, 0, width, height, inFormat, dataType, data ); @@ -2165,6 +2193,9 @@ void R_TextureList_f( void ) case GL_TEXTURE_2D_ARRAY_EXT: gEngfuncs.Con_Printf( "ARRAY " ); break; + case GL_TEXTURE_2D_MULTISAMPLE: + gEngfuncs.Con_Printf( "MSAA "); + break; default: gEngfuncs.Con_Printf( "???? " ); break; diff --git a/ref_gl/gl_local.h b/ref_gl/gl_local.h index a50f7f0c..74e8b9fa 100644 --- a/ref_gl/gl_local.h +++ b/ref_gl/gl_local.h @@ -622,6 +622,7 @@ enum GL_DEBUG_OUTPUT, GL_ARB_VERTEX_BUFFER_OBJECT_EXT, GL_DRAW_RANGEELEMENTS_EXT, + GL_TEXTURE_MULTISAMPLE, GL_EXTCOUNT, // must be last }; diff --git a/ref_gl/gl_opengl.c b/ref_gl/gl_opengl.c index eb3025c9..a4420e83 100644 --- a/ref_gl/gl_opengl.c +++ b/ref_gl/gl_opengl.c @@ -249,6 +249,12 @@ static dllfunc_t vbofuncs[] = { NULL, NULL } }; +static dllfunc_t multisampletexfuncs[] = +{ + { GL_CALL(glTexImage2DMultisample) }, + { NULL, NULL } +}; + static dllfunc_t drawrangeelementsfuncs[] = { { GL_CALL( glDrawRangeElements ) }, @@ -714,6 +720,7 @@ void GL_InitExtensionsBigGL( void ) GL_CheckExtension( "GL_ARB_depth_buffer_float", NULL, "gl_texture_depth_float", GL_ARB_DEPTH_FLOAT_EXT ); GL_CheckExtension( "GL_EXT_gpu_shader4", NULL, NULL, GL_EXT_GPU_SHADER4 ); // don't confuse users GL_CheckExtension( "GL_ARB_vertex_buffer_object", vbofuncs, "gl_vertex_buffer_object", GL_ARB_VERTEX_BUFFER_OBJECT_EXT ); + GL_CheckExtension( "GL_ARB_texture_multisample", multisampletexfuncs, "gl_texture_multisample", GL_TEXTURE_MULTISAMPLE ); if( GL_CheckExtension( "GL_ARB_shading_language_100", NULL, NULL, GL_SHADER_GLSL100_EXT )) { pglGetIntegerv( GL_MAX_TEXTURE_COORDS_ARB, &glConfig.max_texture_coords );