1
0
Fork 0
forked from fte/fteqw

support for gl4 tesselation shaders. glsl code is available separately.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4786 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2014-11-05 05:39:24 +00:00
parent 98ec171f17
commit 5a33efb14e
11 changed files with 226 additions and 120 deletions

View file

@ -499,7 +499,7 @@ void M_Menu_Audio_f (void)
MB_SLIDER("Ambient Volume", ambient_level, 0, 1, 0.1, NULL), MB_SLIDER("Ambient Volume", ambient_level, 0, 1, 0.1, NULL),
MB_SLIDER("Ambient Fade", ambient_fade, 0, 1000, 1, NULL), MB_SLIDER("Ambient Fade", ambient_fade, 0, 1000, 1, NULL),
MB_CHECKBOXCVAR("Static Sounds", cl_staticsounds, 0), MB_CHECKBOXCVAR("Static Sounds", cl_staticsounds, 0),
MB_SLIDER("CD Music Volume", bgmvolume, 0, 1, 0.1, NULL), MB_SLIDER("Music Volume", bgmvolume, 0, 1, 0.1, NULL),
// removed music buffer // removed music buffer
// removed precache // removed precache
// removed eax2 // removed eax2

View file

@ -215,8 +215,8 @@ cvar_t vid_multisample = CVARF ("vid_multisample", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH); CVAR_ARCHIVE | CVAR_RENDERERLATCH);
cvar_t vid_refreshrate = CVARF ("vid_displayfrequency", "0", cvar_t vid_refreshrate = CVARF ("vid_displayfrequency", "0",
CVAR_ARCHIVE | CVAR_RENDERERLATCH); CVAR_ARCHIVE | CVAR_RENDERERLATCH);
cvar_t vid_srgb = CVARF ("vid_srgb", "0", cvar_t vid_srgb = CVARFD ("vid_srgb", "0",
CVAR_ARCHIVE); CVAR_ARCHIVE, "The framebuffer should use sRGB colourspace. This has the effect of brightening the screen");
cvar_t vid_wndalpha = CVAR ("vid_wndalpha", "1"); cvar_t vid_wndalpha = CVAR ("vid_wndalpha", "1");
//more readable defaults to match conwidth/conheight. //more readable defaults to match conwidth/conheight.
cvar_t vid_width = CVARFD ("vid_width", "0", cvar_t vid_width = CVARFD ("vid_width", "0",

View file

@ -895,11 +895,19 @@ void S_Voip_Transmit(unsigned char clc, sizebuf_t *buf)
/*if you're sending sound, you should be prepared to accept others yelling at you to shut up*/ /*if you're sending sound, you should be prepared to accept others yelling at you to shut up*/
if (snd_voip_play.value <= 0) if (snd_voip_play.value <= 0)
voipsendenable = false; voipsendenable = false;
/*don't send sound if its not supported. that'll break stuff*/
if (!(cls.fteprotocolextensions2 & PEXT2_VOICECHAT)) if (!(cls.fteprotocolextensions2 & PEXT2_VOICECHAT))
voipsendenable = false; voipsendenable = false;
} }
else else
{
/*we're not sending it to a server. the above considerations don't matter*/
voipsendenable = snd_voip_test.ival; voipsendenable = snd_voip_test.ival;
}
/*don't send sound if mic volume won't send anything anyway*/
if (micamp <= 0)
voipsendenable = false;
if (rtpstream) if (rtpstream)
{ {
voipsendenable = true; voipsendenable = true;

View file

@ -684,7 +684,7 @@ static shader_t *GL_ChooseSkin(galiasinfo_t *inf, model_t *model, int surfnum, e
(shader->defaulttextures.upperoverlay && (shader->defaulttextures.upperoverlay->status == TEX_LOADING || shader->defaulttextures.upperoverlay->status == TEX_LOADED))) (shader->defaulttextures.upperoverlay && (shader->defaulttextures.upperoverlay->status == TEX_LOADING || shader->defaulttextures.upperoverlay->status == TEX_LOADED)))
return shader; return shader;
} }
if (shader->prog && shader->prog->permu[PERMUTATION_UPPERLOWER].handle.glsl && !h2playertranslations) if (shader->prog && shader->prog->permu[PERMUTATION_UPPERLOWER].handle.glsl.handle && !h2playertranslations)
{ //this shader can do permutations. this means we can generate only a black image, with separate top+bottom textures. { //this shader can do permutations. this means we can generate only a black image, with separate top+bottom textures.
tc = 0xfe000000; tc = 0xfe000000;
bc = 0xfe000000; bc = 0xfe000000;
@ -1402,7 +1402,7 @@ void R_GAlias_DrawBatch(batch_t *batch)
{ {
if (batch->surf_first == surfnum) if (batch->surf_first == surfnum)
{ {
/*needrecolour =*/ Alias_GAliasBuildMesh(&mesh, &batch->vbo, inf, surfnum, e, batch->shader->prog && batch->shader->prog->permu[PERMUTATION_SKELETAL].handle.glsl); /*needrecolour =*/ Alias_GAliasBuildMesh(&mesh, &batch->vbo, inf, surfnum, e, batch->shader->prog && batch->shader->prog->permu[PERMUTATION_SKELETAL].handle.glsl.handle);
batch->mesh = &meshl; batch->mesh = &meshl;
return; return;
} }

View file

@ -81,7 +81,7 @@ struct {
const shader_t *crepopaqueshader; const shader_t *crepopaqueshader;
const shader_t *depthonlyshader; const shader_t *depthonlyshader;
GLhandleARB allblackshader; union programhandle_u allblackshader;
int allblack_mvp; int allblack_mvp;
qboolean initeddepthnorm; qboolean initeddepthnorm;
@ -99,6 +99,7 @@ struct {
texid_t tex_refractiondepth; /*the (culled) underwater view*/ texid_t tex_refractiondepth; /*the (culled) underwater view*/
texid_t tex_ripplemap; /*temp image for waves and things.*/ texid_t tex_ripplemap; /*temp image for waves and things.*/
int curpatchverts;
qboolean force2d; qboolean force2d;
int currenttmu; int currenttmu;
int blendmode[SHADER_TMU_MAX]; int blendmode[SHADER_TMU_MAX];
@ -209,6 +210,12 @@ static void BE_PolyOffset(qboolean pushdepth)
po.factor += r_polygonoffset_submodel_factor.value; po.factor += r_polygonoffset_submodel_factor.value;
po.unit += r_polygonoffset_submodel_offset.value; po.unit += r_polygonoffset_submodel_offset.value;
} }
if (shaderstate.mode == BEM_DEPTHONLY)
{
extern cvar_t r_polygonoffset_shadowmap_offset, r_polygonoffset_shadowmap_factor;
po.factor += r_polygonoffset_shadowmap_factor.value;
po.unit += r_polygonoffset_shadowmap_offset.value;
}
#ifndef FORCESTATE #ifndef FORCESTATE
if (shaderstate.curpolyoffset.factor != po.factor || shaderstate.curpolyoffset.unit != po.unit) if (shaderstate.curpolyoffset.factor != po.factor || shaderstate.curpolyoffset.unit != po.unit)
@ -861,19 +868,19 @@ void GLBE_RenderShadowBuffer(unsigned int numverts, int vbo, vecV_t *verts, unsi
GLBE_PolyOffsetShadowMap(false); GLBE_PolyOffsetShadowMap(false);
if (shaderstate.allblackshader) if (shaderstate.allblackshader.glsl.handle)
{ {
GL_SelectProgram(shaderstate.allblackshader); GL_SelectProgram(shaderstate.allblackshader.glsl.handle);
BE_EnableShaderAttributes(gl_config_nofixedfunc?(1u<<VATTR_VERTEX1):(1u<<VATTR_LEG_VERTEX), 0); BE_EnableShaderAttributes(gl_config_nofixedfunc?(1u<<VATTR_VERTEX1):(1u<<VATTR_LEG_VERTEX), 0);
if (shaderstate.allblackshader != shaderstate.lastuniform && shaderstate.allblack_mvp != -1) if (shaderstate.allblackshader.glsl.handle != shaderstate.lastuniform && shaderstate.allblack_mvp != -1)
{ {
float m16[16]; float m16[16];
Matrix4_Multiply(r_refdef.m_projection, shaderstate.modelviewmatrix, m16); Matrix4_Multiply(r_refdef.m_projection, shaderstate.modelviewmatrix, m16);
qglUniformMatrix4fvARB(shaderstate.allblack_mvp, 1, false, m16); qglUniformMatrix4fvARB(shaderstate.allblack_mvp, 1, false, m16);
} }
shaderstate.lastuniform = shaderstate.allblackshader; shaderstate.lastuniform = shaderstate.allblackshader.glsl.handle;
GL_SelectEBO(ibo); GL_SelectEBO(ibo);
qglDrawRangeElements(GL_TRIANGLES, 0, numverts, numindicies, GL_INDEX_TYPE, indicies); qglDrawRangeElements(GL_TRIANGLES, 0, numverts, numindicies, GL_INDEX_TYPE, indicies);
@ -2694,12 +2701,27 @@ static void BE_SendPassBlendDepthMask(unsigned int sbits)
#endif #endif
} }
static void BE_SubmitMeshChain(void) #define GL_PATCHES_ARB 0xe
static void BE_SubmitMeshChain(qboolean usetesselation)
{ {
int startv, starti, endv, endi; int startv, starti, endv, endi;
int m; int m;
mesh_t *mesh; mesh_t *mesh;
int batchtype = (shaderstate.flags & BEF_LINES)?GL_LINES:GL_TRIANGLES; int batchtype;
if (usetesselation)
{
m = (shaderstate.flags & BEF_LINES)?2:3;
if (shaderstate.curpatchverts != m)
{
shaderstate.curpatchverts = m;
#define GL_PATCH_VERTICES 0x8E72
qglPatchParameteriARB(GL_PATCH_VERTICES, m);
}
batchtype = GL_PATCHES_ARB;
}
else
batchtype = (shaderstate.flags & BEF_LINES)?GL_LINES:GL_TRIANGLES;
if (!shaderstate.streamvbo[0]) //only if we're not forcing vbos elsewhere. if (!shaderstate.streamvbo[0]) //only if we're not forcing vbos elsewhere.
{ {
@ -2866,7 +2888,7 @@ static void DrawPass(const shaderpass_t *pass)
/*push it*/ /*push it*/
BE_EnableShaderAttributes(attr, 0); BE_EnableShaderAttributes(attr, 0);
BE_SubmitMeshChain(); BE_SubmitMeshChain(false);
tmu = 0; tmu = 0;
/*bind the light texture*/ /*bind the light texture*/
@ -2905,7 +2927,7 @@ static void DrawPass(const shaderpass_t *pass)
shaderstate.lastpasstmus = tmu; shaderstate.lastpasstmus = tmu;
BE_EnableShaderAttributes(attr, 0); BE_EnableShaderAttributes(attr, 0);
BE_SubmitMeshChain(); BE_SubmitMeshChain(false);
tmu = 0; tmu = 0;
BE_SendPassBlendDepthMask(pass[i+1].shaderbits); BE_SendPassBlendDepthMask(pass[i+1].shaderbits);
@ -2924,7 +2946,7 @@ static void DrawPass(const shaderpass_t *pass)
shaderstate.lastpasstmus = tmu; shaderstate.lastpasstmus = tmu;
BE_EnableShaderAttributes(attr, 0); BE_EnableShaderAttributes(attr, 0);
BE_SubmitMeshChain(); BE_SubmitMeshChain(false);
} }
#endif #endif
@ -3264,37 +3286,37 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas
perm = 0; perm = 0;
if (shaderstate.sourcevbo->numbones) if (shaderstate.sourcevbo->numbones)
{ {
if (p->permu[perm|PERMUTATION_SKELETAL].handle.glsl) if (p->permu[perm|PERMUTATION_SKELETAL].handle.glsl.handle)
perm |= PERMUTATION_SKELETAL; perm |= PERMUTATION_SKELETAL;
else else
return; return;
} }
if (p->permu[perm|PERMUTATION_FRAMEBLEND].handle.glsl && shaderstate.sourcevbo->coord2.gl.addr) if (p->permu[perm|PERMUTATION_FRAMEBLEND].handle.glsl.handle && shaderstate.sourcevbo->coord2.gl.addr)
perm |= PERMUTATION_FRAMEBLEND; perm |= PERMUTATION_FRAMEBLEND;
if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].handle.glsl) if (TEXLOADED(shaderstate.curtexnums->bump) && p->permu[perm|PERMUTATION_BUMPMAP].handle.glsl.handle)
perm |= PERMUTATION_BUMPMAP; perm |= PERMUTATION_BUMPMAP;
if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].handle.glsl) if (TEXLOADED(shaderstate.curtexnums->fullbright) && p->permu[perm|PERMUTATION_FULLBRIGHT].handle.glsl.handle)
perm |= PERMUTATION_FULLBRIGHT; perm |= PERMUTATION_FULLBRIGHT;
if ((TEXLOADED(shaderstate.curtexnums->loweroverlay) || TEXLOADED(shaderstate.curtexnums->upperoverlay)) && p->permu[perm|PERMUTATION_UPPERLOWER].handle.glsl) if ((TEXLOADED(shaderstate.curtexnums->loweroverlay) || TEXLOADED(shaderstate.curtexnums->upperoverlay)) && p->permu[perm|PERMUTATION_UPPERLOWER].handle.glsl.handle)
perm |= PERMUTATION_UPPERLOWER; perm |= PERMUTATION_UPPERLOWER;
if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].handle.glsl) if (r_refdef.globalfog.density && p->permu[perm|PERMUTATION_FOG].handle.glsl.handle)
perm |= PERMUTATION_FOG; perm |= PERMUTATION_FOG;
if (p->permu[perm|PERMUTATION_DELUXE].handle.glsl && TEXLOADED(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe) if (p->permu[perm|PERMUTATION_DELUXE].handle.glsl.handle && TEXLOADED(shaderstate.curtexnums->bump) && shaderstate.curbatch->lightmap[0] >= 0 && lightmap[shaderstate.curbatch->lightmap[0]]->hasdeluxe)
perm |= PERMUTATION_DELUXE; perm |= PERMUTATION_DELUXE;
#if MAXRLIGHTMAPS > 1 #if MAXRLIGHTMAPS > 1
if (shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].handle.glsl) if (shaderstate.curbatch->lightmap[1] >= 0 && p->permu[perm|PERMUTATION_LIGHTSTYLES].handle.glsl.handle)
perm |= PERMUTATION_LIGHTSTYLES; perm |= PERMUTATION_LIGHTSTYLES;
#endif #endif
GL_SelectProgram(p->permu[perm].handle.glsl); GL_SelectProgram(p->permu[perm].handle.glsl.handle);
#ifndef FORCESTATE #ifndef FORCESTATE
if (shaderstate.lastuniform == p->permu[perm].handle.glsl) if (shaderstate.lastuniform == p->permu[perm].handle.glsl.handle)
i = true; i = true;
else else
#endif #endif
{ {
i = false; i = false;
shaderstate.lastuniform = p->permu[perm].handle.glsl; shaderstate.lastuniform = p->permu[perm].handle.glsl.handle;
} }
BE_Program_Set_Attributes(p, perm, i); BE_Program_Set_Attributes(p, perm, i);
@ -3347,7 +3369,7 @@ static void BE_RenderMeshProgram(const shader_t *shader, const shaderpass_t *pas
shaderstate.lastpasstmus = pass->numMergedPasses; shaderstate.lastpasstmus = pass->numMergedPasses;
} }
} }
BE_SubmitMeshChain(); BE_SubmitMeshChain(p->permu[perm].handle.glsl.usetesselation);
} }
qboolean GLBE_LightCullModel(vec3_t org, model_t *model) qboolean GLBE_LightCullModel(vec3_t org, model_t *model)
@ -3408,11 +3430,11 @@ void GLBE_SelectMode(backendmode_t mode)
} }
else else
#endif #endif
if (!shaderstate.allblackshader) if (!shaderstate.allblackshader.glsl.handle)
{ {
const char *defs[] = {NULL}; const char *defs[] = {NULL};
shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL); shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", NULL, NULL, "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL);
shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader, "m_modelviewprojection"); shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader.glsl.handle, "m_modelviewprojection");
} }
/*BEM_DEPTHONLY does support mesh writing, but its not the only way its used... FIXME!*/ /*BEM_DEPTHONLY does support mesh writing, but its not the only way its used... FIXME!*/
while(shaderstate.lastpasstmus>0) while(shaderstate.lastpasstmus>0)
@ -3433,11 +3455,11 @@ void GLBE_SelectMode(backendmode_t mode)
/*BEM_STENCIL doesn't support mesh writing*/ /*BEM_STENCIL doesn't support mesh writing*/
GLBE_PolyOffsetStencilShadow(false); GLBE_PolyOffsetStencilShadow(false);
if (gl_config_nofixedfunc && !shaderstate.allblackshader) if (gl_config_nofixedfunc && !shaderstate.allblackshader.glsl.handle)
{ {
const char *defs[] = {NULL}; const char *defs[] = {NULL};
shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL); shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", NULL, NULL, "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL);
shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader, "m_modelviewprojection"); shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader.glsl.handle, "m_modelviewprojection");
} }
//disable all tmus //disable all tmus
@ -3784,7 +3806,7 @@ static void BE_LegacyLighting(void)
GL_DeSelectProgram(); GL_DeSelectProgram();
BE_EnableShaderAttributes(attr, 0); BE_EnableShaderAttributes(attr, 0);
BE_SubmitMeshChain(); BE_SubmitMeshChain(false);
GL_LazyBind(1, 0, r_nulltex); GL_LazyBind(1, 0, r_nulltex);
GL_LazyBind(2, 0, r_nulltex); GL_LazyBind(2, 0, r_nulltex);
@ -3904,7 +3926,7 @@ static void DrawMeshes(void)
#pragma warningmsg("fixme: support alpha test") #pragma warningmsg("fixme: support alpha test")
#endif #endif
BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX), 0); BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX), 0);
BE_SubmitMeshChain(); BE_SubmitMeshChain(false); //fixme: dangerous
} }
break; break;
@ -3914,7 +3936,7 @@ static void DrawMeshes(void)
GenerateTCFog(0, NULL); GenerateTCFog(0, NULL);
BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX), 0); BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX), 0);
BE_SubmitMeshChain(); BE_SubmitMeshChain(false);
#endif #endif
break; break;
@ -3943,32 +3965,32 @@ static void DrawMeshes(void)
BE_SendPassBlendDepthMask((shaderstate.curshader->passes[0].shaderbits & ~SBITS_BLEND_BITS) | SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | SBITS_MISC_NODEPTHTEST); BE_SendPassBlendDepthMask((shaderstate.curshader->passes[0].shaderbits & ~SBITS_BLEND_BITS) | SBITS_SRCBLEND_SRC_ALPHA | SBITS_DSTBLEND_ONE_MINUS_SRC_ALPHA | SBITS_MISC_NODEPTHTEST);
BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR), 0); BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR), 0);
BE_SubmitMeshChain(); BE_SubmitMeshChain(false);
break; break;
case BEM_DEPTHDARK: case BEM_DEPTHDARK:
if ((shaderstate.curshader->flags & SHADER_HASLIGHTMAP) && !TEXVALID(shaderstate.curtexnums->fullbright)) if ((shaderstate.curshader->flags & SHADER_HASLIGHTMAP) && !TEXVALID(shaderstate.curtexnums->fullbright))
{ {
if (gl_config.arb_shader_objects) if (gl_config.arb_shader_objects)
{ {
if (!shaderstate.allblackshader) if (!shaderstate.allblackshader.glsl.handle)
{ {
const char *defs[] = {NULL}; const char *defs[] = {NULL};
shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL); shaderstate.allblackshader = GLSlang_CreateProgram("allblackprogram", gl_config_gles?100:110, defs, "#include \"sys/skeletal.h\"\nvoid main(){gl_Position = skeletaltransform();}", NULL, NULL, "void main(){gl_FragColor=vec4(0.0,0.0,0.0,1.0);}", false, NULL);
shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader, "m_modelviewprojection"); shaderstate.allblack_mvp = qglGetUniformLocationARB(shaderstate.allblackshader.glsl.handle, "m_modelviewprojection");
} }
GL_SelectProgram(shaderstate.allblackshader); GL_SelectProgram(shaderstate.allblackshader.glsl.handle);
BE_SendPassBlendDepthMask(shaderstate.curshader->passes[0].shaderbits); BE_SendPassBlendDepthMask(shaderstate.curshader->passes[0].shaderbits);
BE_EnableShaderAttributes(gl_config_nofixedfunc?(1u<<VATTR_VERTEX1):(1u<<VATTR_LEG_VERTEX), 0); BE_EnableShaderAttributes(gl_config_nofixedfunc?(1u<<VATTR_VERTEX1):(1u<<VATTR_LEG_VERTEX), 0);
if (shaderstate.allblackshader != shaderstate.lastuniform && shaderstate.allblack_mvp != -1) if (shaderstate.allblackshader.glsl.handle != shaderstate.lastuniform && shaderstate.allblack_mvp != -1)
{ {
float m16[16]; float m16[16];
Matrix4_Multiply(r_refdef.m_projection, shaderstate.modelviewmatrix, m16); Matrix4_Multiply(r_refdef.m_projection, shaderstate.modelviewmatrix, m16);
qglUniformMatrix4fvARB(shaderstate.allblack_mvp, 1, false, m16); qglUniformMatrix4fvARB(shaderstate.allblack_mvp, 1, false, m16);
} }
BE_SubmitMeshChain(); BE_SubmitMeshChain(shaderstate.allblackshader.glsl.usetesselation);
shaderstate.lastuniform = shaderstate.allblackshader; shaderstate.lastuniform = shaderstate.allblackshader.glsl.handle;
break; break;
} }
#ifndef GLSLONLY #ifndef GLSLONLY
@ -3987,7 +4009,7 @@ static void DrawMeshes(void)
BE_SendPassBlendDepthMask(shaderstate.curshader->passes[0].shaderbits); BE_SendPassBlendDepthMask(shaderstate.curshader->passes[0].shaderbits);
BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR), 0); BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR), 0);
BE_SubmitMeshChain(); BE_SubmitMeshChain(false);
break; break;
} }
#endif #endif
@ -4039,7 +4061,7 @@ static void DrawMeshes(void)
GenerateTCFog(0, shaderstate.curbatch->fog); GenerateTCFog(0, shaderstate.curbatch->fog);
BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR) | (1u<<VATTR_LEG_TMU0), 0); BE_EnableShaderAttributes((1u<<VATTR_LEG_VERTEX) | (1u<<VATTR_LEG_COLOUR) | (1u<<VATTR_LEG_TMU0), 0);
BE_SubmitMeshChain(); BE_SubmitMeshChain(false);
} }
break; break;
#endif #endif

