}
cachepicflags_t;
-void Draw_Init (void);
void Draw_Frame (void);
cachepic_t *Draw_CachePic_Flags (const char *path, unsigned int cachepicflags);
cachepic_t *Draw_CachePic (const char *path); // standard function with no options, used throughout engine
// unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
for (j = 0;j < 5;j++)
if (textures[j])
- for (i = 0;i < vid.teximageunits;i++)
+ for (i = 0;i < MAX_TEXTUREUNITS;i++)
if (gl_state.units[i].texture == textures[j])
R_Mesh_TexBind(i, NULL);
// set up framebuffer object or render targets for the active rendering API
static void GL_Backend_ResetState(void)
{
- unsigned int i;
gl_state.active = true;
gl_state.depthtest = true;
gl_state.alphatest = false;
qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
gl_state.unit = MAX_TEXTUREUNITS;
gl_state.clientunit = MAX_TEXTUREUNITS;
- for (i = 0;i < vid.teximageunits;i++)
- {
- GL_ActiveTexture(i);
- qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
- qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
- qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR
- }
- for (i = 0;i < vid.texarrayunits;i++)
- {
- GL_BindVBO(0);
- qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
- }
CHECKGLERROR
break;
}
void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, size_t stride, const void *pointer, const r_meshbuffer_t *vertexbuffer, size_t bufferoffset)
{
gltextureunit_t *unit = gl_state.units + unitnum;
+ if (unitnum >= MAX_TEXTUREUNITS)
+ Sys_Error("R_Mesh_TexCoordPointer: unitnum %i > max units %i\n", unitnum, MAX_TEXTUREUNITS);
// update array settings
// note: there is no need to check bufferobject here because all cases
// that involve a valid bufferobject also supply a texcoord array
int R_Mesh_TexBound(unsigned int unitnum, int id)
{
gltextureunit_t *unit = gl_state.units + unitnum;
- if (unitnum >= vid.teximageunits)
- return 0;
+ if (unitnum >= MAX_TEXTUREUNITS)
+ Sys_Error("R_Mesh_TexCoordPointer: unitnum %i > max units %i\n", unitnum, MAX_TEXTUREUNITS);
if (id == GL_TEXTURE_2D)
return unit->t2d;
if (id == GL_TEXTURE_3D)
{
gltextureunit_t *unit;
unsigned int unitnum;
- // this doesn't really unbind the texture, but it does prevent a mistaken "do nothing" behavior on the next time this same texnum is bound on the same unit as the same type (this mainly affects r_shadow_bouncegrid because 3D textures are so rarely used)
- for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
+ // unbind the texture from any units it is bound on - this prevents accidental reuse of certain textures whose bindings can linger far too long otherwise (e.g. bouncegrid which is a 3D texture) and confuse the driver later.
+ for (unitnum = 0; unitnum < MAX_TEXTUREUNITS; unitnum++)
{
unit = gl_state.units + unitnum;
- if (unit->t2d == texnum)
- unit->t2d = -1;
- if (unit->t3d == texnum)
- unit->t3d = -1;
- if (unit->tcubemap == texnum)
- unit->tcubemap = -1;
+ if (unit->texture && unit->texture->texnum == texnum)
+ R_Mesh_TexBind(unitnum, NULL);
}
}
{
gltextureunit_t *unit = gl_state.units + unitnum;
int texnum;
- if (unitnum >= vid.teximageunits)
- return;
+ if (unitnum >= MAX_TEXTUREUNITS)
+ Sys_Error("R_Mesh_TexBind: unitnum %i > max units %i\n", unitnum, MAX_TEXTUREUNITS);
if (unit->texture == tex)
return;
switch(vid.renderpath)
BACKENDACTIVECHECK
- for (unitnum = 0;unitnum < vid.teximageunits;unitnum++)
+ for (unitnum = 0;unitnum < MAX_TEXTUREUNITS;unitnum++)
R_Mesh_TexBind(unitnum, NULL);
- for (unitnum = 0;unitnum < vid.texarrayunits;unitnum++)
+ for (unitnum = 0;unitnum < MAX_TEXTUREUNITS;unitnum++)
R_Mesh_TexCoordPointer(unitnum, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0);
}
// ignore TEXF_COMPRESS when comparing, because fallback pics remove the flag, and ignore TEXF_MIPMAP because QC specifies that
if ((pic->texflags ^ texflags) & ~(TEXF_COMPRESS | TEXF_MIPMAP))
{
- Con_DPrintf("Draw_CachePic(\"%s\"): reloading pic due to mismatch on flags\n", path);
+ Con_DPrintf("Draw_CachePic(\"%s\"): frame %i: reloading pic due to mismatch on flags\n", path, draw_frame);
goto reload;
}
if (!pic->skinframe || !pic->skinframe->base)
{
- Con_DPrintf("Draw_CachePic(\"%s\"): reloading pic\n", path);
+ Con_DPrintf("Draw_CachePic(\"%s\"): frame %i: reloading pic\n", path, draw_frame);
goto reload;
}
if (!(cachepicflags & CACHEPICFLAG_NOTPERSISTENT))
if (numcachepics == MAX_CACHED_PICS)
{
- Con_Printf ("Draw_CachePic(\"%s\"): numcachepics == MAX_CACHED_PICS\n", path);
+ Con_Printf ("Draw_CachePic(\"%s\"): frame %i: numcachepics == MAX_CACHED_PICS\n", path, draw_frame);
// FIXME: support NULL in callers?
return cachepics; // return the first one
}
- Con_DPrintf("Draw_CachePic(\"%s\"): loading pic\n", path);
+ Con_DPrintf("Draw_CachePic(\"%s\"): frame %i: loading pic%s\n", path, draw_frame, (cachepicflags & CACHEPICFLAG_NOTPERSISTENT) ? " notpersist" : "");
pic = cachepics + (numcachepics++);
memset(pic, 0, sizeof(*pic));
strlcpy (pic->name, path, sizeof(pic->name));
if (pic == NULL)
return false;
if (pic->autoload && (!pic->skinframe || !pic->skinframe->base))
+ {
+ Con_DPrintf("Draw_IsPicLoaded(\"%s\"): Loading external skin\n", pic->name);
pic->skinframe = R_SkinFrame_LoadExternal(pic->name, pic->texflags | TEXF_FORCE_RELOAD, false, true);
+ }
// skinframe will only be NULL if the pic was created with CACHEPICFLAG_FAILONMISSING and not found
return pic->skinframe != NULL && pic->skinframe->base != NULL;
}
if (pic == NULL)
return NULL;
if (pic->autoload && (!pic->skinframe || !pic->skinframe->base))
+ {
+ Con_DPrintf("Draw_GetPicTexture(\"%s\"): Loading external skin\n", pic->name);
pic->skinframe = R_SkinFrame_LoadExternal(pic->name, pic->texflags | TEXF_FORCE_RELOAD, false, true);
+ }
pic->lastusedframe = draw_frame;
return pic->skinframe ? pic->skinframe->base : NULL;
}
return;
nextpurgetime = realtime + 0.05;
for (i = 0, pic = cachepics;i < numcachepics;i++, pic++)
+ {
if (pic->autoload && pic->skinframe && pic->skinframe->base && pic->lastusedframe < draw_frame - 3)
+ {
+ Con_DPrintf("Draw_Frame(%i): Unloading \"%s\"\n", draw_frame, pic->name);
R_SkinFrame_PurgeSkinFrame(pic->skinframe);
+ }
+ }
draw_frame++;
}
{
if (pic->flags & CACHEPICFLAG_NEWPIC && pic->skinframe && pic->skinframe->base && pic->width == width && pic->height == height)
{
+ Con_DPrintf("Draw_NewPic(\"%s\"): frame %i: updating texture\n", picname, draw_frame);
R_UpdateTexture(pic->skinframe->base, pixels_bgra, 0, 0, 0, width, height, 1);
R_SkinFrame_MarkUsed(pic->skinframe);
pic->lastusedframe = draw_frame;
return pic;
}
+ Con_Printf("Draw_NewPic(\"%s\"): frame %i: reloading pic because flags/size changed\n", picname, draw_frame);
}
else
{
if (numcachepics == MAX_CACHED_PICS)
{
- Con_Printf ("Draw_NewPic: numcachepics == MAX_CACHED_PICS\n");
+ Con_Printf ("Draw_NewPic(\"%s\"): frame %i: numcachepics == MAX_CACHED_PICS\n", picname, draw_frame);
// FIXME: support NULL in callers?
return cachepics; // return the first one
}
+ Con_Printf("Draw_NewPic(\"%s\"): frame %i: creating new cachepic\n", picname, draw_frame);
pic = cachepics + (numcachepics++);
memset(pic, 0, sizeof(*pic));
strlcpy (pic->name, picname, sizeof(pic->name));
{
if (!strcmp (picname, pic->name) && pic->skinframe)
{
+ Con_DPrintf("Draw_FreePic(\"%s\"): frame %i: freeing pic\n", picname, draw_frame);
R_SkinFrame_PurgeSkinFrame(pic->skinframe);
- pic->width = 0;
- pic->height = 0;
return;
}
}
{
case RENDERPATH_GL32:
case RENDERPATH_GLES2:
- Cvar_SetValueQuick(&r_textureunits, vid.texunits);
+ Cvar_SetValueQuick(&r_textureunits, MAX_TEXTUREUNITS);
Cvar_SetValueQuick(&gl_combine, 1);
Cvar_SetValueQuick(&r_glsl, 1);
r_loadnormalmap = true;
extern int cl_available;
-#define MAX_TEXTUREUNITS 16
+#define MAX_TEXTUREUNITS 32
typedef enum renderpath_e
{
renderpath_t renderpath;
qboolean allowalphatocoverage; // indicates the GL_AlphaToCoverage function works on this renderpath and framebuffer
- unsigned int texunits;
- unsigned int teximageunits;
- unsigned int texarrayunits;
unsigned int drawrangeelements_maxvertices;
unsigned int drawrangeelements_maxindices;
Con_Printf("GL_OES_texture_3d reported bogus GL_MAX_3D_TEXTURE_SIZE, disabled\n");
}
- vid.texunits = 4;
- vid.teximageunits = 8;
- vid.texarrayunits = 5;
- qglGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, (GLint*)&vid.teximageunits);CHECKGLERROR
- vid.texunits = bound(1, vid.texunits, MAX_TEXTUREUNITS);
- vid.teximageunits = bound(1, vid.teximageunits, MAX_TEXTUREUNITS);
- vid.texarrayunits = bound(1, vid.texarrayunits, MAX_TEXTUREUNITS);
Con_DPrint("Using GLES2 rendering path\n");
vid.renderpath = RENDERPATH_GLES2;
vid.sRGBcapable2D = false;
vid.maxtexturesize_2d = 0;
vid.maxtexturesize_3d = 0;
vid.maxtexturesize_cubemap = 0;
- vid.texunits = 1;
- vid.teximageunits = 1;
- vid.texarrayunits = 1;
vid.max_anisotropy = 1;
vid.maxdrawbuffers = 1;
qglGetIntegerv(GL_MAX_CUBE_MAP_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_cubemap);
qglGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, (GLint*)&vid.maxtexturesize_3d);
- vid.texunits = 4;
- vid.teximageunits = 32;
- vid.texarrayunits = 10;
vid.renderpath = RENDERPATH_GL32;
vid.sRGBcapable2D = false;
vid.sRGBcapable3D = true;