fteqw/engine/gl/gl_rsurf.c
Spoike c6c3d3f4e0 Trimmed some dead files.
Quick hack preliminary d3d11 renderer. I'm not likely to touch this again for quite some time.
Sys_Error works properly on android, with an error message shown. Should be less of a stab in the dark if you get errors. Seg faults are still instantly fatal. Not much I can reliably do about those - most of the juicy ones will likely occur within the gl drivers (even if its my fault) and java will still call in to it.
Stereoscopic (quad-buffered) rendering is in the gl renderer. You'll likely need a quatro to use it despite it being a gl 1.0 feature. No idea about ati. See r_stereo_method for non-quad-buffered alternatives.
Tweaked networking to not overflow so much. Needs testing against other qw clients.
Fixed an issue with surface numbers > 32k on limit-breaking maps.
Fixed a preparse issue resulting in QW clients dying with the ne_ruins map's progs.
Support for the DP-variant of BSP2. The depricated RMQ variant is still supported.
QTV proxy now uses ipv6 hybrid sockets where possible. Preliminary pext support.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@4105 fc73d0e0-1445-4013-8a0c-d673dee63da5
2012-09-30 05:52:03 +00:00

520 lines
13 KiB
C

/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// r_surf.c: surface-related refresh code
#include "quakedef.h"
#if defined(GLQUAKE)
#include "glquake.h"
#include "shader.h"
#include "renderque.h"
#include <math.h>
void GLBE_ClearVBO(vbo_t *vbo)
{
int vboh[6 + MAXLIGHTMAPS];
int i, j;
vboh[0] = vbo->indicies.gl.vbo;
vboh[1] = vbo->coord.gl.vbo;
vboh[2] = vbo->texcoord.gl.vbo;
vboh[3] = vbo->normals.gl.vbo;
vboh[4] = vbo->svector.gl.vbo;
vboh[5] = vbo->tvector.gl.vbo;
for (i = 0; i < MAXLIGHTMAPS; i++)
vboh[6+i] = vbo->lmcoord[i].gl.vbo;
for (i = 0; i < 7; i++)
{
if (!vboh[i])
continue;
for (j = 0; j < 7; j++)
{
if (vboh[j] == vboh[i])
break; //already freed by one of the other ones
}
if (j == 7)
qglDeleteBuffersARB(1, &vboh[i]);
}
if (vbo->vertdata)
BZ_Free(vbo->vertdata);
BZ_Free(vbo->meshlist);
BZ_Free(vbo);
}
void GLBE_SetupVAO(vbo_t *vbo, unsigned int vaodynamic);
static qboolean GL_BuildVBO(vbo_t *vbo, void *vdata, int vsize, void *edata, int elementsize, unsigned int vaodynamic)
{
unsigned int vbos[2];
int s;
if (!qglGenBuffersARB)
return false;
qglGenBuffersARB(1+(elementsize>0), vbos);
//opengl ate our data, fixup the vbo arrays to point to the vbo instead of the raw data
if (vbo->indicies.gl.addr && elementsize)
{
vbo->indicies.gl.vbo = vbos[1];
vbo->indicies.gl.addr = (index_t*)((char*)vbo->indicies.gl.addr - (char*)edata);
}
if (vbo->coord.gl.addr)
{
vbo->coord.gl.vbo = vbos[0];
vbo->coord.gl.addr = (vecV_t*)((char*)vbo->coord.gl.addr - (char*)vdata);
}
if (vbo->texcoord.gl.addr)
{
vbo->texcoord.gl.vbo = vbos[0];
vbo->texcoord.gl.addr = (vec2_t*)((char*)vbo->texcoord.gl.addr - (char*)vdata);
}
for (s = 0; s < MAXLIGHTMAPS; s++)
{
if (vbo->lmcoord[s].gl.addr)
{
vbo->lmcoord[s].gl.vbo = vbos[0];
vbo->lmcoord[s].gl.addr = (vec2_t*)((char*)vbo->lmcoord[s].gl.addr - (char*)vdata);
}
}
if (vbo->normals.gl.addr)
{
vbo->normals.gl.vbo = vbos[0];
vbo->normals.gl.addr = (vec3_t*)((char*)vbo->normals.gl.addr - (char*)vdata);
}
if (vbo->svector.gl.addr)
{
vbo->svector.gl.vbo = vbos[0];
vbo->svector.gl.addr = (vec3_t*)((char*)vbo->svector.gl.addr - (char*)vdata);
}
if (vbo->tvector.gl.addr)
{
vbo->tvector.gl.vbo = vbos[0];
vbo->tvector.gl.addr = (vec3_t*)((char*)vbo->tvector.gl.addr - (char*)vdata);
}
if (vbo->colours.gl.addr)
{
vbo->colours.gl.vbo = vbos[0];
vbo->colours.gl.addr = (vec4_t*)((char*)vbo->colours.gl.addr - (char*)vdata);
}
GLBE_SetupVAO(vbo, vaodynamic);
qglBufferDataARB(GL_ARRAY_BUFFER_ARB, vsize, vdata, GL_STATIC_DRAW_ARB);
if (elementsize>0)
{
qglBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, elementsize, edata, GL_STATIC_DRAW_ARB);
}
return true;
}
void *allocbuf(char **p, int elements, int elementsize)
{
void *ret;
*p += elementsize - 1;
*p -= (size_t)*p & (elementsize-1);
ret = *p;
*p += elements*elementsize;
return ret;
}
void GLBE_GenBatchVBOs(vbo_t **vbochain, batch_t *firstbatch, batch_t *stopbatch)
{
unsigned int maxvboverts;
unsigned int maxvboelements;
unsigned int i, s;
unsigned int v;
unsigned int vcount, ecount;
unsigned int pervertsize; //erm, that name wasn't intentional
unsigned int meshes;
vbo_t *vbo;
mesh_t *m;
char *p;
vecV_t *coord;
vec2_t *texcoord;
vec2_t *lmcoord[MAXLIGHTMAPS];
vec3_t *normals;
vec3_t *svector;
vec3_t *tvector;
vec4_t *colours;
index_t *indicies;
batch_t *batch;
vbo = Z_Malloc(sizeof(*vbo));
maxvboverts = 0;
maxvboelements = 0;
meshes = 0;
for(batch = firstbatch; batch != stopbatch; batch = batch->next)
{
for (i=0 ; i<batch->maxmeshes ; i++)
{
m = batch->mesh[i];
meshes++;
maxvboelements += m->numindexes;
maxvboverts += m->numvertexes;
}
}
if (maxvboverts > MAX_INDICIES)
Sys_Error("Building a vbo with too many verticies\n");
vcount = 0;
ecount = 0;
pervertsize = sizeof(vecV_t)+ //coord
sizeof(vec2_t)+ //tex
sizeof(vec2_t)*MAXLIGHTMAPS+ //lm
sizeof(vec3_t)+ //normal
sizeof(vec3_t)+ //sdir
sizeof(vec3_t)+ //tdir
sizeof(vec4_t); //colours
vbo->vertdata = BZ_Malloc((maxvboverts+1)*pervertsize + (maxvboelements+1)*sizeof(index_t));
p = vbo->vertdata;
vbo->coord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vecV_t));
vbo->texcoord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec2_t));
for (s = 0; s < MAXLIGHTMAPS; s++)
vbo->lmcoord[s].gl.addr = allocbuf(&p, maxvboverts, sizeof(vec2_t));
vbo->normals.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t));
vbo->svector.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t));
vbo->tvector.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t));
vbo->colours.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec4_t));
vbo->indicies.gl.addr = allocbuf(&p, maxvboelements, sizeof(index_t));
coord = vbo->coord.gl.addr;
texcoord = vbo->texcoord.gl.addr;
for (s = 0; s < 4; s++)
lmcoord[s] = vbo->lmcoord[s].gl.addr;
normals = vbo->normals.gl.addr;
svector = vbo->svector.gl.addr;
tvector = vbo->tvector.gl.addr;
colours = vbo->colours.gl.addr;
indicies = vbo->indicies.gl.addr;
//vbo->meshcount = meshes;
//vbo->meshlist = BZ_Malloc(meshes*sizeof(*vbo->meshlist));
meshes = 0;
for(batch = firstbatch; batch != stopbatch; batch = batch->next)
{
batch->vbo = vbo;
for (i=0 ; i<batch->maxmeshes ; i++)
{
m = batch->mesh[i];
// surf->mark = &vbo->meshlist[meshes++];
// *surf->mark = NULL;
m->vbofirstvert = vcount;
m->vbofirstelement = ecount;
for (v = 0; v < m->numindexes; v++)
indicies[ecount++] = vcount + m->indexes[v];
for (v = 0; v < m->numvertexes; v++)
{
coord[vcount+v][0] = m->xyz_array[v][0];
coord[vcount+v][1] = m->xyz_array[v][1];
coord[vcount+v][2] = m->xyz_array[v][2];
if (m->st_array)
{
texcoord[vcount+v][0] = m->st_array[v][0];
texcoord[vcount+v][1] = m->st_array[v][1];
}
for (s = 0; s < MAXLIGHTMAPS; s++)
{
if (m->lmst_array[s])
{
lmcoord[s][vcount+v][0] = m->lmst_array[s][v][0];
lmcoord[s][vcount+v][1] = m->lmst_array[s][v][1];
}
}
if (m->normals_array)
{
normals[vcount+v][0] = m->normals_array[v][0];
normals[vcount+v][1] = m->normals_array[v][1];
normals[vcount+v][2] = m->normals_array[v][2];
}
if (m->snormals_array)
{
svector[vcount+v][0] = m->snormals_array[v][0];
svector[vcount+v][1] = m->snormals_array[v][1];
svector[vcount+v][2] = m->snormals_array[v][2];
}
if (m->tnormals_array)
{
tvector[vcount+v][0] = m->tnormals_array[v][0];
tvector[vcount+v][1] = m->tnormals_array[v][1];
tvector[vcount+v][2] = m->tnormals_array[v][2];
}
if (m->colors4f_array)
{
colours[vcount+v][0] = m->colors4f_array[v][0];
colours[vcount+v][1] = m->colors4f_array[v][1];
colours[vcount+v][2] = m->colors4f_array[v][2];
colours[vcount+v][3] = m->colors4f_array[v][3];
}
}
vcount += v;
}
}
if (GL_BuildVBO(vbo, vbo->vertdata, vcount*pervertsize, indicies, ecount*sizeof(index_t), 0))
{
BZ_Free(vbo->vertdata);
vbo->vertdata = NULL;
}
vbo->next = *vbochain;
*vbochain = vbo;
}
void GLBE_GenBrushModelVBO(model_t *mod)
{
unsigned int vcount;
unsigned int cvcount;
batch_t *batch, *fbatch;
int sortid;
int i;
fbatch = NULL;
vcount = 0;
for (sortid = 0; sortid < SHADER_SORT_COUNT; sortid++)
{
if (!mod->batches[sortid])
continue;
for (fbatch = batch = mod->batches[sortid]; batch != NULL; batch = batch->next)
{
for (i = 0, cvcount = 0; i < batch->maxmeshes; i++)
cvcount += batch->mesh[i]->numvertexes;
//firstmesh got reused as the number of verticies in each batch
if (vcount + cvcount > MAX_INDICIES)
{
GLBE_GenBatchVBOs(&mod->vbos, fbatch, batch);
fbatch = batch;
vcount = 0;
}
vcount += cvcount;
}
GLBE_GenBatchVBOs(&mod->vbos, fbatch, batch);
}
#if 0
if (!mod->numsurfaces)
return;
for (t = 0; t < mod->numtextures; t++)
{
if (!mod->textures[t])
continue;
vbo = &mod->textures[t]->vbo;
BE_ClearVBO(vbo);
maxvboverts = 0;
maxvboelements = 0;
meshes = 0;
for (i=0 ; i<mod->numsurfaces ; i++)
{
if (mod->surfaces[i].texinfo->texture != mod->textures[t])
continue;
m = mod->surfaces[i].mesh;
if (!m)
continue;
meshes++;
maxvboelements += m->numindexes;
maxvboverts += m->numvertexes;
}
#if sizeof_index_t == 2
if (maxvboverts > (1<<(sizeof(index_t)*8))-1)
continue;
#endif
if (!maxvboverts)
continue;
//fixme: stop this from leaking!
vcount = 0;
ecount = 0;
pervertsize = sizeof(vecV_t)+ //coord
sizeof(vec2_t)+ //tex
sizeof(vec2_t)+ //lm
sizeof(vec3_t)+ //normal
sizeof(vec3_t)+ //sdir
sizeof(vec3_t)+ //tdir
sizeof(vec4_t); //colours
vbo->vertdata = BZ_Malloc((maxvboverts+1)*pervertsize + (maxvboelements+1)*sizeof(index_t));
p = vbo->vertdata;
vbo->coord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vecV_t));
vbo->texcoord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec2_t));
vbo->lmcoord.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec2_t));
vbo->normals.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t));
vbo->svector.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t));
vbo->tvector.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec3_t));
vbo->colours.gl.addr = allocbuf(&p, maxvboverts, sizeof(vec4_t));
vbo->indicies.gl.addr = allocbuf(&p, maxvboelements, sizeof(index_t));
coord = vbo->coord.gl.addr;
texcoord = vbo->texcoord.gl.addr;
lmcoord = vbo->lmcoord.gl.addr;
normals = vbo->normals.gl.addr;
svector = vbo->svector.gl.addr;
tvector = vbo->tvector.gl.addr;
colours = vbo->colours.gl.addr;
indicies = vbo->indicies.gl.addr;
vbo->meshcount = meshes;
vbo->meshlist = BZ_Malloc(meshes*sizeof(*vbo->meshlist));
meshes = 0;
for (i=0 ; i<mod->numsurfaces ; i++)
{
if (mod->surfaces[i].texinfo->texture != mod->textures[t])
continue;
m = mod->surfaces[i].mesh;
if (!m)
continue;
mod->surfaces[i].mark = &vbo->meshlist[meshes++];
*mod->surfaces[i].mark = NULL;
m->vbofirstvert = vcount;
m->vbofirstelement = ecount;
for (v = 0; v < m->numindexes; v++)
indicies[ecount++] = vcount + m->indexes[v];
for (v = 0; v < m->numvertexes; v++)
{
coord[vcount+v][0] = m->xyz_array[v][0];
coord[vcount+v][1] = m->xyz_array[v][1];
coord[vcount+v][2] = m->xyz_array[v][2];
if (m->st_array)
{
texcoord[vcount+v][0] = m->st_array[v][0];
texcoord[vcount+v][1] = m->st_array[v][1];
}
if (m->lmst_array)
{
lmcoord[vcount+v][0] = m->lmst_array[v][0];
lmcoord[vcount+v][1] = m->lmst_array[v][1];
}
if (m->normals_array)
{
normals[vcount+v][0] = m->normals_array[v][0];
normals[vcount+v][1] = m->normals_array[v][1];
normals[vcount+v][2] = m->normals_array[v][2];
}
if (m->snormals_array)
{
svector[vcount+v][0] = m->snormals_array[v][0];
svector[vcount+v][1] = m->snormals_array[v][1];
svector[vcount+v][2] = m->snormals_array[v][2];
}
if (m->tnormals_array)
{
tvector[vcount+v][0] = m->tnormals_array[v][0];
tvector[vcount+v][1] = m->tnormals_array[v][1];
tvector[vcount+v][2] = m->tnormals_array[v][2];
}
if (m->colors4f_array)
{
colours[vcount+v][0] = m->colors4f_array[v][0];
colours[vcount+v][1] = m->colors4f_array[v][1];
colours[vcount+v][2] = m->colors4f_array[v][2];
colours[vcount+v][3] = m->colors4f_array[v][3];
}
}
vcount += v;
}
if (GL_BuildVBO(vbo, vbo->vertdata, vcount*pervertsize, indicies, ecount*sizeof(index_t), 0))
{
BZ_Free(vbo->vertdata);
vbo->vertdata = NULL;
}
}
#endif
}
void GLBE_UploadAllLightmaps(void)
{
lightmapinfo_t *lm;
int i;
//
// upload all lightmaps that were filled
//
for (i=0 ; i<numlightmaps ; i++)
{
if (!lightmap[i])
break; // no more used
lm = lightmap[i];
lm->rectchange.l = lm->width;
lm->rectchange.t = lm->height;
lm->rectchange.w = 0;
lm->rectchange.h = 0;
if (!lm->modified)
continue;
lm->modified = false;
if (!TEXVALID(lm->lightmap_texture))
{
TEXASSIGN(lm->lightmap_texture, R_AllocNewTexture("***lightmap***", lm->width, lm->height, 0));
}
GL_MTBind(0, GL_TEXTURE_2D, lm->lightmap_texture);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
switch (lightmap_bytes)
{
case 4:
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
lm->width, lm->height, 0, (lightmap_bgra?GL_BGRA_EXT:GL_RGBA), GL_UNSIGNED_INT_8_8_8_8_REV,
lightmap[i]->lightmaps);
break;
case 3:
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
lm->width, lm->height, 0, (lightmap_bgra?GL_BGR_EXT:GL_RGB), GL_UNSIGNED_BYTE,
lightmap[i]->lightmaps);
break;
case 1:
qglTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE,
lm->width, lm->height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE,
lightmap[i]->lightmaps);
break;
}
}
}
#endif