View file

@ -78,19 +78,19 @@ static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int
{ {
vbo->indicies.gl.vbo = vbos[1]; vbo->indicies.gl.vbo = vbos[1];
vbo->indicies.gl.addr = (index_t*)((char*)vbo->indicies.gl.addr - (char*)edata); vbo->indicies.gl.addr = (index_t*)((char*)vbo->indicies.gl.addr - (char*)edata);
vaostatic |= VATTR_LEG_ELEMENTS; vaostatic |= 1u<<VATTR_LEG_ELEMENTS;
} }
if (vbo->coord.gl.addr) if (vbo->coord.gl.addr)
{ {
vbo->coord.gl.vbo = vbos[0]; vbo->coord.gl.vbo = vbos[0];
vbo->coord.gl.addr = (vecV_t*)((char*)vbo->coord.gl.addr - (char*)vdata); vbo->coord.gl.addr = (vecV_t*)((char*)vbo->coord.gl.addr - (char*)vdata);
vaostatic |= VATTR_VERTEX1; vaostatic |= 1u<<VATTR_VERTEX1;
} }
if (vbo->texcoord.gl.addr) if (vbo->texcoord.gl.addr)
{ {
vbo->texcoord.gl.vbo = vbos[0]; vbo->texcoord.gl.vbo = vbos[0];
vbo->texcoord.gl.addr = (vec2_t*)((char*)vbo->texcoord.gl.addr - (char*)vdata); vbo->texcoord.gl.addr = (vec2_t*)((char*)vbo->texcoord.gl.addr - (char*)vdata);
vaostatic |= VATTR_TEXCOORD; vaostatic |= 1u<<VATTR_TEXCOORD;
} }
for (s = 0; s < MAXRLIGHTMAPS; s++) for (s = 0; s < MAXRLIGHTMAPS; s++)
{ {
@ -100,11 +100,11 @@ static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int
vbo->colours[s].gl.addr = (vec4_t*)((char*)vbo->colours[s].gl.addr - (char*)vdata); vbo->colours[s].gl.addr = (vec4_t*)((char*)vbo->colours[s].gl.addr - (char*)vdata);
switch(s) switch(s)
{ {
default: vaostatic |= VATTR_COLOUR; break; default: vaostatic |= 1u<<VATTR_COLOUR; break;
#if MAXRLIGHTMAPS > 1 #if MAXRLIGHTMAPS > 1
case 1: vaostatic |= VATTR_COLOUR2; break; case 1: vaostatic |= 1u<<VATTR_COLOUR2; break;
case 2: vaostatic |= VATTR_COLOUR3; break; case 2: vaostatic |= 1u<<VATTR_COLOUR3; break;
case 3: vaostatic |= VATTR_COLOUR4; break; case 3: vaostatic |= 1u<<VATTR_COLOUR4; break;
#endif #endif
} }
} }
@ -114,11 +114,11 @@ static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int
vbo->lmcoord[s].gl.addr = (vec2_t*)((char*)vbo->lmcoord[s].gl.addr - (char*)vdata); vbo->lmcoord[s].gl.addr = (vec2_t*)((char*)vbo->lmcoord[s].gl.addr - (char*)vdata);
switch(s) switch(s)
{ {
default: vaostatic |= VATTR_LMCOORD; break; default: vaostatic |= 1u<<VATTR_LMCOORD; break;
#if MAXRLIGHTMAPS > 1 #if MAXRLIGHTMAPS > 1
case 1: vaostatic |= VATTR_LMCOORD2; break; case 1: vaostatic |= 1u<<VATTR_LMCOORD2; break;
case 2: vaostatic |= VATTR_LMCOORD3; break; case 2: vaostatic |= 1u<<VATTR_LMCOORD3; break;
case 3: vaostatic |= VATTR_LMCOORD4; break; case 3: vaostatic |= 1u<<VATTR_LMCOORD4; break;
#endif #endif
} }
} }
@ -127,19 +127,19 @@ static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int
{ {
vbo->normals.gl.vbo = vbos[0]; vbo->normals.gl.vbo = vbos[0];
vbo->normals.gl.addr = (vec3_t*)((char*)vbo->normals.gl.addr - (char*)vdata); vbo->normals.gl.addr = (vec3_t*)((char*)vbo->normals.gl.addr - (char*)vdata);
vaostatic |= VATTR_NORMALS; vaostatic |= 1u<<VATTR_NORMALS;
} }
if (vbo->svector.gl.addr) if (vbo->svector.gl.addr)
{ {
vbo->svector.gl.vbo = vbos[0]; vbo->svector.gl.vbo = vbos[0];
vbo->svector.gl.addr = (vec3_t*)((char*)vbo->svector.gl.addr - (char*)vdata); vbo->svector.gl.addr = (vec3_t*)((char*)vbo->svector.gl.addr - (char*)vdata);
vaostatic |= VATTR_SNORMALS; vaostatic |= 1u<<VATTR_SNORMALS;
} }
if (vbo->tvector.gl.addr) if (vbo->tvector.gl.addr)
{ {
vbo->tvector.gl.vbo = vbos[0]; vbo->tvector.gl.vbo = vbos[0];
vbo->tvector.gl.addr = (vec3_t*)((char*)vbo->tvector.gl.addr - (char*)vdata); vbo->tvector.gl.addr = (vec3_t*)((char*)vbo->tvector.gl.addr - (char*)vdata);
vaostatic |= VATTR_TNORMALS; vaostatic |= 1u<<VATTR_TNORMALS;
} }

View file

@ -1783,11 +1783,11 @@ static void Shader_ProgramParam ( shader_t *shader, shaderpass_t *pass, char **p
prog->parm[prog->numparams].type = parmtype; prog->parm[prog->numparams].type = parmtype;
for (p = 0; p < PERMUTATIONS; p++) for (p = 0; p < PERMUTATIONS; p++)
{ {
if (!prog->permu[p].handle.glsl) if (!prog->permu[p].handle.glsl.handle)
continue; continue;
GLSlang_UseProgram(prog->permu[p].handle.glsl); GLSlang_UseProgram(prog->permu[p].handle.glsl.handle);
uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl, token); uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl.handle, token);
prog->permu[p].parm[prog->numparams] = uniformloc; prog->permu[p].parm[prog->numparams] = uniformloc;
if (uniformloc != -1) if (uniformloc != -1)

View file

@ -220,6 +220,8 @@ int mtexid0;
FTEPFNGLPNTRIANGLESIATIPROC qglPNTrianglesiATI; FTEPFNGLPNTRIANGLESIATIPROC qglPNTrianglesiATI;
FTEPFNGLPNTRIANGLESFATIPROC qglPNTrianglesfATI; FTEPFNGLPNTRIANGLESFATIPROC qglPNTrianglesfATI;
void (APIENTRY *qglPatchParameteriARB)(GLenum pname, GLint value); //core in gl4
//stencil shadowing //stencil shadowing
FTEPFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT; FTEPFNGLACTIVESTENCILFACEEXTPROC qglActiveStencilFaceEXT;
@ -742,6 +744,13 @@ void GL_CheckExtensions (void *(*getglfunction) (char *name))
qglPNTrianglesfATI = (void *)getglext("glPNTrianglesfATI"); qglPNTrianglesfATI = (void *)getglext("glPNTrianglesfATI");
qglPNTrianglesiATI = (void *)getglext("glPNTrianglesiATI"); qglPNTrianglesiATI = (void *)getglext("glPNTrianglesiATI");
} }
if (!gl_config.gles && gl_config.glversion >= 4.0)
qglPatchParameteriARB = getglext("glPatchParameteri");
else if (GL_CheckExtension("GL_ARB_tessellation_shader"))
qglPatchParameteriARB = getglext("glPatchParameteriARB");
else
qglPatchParameteriARB = NULL;
#ifndef GL_STATIC #ifndef GL_STATIC
if (GL_CheckExtension("GL_EXT_texture_object")) if (GL_CheckExtension("GL_EXT_texture_object"))
@ -1207,9 +1216,12 @@ static const char *glsl_hdrs[] =
"uniform float cvar_r_glsl_offsetmapping_scale;\n" "uniform float cvar_r_glsl_offsetmapping_scale;\n"
"vec2 offsetmap(sampler2D normtex, vec2 base, vec3 eyevector)\n" "vec2 offsetmap(sampler2D normtex, vec2 base, vec3 eyevector)\n"
"{\n" "{\n"
"#if !defined(OFFSETMAPPING_SCALE)\n"
"#define OFFSETMAPPING_SCALE 1.0\n"
"#endif\n"
"#if defined(RELIEFMAPPING) && !defined(GL_ES)\n" "#if defined(RELIEFMAPPING) && !defined(GL_ES)\n"
"float i, f;\n" "float i, f;\n"
"vec3 OffsetVector = vec3(normalize(eyevector.xyz).xy * cvar_r_glsl_offsetmapping_scale * vec2(-1.0, 1.0), -1.0);\n" "vec3 OffsetVector = vec3(normalize(eyevector.xyz).xy * cvar_r_glsl_offsetmapping_scale * OFFSETMAPPING_SCALE * vec2(-1.0, 1.0), -1.0);\n"
"vec3 RT = vec3(vec2(base.xy"/* - OffsetVector.xy*OffsetMapping_Bias*/"), 1.0);\n" "vec3 RT = vec3(vec2(base.xy"/* - OffsetVector.xy*OffsetMapping_Bias*/"), 1.0);\n"
"OffsetVector /= 10.0;\n" "OffsetVector /= 10.0;\n"
"for(i = 1.0; i < 10.0; ++i)\n" "for(i = 1.0; i < 10.0; ++i)\n"
@ -1218,7 +1230,7 @@ static const char *glsl_hdrs[] =
"RT += OffsetVector * (step(texture2D(normtex, RT.xy).a, RT.z) * f - 0.5 * f);\n" "RT += OffsetVector * (step(texture2D(normtex, RT.xy).a, RT.z) * f - 0.5 * f);\n"
"return RT.xy;\n" "return RT.xy;\n"
"#elif defined(OFFSETMAPPING)\n" "#elif defined(OFFSETMAPPING)\n"
"vec2 OffsetVector = normalize(eyevector).xy * cvar_r_glsl_offsetmapping_scale * vec2(-1.0, 1.0);\n" "vec2 OffsetVector = normalize(eyevector).xy * cvar_r_glsl_offsetmapping_scale * OFFSETMAPPING_SCALE * vec2(-1.0, 1.0);\n"
"vec2 tc = base;\n" "vec2 tc = base;\n"
"tc += OffsetVector;\n" "tc += OffsetVector;\n"
"OffsetVector *= 0.333;\n" "OffsetVector *= 0.333;\n"
@ -1426,6 +1438,9 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char *
int strings = 0; int strings = 0;
char verline[64]; char verline[64];
if (!shadersource)
return 0;
if (ver) if (ver)
{ {
/*required version not supported, don't even try*/ /*required version not supported, don't even try*/
@ -1471,6 +1486,16 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char *
strings++; strings++;
} }
break; break;
case GL_TESS_CONTROL_SHADER_ARB:
prstrings[strings] = "#define TESS_CONTROL_SHADER\n";
length[strings] = strlen(prstrings[strings]);
strings++;
break;
case GL_TESS_EVALUATION_SHADER_ARB:
prstrings[strings] = "#define TESS_EVALUATION_SHADER\n";
length[strings] = strlen(prstrings[strings]);
strings++;
break;
case GL_VERTEX_SHADER_ARB: case GL_VERTEX_SHADER_ARB:
prstrings[strings] = "#define VERTEX_SHADER\n"; prstrings[strings] = "#define VERTEX_SHADER\n";
length[strings] = strlen(prstrings[strings]); length[strings] = strlen(prstrings[strings]);
@ -1487,12 +1512,28 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char *
length[strings] = strlen(prstrings[strings]); length[strings] = strlen(prstrings[strings]);
strings++; strings++;
} }
if (gl_config.nofixedfunc) if (ver < 140)
{ {
prstrings[strings] = prstrings[strings] =
"attribute vec3 v_position1;\n" "#define in attribute\n"
"#define out varying\n"
;
}
else
{
prstrings[strings] =
"#define attribute in\n"
"#define varying out\n"
;
length[strings] = strlen(prstrings[strings]);
strings++;
}
if (gl_config.nofixedfunc || ver >= 140)
{
prstrings[strings] =
"in vec3 v_position1;\n"
"#ifdef FRAMEBLEND\n" "#ifdef FRAMEBLEND\n"
"attribute vec3 v_position2;\n" "in vec3 v_position2;\n"
"uniform vec2 e_vblend;\n" "uniform vec2 e_vblend;\n"
"#define v_position ((v_position1*e_vblend.x)+(v_position2*e_vblend.y))\n" "#define v_position ((v_position1*e_vblend.x)+(v_position2*e_vblend.y))\n"
"#else\n" "#else\n"
@ -1509,7 +1550,7 @@ static GLhandleARB GLSlang_CreateShader (const char *name, int ver, const char *
{ {
prstrings[strings] = prstrings[strings] =
"#ifdef FRAMEBLEND\n" "#ifdef FRAMEBLEND\n"
"attribute vec3 v_position2;\n" "in vec3 v_position2;\n"
"uniform vec2 e_vblend;\n" "uniform vec2 e_vblend;\n"
"#define v_position (gl_Vertex.xyz*e_vblend.x+v_position2*e_vblend.y)\n" "#define v_position (gl_Vertex.xyz*e_vblend.x+v_position2*e_vblend.y)\n"
"uniform mat4 m_modelviewprojection;\n" "uniform mat4 m_modelviewprojection;\n"
@ -1593,6 +1634,12 @@ static GLhandleARB GLSlang_FinishShader(GLhandleARB shader, const char *name, GL
case GL_VERTEX_SHADER_ARB: case GL_VERTEX_SHADER_ARB:
typedesc = "Vertex"; typedesc = "Vertex";
break; break;
case GL_TESS_CONTROL_SHADER_ARB:
typedesc = "Tesselation Control";
break;
case GL_TESS_EVALUATION_SHADER_ARB:
typedesc = "Tesselation Evaluation";
break;
default: default:
typedesc = "???"; typedesc = "???";
break; break;
@ -1633,13 +1680,15 @@ static GLhandleARB GLSlang_FinishShader(GLhandleARB shader, const char *name, GL
return shader; return shader;
} }
GLhandleARB GLSlang_CreateProgramObject (const char *name, GLhandleARB vert, GLhandleARB frag, qboolean silent) GLhandleARB GLSlang_CreateProgramObject (const char *name, GLhandleARB vert, GLhandleARB cont, GLhandleARB eval, GLhandleARB frag, qboolean silent)
{ {
GLhandleARB program; GLhandleARB program;
program = qglCreateProgramObjectARB(); program = qglCreateProgramObjectARB();
qglAttachObjectARB(program, vert); if (vert) qglAttachObjectARB(program, vert);
qglAttachObjectARB(program, frag); if (cont) qglAttachObjectARB(program, cont);
if (eval) qglAttachObjectARB(program, eval);
if (frag) qglAttachObjectARB(program, frag);
qglBindAttribLocationARB(program, VATTR_VERTEX1, "v_position1"); qglBindAttribLocationARB(program, VATTR_VERTEX1, "v_position1");
qglBindAttribLocationARB(program, VATTR_COLOUR, "v_colour"); qglBindAttribLocationARB(program, VATTR_COLOUR, "v_colour");
@ -1666,108 +1715,124 @@ GLhandleARB GLSlang_CreateProgramObject (const char *name, GLhandleARB vert, GLh
return program; return program;
} }
GLhandleARB GLSlang_ValidateProgram(GLhandleARB program, const char *name, qboolean silent, vfsfile_t *blobfile) qboolean GLSlang_ValidateProgram(union programhandle_u *h, const char *name, qboolean silent, vfsfile_t *blobfile)
{ {
char str[2048]; char str[2048];
char *nullconstants = NULL; char *nullconstants = NULL;
GLint linked; GLint linked;
if (!program) if (!h->glsl.handle)
return (GLhandleARB)0; return false;
qglGetProgramParameteriv_(program, GL_OBJECT_LINK_STATUS_ARB, &linked); qglGetProgramParameteriv_(h->glsl.handle, GL_OBJECT_LINK_STATUS_ARB, &linked);
if(!linked) if(!linked)
{ {
if (!silent) if (!silent)
{ {
qglGetProgramInfoLog_(program, sizeof(str), NULL, str); qglGetProgramInfoLog_(h->glsl.handle, sizeof(str), NULL, str);
Con_Printf("Program link error on glsl program %s:\n%s\n", name, str); Con_Printf("Program link error on glsl program %s:\n%s\n", name, str);
} }
qglDeleteProgramObject_(program); qglDeleteProgramObject_(h->glsl.handle);
h->glsl.handle = 0;
return (GLhandleARB)0; return (GLhandleARB)0;
} }
if (program && blobfile && qglGetProgramBinary) if (h->glsl.handle && blobfile && qglGetProgramBinary)
{ {
GLuint ui; GLuint ui;
GLenum e; GLenum e;
unsigned int len, fmt; unsigned int len, fmt;
void *blobdata; void *blobdata;
qglGetProgramParameteriv_(program, GL_PROGRAM_BINARY_LENGTH, &ui); qglGetProgramParameteriv_(h->glsl.handle, GL_PROGRAM_BINARY_LENGTH, &ui);
len = ui; len = ui;
blobdata = BZ_Malloc(len); blobdata = BZ_Malloc(len);
qglGetProgramBinary(program, len, NULL, &e, blobdata); qglGetProgramBinary(h->glsl.handle, len, NULL, &e, blobdata);
fmt = e; fmt = e;
VFS_WRITE(blobfile, &fmt, sizeof(fmt)); VFS_WRITE(blobfile, &fmt, sizeof(fmt));
VFS_WRITE(blobfile, &len, sizeof(len)); VFS_WRITE(blobfile, &len, sizeof(len));
VFS_WRITE(blobfile, blobdata, len); VFS_WRITE(blobfile, blobdata, len);
VFS_WRITE(blobfile, &h->glsl.usetesselation, sizeof(h->glsl.usetesselation));
BZ_Free(blobdata); BZ_Free(blobdata);
} }
return program; return true;
} }
GLhandleARB GLSlang_CreateProgram(const char *name, int ver, const char **precompilerconstants, const char *vert, const char *frag, qboolean silent, vfsfile_t *blobfile) union programhandle_u GLSlang_CreateProgram(const char *name, int ver, const char **precompilerconstants, const char *vert, const char *cont, const char *eval, const char *frag, qboolean silent, vfsfile_t *blobfile)
{ {
GLhandleARB handle; union programhandle_u ret;
GLhandleARB vs; GLhandleARB vs;
GLhandleARB fs; GLhandleARB fs;
GLhandleARB cs;
GLhandleARB es;
const char *nullconstants = NULL; const char *nullconstants = NULL;
memset(&ret, 0, sizeof(ret));
if (!gl_config.arb_shader_objects) if (!gl_config.arb_shader_objects)
return 0; return ret;
if ((cont || frag) && !qglPatchParameteriARB)
return ret;
if (!precompilerconstants) if (!precompilerconstants)
precompilerconstants = &nullconstants; precompilerconstants = &nullconstants;
fs = GLSlang_CreateShader(name, ver, precompilerconstants, frag, GL_FRAGMENT_SHADER_ARB, silent); fs = GLSlang_CreateShader(name, ver, precompilerconstants, frag, GL_FRAGMENT_SHADER_ARB, silent);
vs = GLSlang_CreateShader(name, ver, precompilerconstants, vert, GL_VERTEX_SHADER_ARB, silent); vs = GLSlang_CreateShader(name, ver, precompilerconstants, vert, GL_VERTEX_SHADER_ARB, silent);
cs = GLSlang_CreateShader(name, ver, precompilerconstants, cont, GL_TESS_CONTROL_SHADER_ARB, silent);
es = GLSlang_CreateShader(name, ver, precompilerconstants, eval, GL_TESS_EVALUATION_SHADER_ARB, silent);
fs = GLSlang_FinishShader(fs, name, GL_FRAGMENT_SHADER_ARB, silent); fs = GLSlang_FinishShader(fs, name, GL_FRAGMENT_SHADER_ARB, silent);
vs = GLSlang_FinishShader(vs, name, GL_VERTEX_SHADER_ARB, silent); vs = GLSlang_FinishShader(vs, name, GL_VERTEX_SHADER_ARB, silent);
cs = GLSlang_FinishShader(cs, name, GL_TESS_CONTROL_SHADER_ARB, silent);
es = GLSlang_FinishShader(es, name, GL_TESS_EVALUATION_SHADER_ARB, silent);
if (!vs || !fs) if (!vs || !fs)
handle = 0; ret.glsl.handle = 0;
else else
handle = GLSlang_CreateProgramObject(name, vs, fs, silent); ret.glsl.handle = GLSlang_CreateProgramObject(name, vs, cs, es, fs, silent);
//delete ignores 0s. //delete ignores 0s.
qglDeleteShaderObject_(vs); if (vs) qglDeleteShaderObject_(vs);
qglDeleteShaderObject_(fs); if (fs) qglDeleteShaderObject_(fs);
if (cs) qglDeleteShaderObject_(cs);
if (es) qglDeleteShaderObject_(es);
checkglerror(); checkglerror();
if (handle && blobfile && qglGetProgramBinary) if (ret.glsl.handle && blobfile && qglGetProgramBinary)
{ {
GLuint ui; GLuint ui;
GLenum e; GLenum e;
unsigned int len, fmt; unsigned int len, fmt;
void *blobdata; void *blobdata;
qglGetProgramParameteriv_(handle, GL_PROGRAM_BINARY_LENGTH, &ui); qglGetProgramParameteriv_(ret.glsl.handle, GL_PROGRAM_BINARY_LENGTH, &ui);
len = ui; len = ui;
blobdata = BZ_Malloc(len); blobdata = BZ_Malloc(len);
qglGetProgramBinary(handle, len, NULL, &e, blobdata); qglGetProgramBinary(ret.glsl.handle, len, NULL, &e, blobdata);
fmt = e; fmt = e;
VFS_WRITE(blobfile, &fmt, sizeof(fmt)); VFS_WRITE(blobfile, &fmt, sizeof(fmt));
VFS_WRITE(blobfile, &len, sizeof(len)); VFS_WRITE(blobfile, &len, sizeof(len));
VFS_WRITE(blobfile, blobdata, len); VFS_WRITE(blobfile, blobdata, len);
VFS_WRITE(blobfile, &ret.glsl.usetesselation, sizeof(ret.glsl.usetesselation));
BZ_Free(blobdata); BZ_Free(blobdata);
} }
return handle; ret.glsl.usetesselation = (cont || eval);
return ret;
} }
qboolean GLSlang_ValidateProgramPermu(program_t *prog, const char *name, unsigned int permu, qboolean noerrors, vfsfile_t *blobfile) qboolean GLSlang_ValidateProgramPermu(program_t *prog, const char *name, unsigned int permu, qboolean noerrors, vfsfile_t *blobfile)
{ {
prog->permu[permu].handle.glsl = GLSlang_ValidateProgram(prog->permu[permu].handle.glsl, name, noerrors, blobfile); return GLSlang_ValidateProgram(&prog->permu[permu].handle, name, noerrors, blobfile);
return !!prog->permu[permu].handle.glsl;
} }
qboolean GLSlang_CreateProgramPermu(program_t *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *frag, qboolean noerrors, vfsfile_t *blobfile) qboolean GLSlang_CreateProgramPermu(program_t *prog, const char *name, unsigned int permu, int ver, const char **precompilerconstants, const char *vert, const char *tcs, const char *tes, const char *frag, qboolean noerrors, vfsfile_t *blobfile)
{ {
@ -1777,8 +1842,8 @@ qboolean GLSlang_CreateProgramPermu(program_t *prog, const char *name, unsigned
if (permu & PERMUTATION_SKELETAL) if (permu & PERMUTATION_SKELETAL)
ver = 120; ver = 120;
} }
prog->permu[permu].handle.glsl = GLSlang_CreateProgram(name, ver, precompilerconstants, vert, frag, noerrors, blobfile); prog->permu[permu].handle = GLSlang_CreateProgram(name, ver, precompilerconstants, vert, tcs, tes, frag, noerrors, blobfile);
if (prog->permu[permu].handle.glsl) if (prog->permu[permu].handle.glsl.handle)
return true; return true;
return false; return false;
} }
@ -1805,26 +1870,27 @@ static qboolean GLSlang_LoadBlob(program_t *prog, const char *name, unsigned int
VFS_READ(blobfile, &length, sizeof(length)); VFS_READ(blobfile, &length, sizeof(length));
binary = BZ_Malloc(length); binary = BZ_Malloc(length);
VFS_READ(blobfile, binary, length); VFS_READ(blobfile, binary, length);
VFS_READ(blobfile, &prog->permu[permu].handle.glsl.usetesselation, sizeof(prog->permu[permu].handle.glsl.usetesselation));
prog->permu[permu].handle.glsl = qglCreateProgramObjectARB(); prog->permu[permu].handle.glsl.handle = qglCreateProgramObjectARB();
qglProgramBinary(prog->permu[permu].handle.glsl, fmt, binary, length); qglProgramBinary(prog->permu[permu].handle.glsl.handle, fmt, binary, length);
BZ_Free(binary); BZ_Free(binary);
qglGetProgramParameteriv_(prog->permu[permu].handle.glsl, GL_OBJECT_LINK_STATUS_ARB, &success); qglGetProgramParameteriv_(prog->permu[permu].handle.glsl.handle, GL_OBJECT_LINK_STATUS_ARB, &success);
if (!success) if (!success)
{ {
qglDeleteProgramObject_(prog->permu[permu].handle.glsl); qglDeleteProgramObject_(prog->permu[permu].handle.glsl.handle);
prog->permu[permu].handle.glsl = 0; memset(&prog->permu[permu].handle, 0, sizeof(prog->permu[permu].handle));
} }
return !!success; return !!success;
} }
static void GLSlang_DeleteProg(program_t *prog, unsigned int permu) static void GLSlang_DeleteProg(program_t *prog, unsigned int permu)
{ {
if (prog->permu[permu].handle.glsl) if (prog->permu[permu].handle.glsl.handle)
{ {
qglDeleteProgramObject_(prog->permu[permu].handle.glsl); qglDeleteProgramObject_(prog->permu[permu].handle.glsl.handle);
prog->permu[permu].handle.glsl = 0; prog->permu[permu].handle.glsl.handle = 0;
} }
} }
@ -1841,12 +1907,12 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart
//figure out visible attributes //figure out visible attributes
for (p = 0; p < PERMUTATIONS; p++) for (p = 0; p < PERMUTATIONS; p++)
{ {
if (!prog->permu[p].handle.glsl) if (!prog->permu[p].handle.glsl.handle)
continue; continue;
GLSlang_UseProgram(prog->permu[p].handle.glsl); GLSlang_UseProgram(prog->permu[p].handle.glsl.handle);
for (i = 0; shader_attr_names[i].name; i++) for (i = 0; shader_attr_names[i].name; i++)
{ {
uniformloc = qglGetAttribLocationARB(prog->permu[p].handle.glsl, shader_attr_names[i].name); uniformloc = qglGetAttribLocationARB(prog->permu[p].handle.glsl.handle, shader_attr_names[i].name);
if (uniformloc != -1) if (uniformloc != -1)
{ {
if (shader_attr_names[i].ptype != uniformloc) if (shader_attr_names[i].ptype != uniformloc)
@ -1863,11 +1929,11 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart
found = false; found = false;
for (p = 0; p < PERMUTATIONS; p++) for (p = 0; p < PERMUTATIONS; p++)
{ {
if (!prog->permu[p].handle.glsl) if (!prog->permu[p].handle.glsl.handle)
continue; continue;
GLSlang_UseProgram(prog->permu[p].handle.glsl); GLSlang_UseProgram(prog->permu[p].handle.glsl.handle);
uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl, shader_unif_names[i].name); uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl.handle, shader_unif_names[i].name);
if (uniformloc != -1) if (uniformloc != -1)
found = true; found = true;
@ -1911,11 +1977,11 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart
for (p = 0; p < PERMUTATIONS; p++) for (p = 0; p < PERMUTATIONS; p++)
{ {
char uniformname[64]; char uniformname[64];
if (!prog->permu[p].handle.glsl) if (!prog->permu[p].handle.glsl.handle)
continue; continue;
GL_SelectProgram(prog->permu[p].handle.glsl); GL_SelectProgram(prog->permu[p].handle.glsl.handle);
Q_snprintfz(uniformname, sizeof(uniformname), "cvar_%s", tmpname); Q_snprintfz(uniformname, sizeof(uniformname), "cvar_%s", tmpname);
uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl, uniformname); uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl.handle, uniformname);
if (uniformloc != -1) if (uniformloc != -1)
{ {
//qglUniform1fARB(uniformloc, cvar->value); //qglUniform1fARB(uniformloc, cvar->value);
@ -1929,15 +1995,15 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart
/*set texture uniforms*/ /*set texture uniforms*/
for (p = 0; p < PERMUTATIONS; p++) for (p = 0; p < PERMUTATIONS; p++)
{ {
if (!prog->permu[p].handle.glsl) if (!prog->permu[p].handle.glsl.handle)
continue; continue;
if (!(prog->permu[p].attrmask & (1u<<VATTR_VERTEX1))) //a shader kinda has to use one of these... if (!(prog->permu[p].attrmask & (1u<<VATTR_VERTEX1))) //a shader kinda has to use one of these...
prog->permu[p].attrmask |= (1u<<VATTR_LEG_VERTEX); prog->permu[p].attrmask |= (1u<<VATTR_LEG_VERTEX);
GLSlang_UseProgram(prog->permu[p].handle.glsl); GLSlang_UseProgram(prog->permu[p].handle.glsl.handle);
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
{ {
Q_snprintfz(tmpname, sizeof(tmpname), "s_t%i", i); Q_snprintfz(tmpname, sizeof(tmpname), "s_t%i", i);
uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl, tmpname); uniformloc = qglGetUniformLocationARB(prog->permu[p].handle.glsl.handle, tmpname);
if (uniformloc != -1) if (uniformloc != -1)
qglUniform1iARB(uniformloc, i); qglUniform1iARB(uniformloc, i);
} }
@ -1948,7 +2014,7 @@ static void GLSlang_ProgAutoFields(program_t *prog, char **cvarnames, int *cvart
void GL_Init(void *(*getglfunction) (char *name)) void GL_Init(void *(*getglfunction) (char *name))
{ {
#ifndef GL_STATIC #ifndef GL_STATIC
qglBindTexture = (void *)getglcore("glBindTexture"); //for compleateness qglBindTexture = (void *)getglcore("glBindTexture"); //for compleateness. core in 1.1. needed by fte.
qglBlendFunc = (void *)getglcore("glBlendFunc"); qglBlendFunc = (void *)getglcore("glBlendFunc");
qglClear = (void *)getglcore("glClear"); qglClear = (void *)getglcore("glClear");
qglClearColor = (void *)getglcore("glClearColor"); qglClearColor = (void *)getglcore("glClearColor");

View file

@ -198,6 +198,7 @@ extern FTEPFNGLCOMPRESSEDTEXIMAGE2DARBPROC qglCompressedTexImage2DARB;
extern FTEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC qglGetCompressedTexImageARB; extern FTEPFNGLGETCOMPRESSEDTEXIMAGEARBPROC qglGetCompressedTexImageARB;
extern FTEPFNGLPNTRIANGLESIATIPROC qglPNTrianglesiATI; extern FTEPFNGLPNTRIANGLESIATIPROC qglPNTrianglesiATI;
extern FTEPFNGLPNTRIANGLESFATIPROC qglPNTrianglesfATI; extern FTEPFNGLPNTRIANGLESFATIPROC qglPNTrianglesfATI;
extern void (APIENTRY *qglPatchParameteriARB)(GLenum pname, GLint value); //core in gl4
qboolean GL_CheckExtension(char *extname); qboolean GL_CheckExtension(char *extname);
@ -1061,7 +1062,7 @@ extern void (APIENTRY *qglBindVertexArray)(GLuint vaoarray);
//glslang helper api //glslang helper api
GLhandleARB GLSlang_CreateProgram(const char *name, int ver, const char **precompilerconstants, const char *vert, const char *frag, qboolean silent, vfsfile_t *blobfile); union programhandle_u GLSlang_CreateProgram(const char *name, int ver, const char **precompilerconstants, const char *vert, const char *cont, const char *eval, const char *frag, qboolean silent, vfsfile_t *blobfile);
GLint GLSlang_GetUniformLocation (int prog, char *name); GLint GLSlang_GetUniformLocation (int prog, char *name);
void GL_SelectProgram(int program); void GL_SelectProgram(int program);
#define GLSlang_UseProgram(prog) GL_SelectProgram(prog) #define GLSlang_UseProgram(prog) GL_SelectProgram(prog)

View file

@ -579,6 +579,11 @@ typedef void (APIENTRYP PFNGLGETSHADERSOURCEARBPROC) (GLhandleARB obj, GLsizei
#define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A #define GL_OBJECT_ACTIVE_ATTRIBUTE_MAX_LENGTH_ARB 0x8B8A
#endif #endif
#ifndef GL_ARB_vertex_shader
#define GL_TESS_EVALUATION_SHADER_ARB 0x8E87
#define GL_TESS_CONTROL_SHADER_ARB 0x8E88
#endif
#ifndef GL_ARB_fragment_shader #ifndef GL_ARB_fragment_shader
#define GL_FRAGMENT_SHADER_ARB 0x8B30 #define GL_FRAGMENT_SHADER_ARB 0x8B30
#define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49 #define GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB 0x8B49

View file

@ -422,7 +422,11 @@ typedef struct {
union programhandle_u union programhandle_u
{ {
int glsl; struct
{
int handle;
qboolean usetesselation;
} glsl;
#ifdef D3DQUAKE #ifdef D3DQUAKE
struct struct
{ {