X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=gl_backend.c;h=61e5291e748b104f4aac39ee45ad47316062f8fd;hb=212a93f6f5c06d50d331d61e1792d12f11ca1595;hp=6fc886ba0052b212304e5857536ddbcc4928ec79;hpb=f7b0c61e168f52b255e42a9cf26e87bf7be6fc41;p=xonotic%2Fdarkplaces.git diff --git a/gl_backend.c b/gl_backend.c index 6fc886ba..61e5291e 100644 --- a/gl_backend.c +++ b/gl_backend.c @@ -8,11 +8,98 @@ extern LPDIRECT3DDEVICE9 vid_d3d9dev; extern D3DCAPS9 vid_d3d9caps; #endif +// on GLES we have to use some proper #define's +#ifndef GL_FRAMEBUFFER +#define GL_FRAMEBUFFER 0x8D40 +#define GL_DEPTH_ATTACHMENT 0x8D00 +#define GL_COLOR_ATTACHMENT0 0x8CE0 +#define GL_INVALID_FRAMEBUFFER_OPERATION 0x0506 +#endif +#ifndef GL_COLOR_ATTACHMENT1 +#define GL_COLOR_ATTACHMENT1 0x8CE1 +#define GL_COLOR_ATTACHMENT2 0x8CE2 +#define GL_COLOR_ATTACHMENT3 0x8CE3 +#define GL_COLOR_ATTACHMENT4 0x8CE4 +#define GL_COLOR_ATTACHMENT5 0x8CE5 +#define GL_COLOR_ATTACHMENT6 0x8CE6 +#define GL_COLOR_ATTACHMENT7 0x8CE7 +#define GL_COLOR_ATTACHMENT8 0x8CE8 +#define GL_COLOR_ATTACHMENT9 0x8CE9 +#define GL_COLOR_ATTACHMENT10 0x8CEA +#define GL_COLOR_ATTACHMENT11 0x8CEB +#define GL_COLOR_ATTACHMENT12 0x8CEC +#define GL_COLOR_ATTACHMENT13 0x8CED +#define GL_COLOR_ATTACHMENT14 0x8CEE +#define GL_COLOR_ATTACHMENT15 0x8CEF +#endif +#ifndef GL_ARRAY_BUFFER +#define GL_ARRAY_BUFFER 0x8892 +#define GL_ELEMENT_ARRAY_BUFFER 0x8893 +#endif +//#ifndef GL_VERTEX_ARRAY +//#define GL_VERTEX_ARRAY 0x8074 +//#define GL_COLOR_ARRAY 0x8076 +//#define GL_TEXTURE_COORD_ARRAY 0x8078 +//#endif +#ifndef GL_TEXTURE0 +#define GL_TEXTURE0 0x84C0 +#define GL_TEXTURE1 0x84C1 +#define GL_TEXTURE2 0x84C2 +#define GL_TEXTURE3 0x84C3 +#define GL_TEXTURE4 0x84C4 +#define GL_TEXTURE5 0x84C5 +#define GL_TEXTURE6 0x84C6 +#define GL_TEXTURE7 0x84C7 +#define GL_TEXTURE8 0x84C8 +#define GL_TEXTURE9 0x84C9 +#define GL_TEXTURE10 0x84CA +#define GL_TEXTURE11 0x84CB +#define GL_TEXTURE12 0x84CC +#define GL_TEXTURE13 0x84CD +#define GL_TEXTURE14 0x84CE +#define GL_TEXTURE15 0x84CF +#define GL_TEXTURE16 0x84D0 +#define GL_TEXTURE17 0x84D1 +#define GL_TEXTURE18 0x84D2 +#define GL_TEXTURE19 0x84D3 +#define GL_TEXTURE20 0x84D4 +#define GL_TEXTURE21 0x84D5 +#define GL_TEXTURE22 0x84D6 +#define GL_TEXTURE23 0x84D7 +#define GL_TEXTURE24 0x84D8 +#define GL_TEXTURE25 0x84D9 +#define GL_TEXTURE26 0x84DA +#define GL_TEXTURE27 0x84DB +#define GL_TEXTURE28 0x84DC +#define GL_TEXTURE29 0x84DD +#define GL_TEXTURE30 0x84DE +#define GL_TEXTURE31 0x84DF +#endif + +#ifndef GL_TEXTURE_3D +#define GL_TEXTURE_3D 0x806F +#endif +#ifndef GL_TEXTURE_CUBE_MAP +#define GL_TEXTURE_CUBE_MAP 0x8513 +#endif +//#ifndef GL_MODELVIEW +//#define GL_MODELVIEW 0x1700 +//#endif +//#ifndef GL_PROJECTION +//#define GL_PROJECTION 0x1701 +//#endif +//#ifndef GL_DECAL +//#define GL_DECAL 0x2101 +//#endif +//#ifndef GL_INTERPOLATE +//#define GL_INTERPOLATE 0x8575 +//#endif + + #define MAX_RENDERTARGETS 4 cvar_t gl_mesh_drawrangeelements = {0, "gl_mesh_drawrangeelements", "1", "use glDrawRangeElements function if available instead of glDrawElements (for performance comparisons or bug testing)"}; cvar_t gl_mesh_testmanualfeeding = {0, "gl_mesh_testmanualfeeding", "0", "use glBegin(GL_TRIANGLES);glTexCoord2f();glVertex3f();glEnd(); primitives instead of glDrawElements (useful to test for driver bugs with glDrawElements)"}; -cvar_t gl_mesh_prefer_short_elements = {CVAR_SAVE, "gl_mesh_prefer_short_elements", "1", "use GL_UNSIGNED_SHORT element arrays instead of GL_UNSIGNED_INT"}; cvar_t gl_paranoid = {0, "gl_paranoid", "0", "enables OpenGL error checking and other tests"}; cvar_t gl_printcheckerror = {0, "gl_printcheckerror", "0", "prints all OpenGL error checks, useful to identify location of driver crashes"}; @@ -43,7 +130,7 @@ int gl_maxdrawrangeelementsvertices; int gl_maxdrawrangeelementsindices; #ifdef DEBUGGL -int errornumber = 0; +int gl_errornumber = 0; void GL_PrintError(int errornumber, const char *filename, int linenumber) { @@ -84,8 +171,8 @@ void GL_PrintError(int errornumber, const char *filename, int linenumber) Con_Printf("GL_TABLE_TOO_LARGE at %s:%i\n", filename, linenumber); break; #endif -#ifdef GL_INVALID_FRAMEBUFFER_OPERATION_EXT - case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: +#ifdef GL_INVALID_FRAMEBUFFER_OPERATION + case GL_INVALID_FRAMEBUFFER_OPERATION: Con_Printf("GL_INVALID_FRAMEBUFFER_OPERATION at %s:%i\n", filename, linenumber); break; #endif @@ -137,6 +224,7 @@ typedef struct gl_state_s int alphatest; int alphafunc; float alphafuncvalue; + qboolean alphatocoverage; int scissortest; unsigned int unit; unsigned int clientunit; @@ -146,6 +234,7 @@ typedef struct gl_state_s int lockrange_count; int vertexbufferobject; int elementbufferobject; + int uniformbufferobject; int framebufferobject; int defaultframebufferobject; // deal with platforms that use a non-zero default fbo qboolean pointer_color_enabled; @@ -166,13 +255,10 @@ typedef struct gl_state_s void *preparevertices_tempdata; size_t preparevertices_tempdatamaxsize; - r_meshbuffer_t *preparevertices_dynamicvertexbuffer; r_vertexgeneric_t *preparevertices_vertexgeneric; r_vertexmesh_t *preparevertices_vertexmesh; int preparevertices_numvertices; - r_meshbuffer_t *draw_dynamicindexbuffer; - qboolean usevbo_staticvertex; qboolean usevbo_staticindex; qboolean usevbo_dynamicvertex; @@ -191,7 +277,7 @@ typedef struct gl_state_s IDirect3DSurface9 *d3drt_backbuffercolorsurface; void *d3dvertexbuffer; void *d3dvertexdata; - size_t d3dvertexsize; + int d3dvertexsize; #endif } gl_state_t; @@ -258,7 +344,7 @@ unsigned short polygonelement3s[(POLYGONELEMENTS_MAXPOINTS-2)*3]; int quadelement3i[QUADELEMENTS_MAXQUADS*6]; unsigned short quadelement3s[QUADELEMENTS_MAXQUADS*6]; -void GL_VBOStats_f(void) +static void GL_VBOStats_f(void) { GL_Mesh_ListVBOs(true); } @@ -278,12 +364,12 @@ static void R_Mesh_SetUseVBO(void) case RENDERPATH_GLES1: gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo; gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && (gl_vbo.integer == 1 || gl_vbo.integer == 3)) || vid.forcevbo; - gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo; - gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo; + gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer && gl_vbo.integer) || vid.forcevbo; + gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer && gl_vbo.integer) || vid.forcevbo; break; case RENDERPATH_D3D9: gl_state.usevbo_staticvertex = gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo; - gl_state.usevbo_dynamicvertex = gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer && gl_vbo_dynamicindex.integer) || vid.forcevbo; + gl_state.usevbo_dynamicvertex = gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer && gl_vbo_dynamicindex.integer && gl_vbo.integer) || vid.forcevbo; break; case RENDERPATH_D3D10: Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); @@ -299,9 +385,9 @@ static void R_Mesh_SetUseVBO(void) break; case RENDERPATH_GLES2: gl_state.usevbo_staticvertex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo; - gl_state.usevbo_staticindex = false; + gl_state.usevbo_staticindex = (vid.support.arb_vertex_buffer_object && gl_vbo.integer) || vid.forcevbo; gl_state.usevbo_dynamicvertex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicvertex.integer) || vid.forcevbo; - gl_state.usevbo_dynamicindex = false; + gl_state.usevbo_dynamicindex = (vid.support.arb_vertex_buffer_object && gl_vbo_dynamicindex.integer) || vid.forcevbo; break; } } @@ -330,7 +416,7 @@ static void gl_backend_start(void) case RENDERPATH_GLES2: // fetch current fbo here (default fbo is not 0 on some GLES devices) if (vid.support.ext_framebuffer_object) - qglGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &gl_state.defaultframebufferobject); + qglGetIntegerv(GL_FRAMEBUFFER_BINDING, &gl_state.defaultframebufferobject); break; case RENDERPATH_D3D9: #ifdef SUPPORTD3D @@ -378,8 +464,6 @@ static void gl_backend_shutdown(void) if (gl_state.preparevertices_tempdata) Mem_Free(gl_state.preparevertices_tempdata); - if (gl_state.preparevertices_dynamicvertexbuffer) - R_Mesh_DestroyMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer); Mem_ExpandableArray_FreeArray(&gl_state.meshbufferarray); @@ -421,7 +505,7 @@ static void gl_backend_devicelost(void) Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); break; } - endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray); + endindex = (int)Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray); for (i = 0;i < endindex;i++) { buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i); @@ -524,7 +608,6 @@ void gl_backend_init(void) Cvar_RegisterVariable(&gl_mesh_drawrangeelements); Cvar_RegisterVariable(&gl_mesh_testmanualfeeding); - Cvar_RegisterVariable(&gl_mesh_prefer_short_elements); Cmd_AddCommand("gl_vbostats", GL_VBOStats_f, "prints a list of all buffer objects (vertex data and triangle elements) and total video memory used by them"); @@ -617,8 +700,6 @@ qboolean R_ScissorForBBox(const float *mins, const float *maxs, int *scissor) if (BoxesOverlap(r_refdef.view.origin, r_refdef.view.origin, mins, maxs)) return false; - x1 = y1 = x2 = y2 = 0; - // transform all corners that are infront of the nearclip plane VectorNegate(r_refdef.view.frustum[4].normal, plane4f); plane4f[3] = r_refdef.view.frustum[4].dist; @@ -1016,7 +1097,7 @@ void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatri m[14] = -2 * nearclip * farclip / (farclip - nearclip); Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]); - Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix); + Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix); Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix); if (nearplane) @@ -1025,15 +1106,15 @@ void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatri Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m); } -void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, int border, float nearclip, float farclip, const float *nearplane) +void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, int border, float nearclip, float farclip, const float *nearplane, int offsetx, int offsety) { matrix4x4_t tempmatrix, basematrix; float m[16]; memset(v, 0, sizeof(*v)); v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE; v->cameramatrix = *cameramatrix; - v->x = (side & 1) * size; - v->y = (side >> 1) * size; + v->x = offsetx + (side & 1) * size; + v->y = offsety + (side >> 1) * size; v->width = size; v->height = size; v->depth = 1; @@ -1044,7 +1125,7 @@ void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatri m[14] = -2 * nearclip * farclip / (farclip - nearclip); Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]); - Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix); + Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix); Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix); switch(vid.renderpath) @@ -1075,7 +1156,6 @@ void R_Viewport_InitRectSideView(r_viewport_t *v, const matrix4x4_t *cameramatri void R_SetViewport(const r_viewport_t *v) { - float m[16]; gl_viewport = *v; // FIXME: v_flipped_state is evil, this probably breaks somewhere @@ -1090,13 +1170,18 @@ void R_SetViewport(const r_viewport_t *v) case RENDERPATH_GL13: case RENDERPATH_GL11: case RENDERPATH_GLES1: - CHECKGLERROR - qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR - // Load the projection matrix into OpenGL - qglMatrixMode(GL_PROJECTION);CHECKGLERROR - Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m); - qglLoadMatrixf(m);CHECKGLERROR - qglMatrixMode(GL_MODELVIEW);CHECKGLERROR +#ifndef USE_GLES2 + { + float m[16]; + CHECKGLERROR + qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR + // Load the projection matrix into OpenGL + qglMatrixMode(GL_PROJECTION);CHECKGLERROR + Matrix4x4_ToArrayFloatGL(&gl_projectionmatrix, m); + qglLoadMatrixf(m);CHECKGLERROR + qglMatrixMode(GL_MODELVIEW);CHECKGLERROR + } +#endif break; case RENDERPATH_D3D9: #ifdef SUPPORTD3D @@ -1144,7 +1229,7 @@ static void GL_BindVBO(int bufferobject) { gl_state.vertexbufferobject = bufferobject; CHECKGLERROR - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR + qglBindBufferARB(GL_ARRAY_BUFFER, bufferobject);CHECKGLERROR } } @@ -1154,13 +1239,25 @@ static void GL_BindEBO(int bufferobject) { gl_state.elementbufferobject = bufferobject; CHECKGLERROR - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, bufferobject);CHECKGLERROR + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, bufferobject);CHECKGLERROR } } +static void GL_BindUBO(int bufferobject) +{ + if (gl_state.uniformbufferobject != bufferobject) + { + gl_state.uniformbufferobject = bufferobject; +#ifdef GL_UNIFORM_BUFFER + CHECKGLERROR + qglBindBufferARB(GL_UNIFORM_BUFFER, bufferobject);CHECKGLERROR +#endif + } +} + +static const GLuint drawbuffers[4] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3}; int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4) { - int temp; switch(vid.renderpath) { case RENDERPATH_GL11: @@ -1168,16 +1265,131 @@ int R_Mesh_CreateFramebufferObject(rtexture_t *depthtexture, rtexture_t *colorte case RENDERPATH_GL20: case RENDERPATH_GLES1: case RENDERPATH_GLES2: - if (!vid.support.ext_framebuffer_object) - return 0; - qglGenFramebuffersEXT(1, (GLuint*)&temp);CHECKGLERROR - R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL); - if (depthtexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, depthtexture->gltexturetypeenum, R_GetTexture(depthtexture), 0);CHECKGLERROR - if (colortexture) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, colortexture->gltexturetypeenum, R_GetTexture(colortexture), 0);CHECKGLERROR - if (colortexture2) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT1_EXT, colortexture2->gltexturetypeenum, R_GetTexture(colortexture2), 0);CHECKGLERROR - if (colortexture3) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT2_EXT, colortexture3->gltexturetypeenum, R_GetTexture(colortexture3), 0);CHECKGLERROR - if (colortexture4) qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT3_EXT, colortexture4->gltexturetypeenum, R_GetTexture(colortexture4), 0);CHECKGLERROR - return temp; + if (vid.support.arb_framebuffer_object) + { + int temp; + GLuint status; + qglGenFramebuffers(1, (GLuint*)&temp);CHECKGLERROR + R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL); + // GL_ARB_framebuffer_object (GL3-class hardware) - depth stencil attachment +#ifdef USE_GLES2 + // FIXME: separate stencil attachment on GLES + if (depthtexture && depthtexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR + if (depthtexture && depthtexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR +#else + if (depthtexture && depthtexture->texnum ) + { + qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR + if (depthtexture->glisdepthstencil) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR + } + if (depthtexture && depthtexture->renderbuffernum ) + { + qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR + if (depthtexture->glisdepthstencil) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR + } +#endif + if (colortexture && colortexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , colortexture->gltexturetypeenum , colortexture->texnum , 0);CHECKGLERROR + if (colortexture2 && colortexture2->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , colortexture2->gltexturetypeenum, colortexture2->texnum, 0);CHECKGLERROR + if (colortexture3 && colortexture3->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , colortexture3->gltexturetypeenum, colortexture3->texnum, 0);CHECKGLERROR + if (colortexture4 && colortexture4->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , colortexture4->gltexturetypeenum, colortexture4->texnum, 0);CHECKGLERROR + if (colortexture && colortexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER, colortexture->renderbuffernum );CHECKGLERROR + if (colortexture2 && colortexture2->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , GL_RENDERBUFFER, colortexture2->renderbuffernum);CHECKGLERROR + if (colortexture3 && colortexture3->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER, colortexture3->renderbuffernum);CHECKGLERROR + if (colortexture4 && colortexture4->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER, colortexture4->renderbuffernum);CHECKGLERROR + +#ifndef USE_GLES2 + if (colortexture4 && qglDrawBuffersARB) + { + qglDrawBuffersARB(4, drawbuffers);CHECKGLERROR + qglReadBuffer(GL_NONE);CHECKGLERROR + } + else if (colortexture3 && qglDrawBuffersARB) + { + qglDrawBuffersARB(3, drawbuffers);CHECKGLERROR + qglReadBuffer(GL_NONE);CHECKGLERROR + } + else if (colortexture2 && qglDrawBuffersARB) + { + qglDrawBuffersARB(2, drawbuffers);CHECKGLERROR + qglReadBuffer(GL_NONE);CHECKGLERROR + } + else if (colortexture && qglDrawBuffer) + { + qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR + qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR + } + else if (qglDrawBuffer) + { + qglDrawBuffer(GL_NONE);CHECKGLERROR + qglReadBuffer(GL_NONE);CHECKGLERROR + } +#endif + status = qglCheckFramebufferStatus(GL_FRAMEBUFFER);CHECKGLERROR + if (status != GL_FRAMEBUFFER_COMPLETE) + { + Con_Printf("R_Mesh_CreateFramebufferObject: glCheckFramebufferStatus returned %i\n", status); + gl_state.framebufferobject = 0; // GL unbinds it for us + qglDeleteFramebuffers(1, (GLuint*)&temp); + temp = 0; + } + return temp; + } + else if (vid.support.ext_framebuffer_object) + { + int temp; + GLuint status; + qglGenFramebuffers(1, (GLuint*)&temp);CHECKGLERROR + R_Mesh_SetRenderTargets(temp, NULL, NULL, NULL, NULL, NULL); + // GL_EXT_framebuffer_object (GL2-class hardware) - no depth stencil attachment, let it break stencil + if (depthtexture && depthtexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , depthtexture->gltexturetypeenum , depthtexture->texnum , 0);CHECKGLERROR + if (depthtexture && depthtexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER, depthtexture->renderbuffernum );CHECKGLERROR + if (colortexture && colortexture->texnum ) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , colortexture->gltexturetypeenum , colortexture->texnum , 0);CHECKGLERROR + if (colortexture2 && colortexture2->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , colortexture2->gltexturetypeenum, colortexture2->texnum, 0);CHECKGLERROR + if (colortexture3 && colortexture3->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , colortexture3->gltexturetypeenum, colortexture3->texnum, 0);CHECKGLERROR + if (colortexture4 && colortexture4->texnum) qglFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , colortexture4->gltexturetypeenum, colortexture4->texnum, 0);CHECKGLERROR + if (colortexture && colortexture->renderbuffernum ) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER, colortexture->renderbuffernum );CHECKGLERROR + if (colortexture2 && colortexture2->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1 , GL_RENDERBUFFER, colortexture2->renderbuffernum);CHECKGLERROR + if (colortexture3 && colortexture3->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT2 , GL_RENDERBUFFER, colortexture3->renderbuffernum);CHECKGLERROR + if (colortexture4 && colortexture4->renderbuffernum) qglFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3 , GL_RENDERBUFFER, colortexture4->renderbuffernum);CHECKGLERROR + +#ifndef USE_GLES2 + if (colortexture4 && qglDrawBuffersARB) + { + qglDrawBuffersARB(4, drawbuffers);CHECKGLERROR + qglReadBuffer(GL_NONE);CHECKGLERROR + } + else if (colortexture3 && qglDrawBuffersARB) + { + qglDrawBuffersARB(3, drawbuffers);CHECKGLERROR + qglReadBuffer(GL_NONE);CHECKGLERROR + } + else if (colortexture2 && qglDrawBuffersARB) + { + qglDrawBuffersARB(2, drawbuffers);CHECKGLERROR + qglReadBuffer(GL_NONE);CHECKGLERROR + } + else if (colortexture && qglDrawBuffer) + { + qglDrawBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR + qglReadBuffer(GL_COLOR_ATTACHMENT0);CHECKGLERROR + } + else if (qglDrawBuffer) + { + qglDrawBuffer(GL_NONE);CHECKGLERROR + qglReadBuffer(GL_NONE);CHECKGLERROR + } +#endif + status = qglCheckFramebufferStatus(GL_FRAMEBUFFER);CHECKGLERROR + if (status != GL_FRAMEBUFFER_COMPLETE) + { + Con_Printf("R_Mesh_CreateFramebufferObject: glCheckFramebufferStatus returned %i\n", status); + gl_state.framebufferobject = 0; // GL unbinds it for us + qglDeleteFramebuffers(1, (GLuint*)&temp); + temp = 0; + } + return temp; + } + return 0; case RENDERPATH_D3D9: case RENDERPATH_D3D10: case RENDERPATH_D3D11: @@ -1198,7 +1410,12 @@ void R_Mesh_DestroyFramebufferObject(int fbo) case RENDERPATH_GLES1: case RENDERPATH_GLES2: if (fbo) - qglDeleteFramebuffersEXT(1, (GLuint*)&fbo); + { + // GL clears the binding if we delete something bound + if (gl_state.framebufferobject == fbo) + gl_state.framebufferobject = 0; + qglDeleteFramebuffers(1, (GLuint*)&fbo); + } break; case RENDERPATH_D3D9: case RENDERPATH_D3D10: @@ -1212,10 +1429,6 @@ void R_Mesh_DestroyFramebufferObject(int fbo) #ifdef SUPPORTD3D void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3) { -// LordHavoc: for some weird reason the redundant SetDepthStencilSurface calls are necessary (otherwise the lights fail depth test, as if they were using the shadowmap depth surface and render target still) - if (gl_state.d3drt_depthsurface == depthsurface && gl_state.d3drt_colorsurfaces[0] == colorsurface0 && gl_state.d3drt_colorsurfaces[1] == colorsurface1 && gl_state.d3drt_colorsurfaces[2] == colorsurface2 && gl_state.d3drt_colorsurfaces[3] == colorsurface3) - return; - gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface; if (gl_state.d3drt_depthsurface != depthsurface) { @@ -1245,38 +1458,6 @@ void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurfa } #endif -void R_Mesh_ResetRenderTargets(void) -{ - switch(vid.renderpath) - { - case RENDERPATH_GL11: - case RENDERPATH_GL13: - case RENDERPATH_GL20: - case RENDERPATH_GLES1: - case RENDERPATH_GLES2: - if (gl_state.framebufferobject) - { - gl_state.framebufferobject = 0; - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject); - } - break; - case RENDERPATH_D3D9: -#ifdef SUPPORTD3D - R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL); -#endif - break; - case RENDERPATH_D3D10: - Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_D3D11: - Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); - break; - case RENDERPATH_SOFT: - DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL); - break; - } -} - void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4) { unsigned int i; @@ -1301,7 +1482,7 @@ void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colo if (gl_state.framebufferobject != fbo) { gl_state.framebufferobject = fbo; - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject); + qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject); } break; case RENDERPATH_D3D9: @@ -1310,19 +1491,24 @@ void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colo // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost if (fbo) { - IDirect3DSurface9 *colorsurfaces[4]; - for (i = 0;i < 4;i++) + IDirect3DSurface9 *surfaces[5]; + for (i = 0;i < 5;i++) { - colorsurfaces[i] = NULL; + surfaces[i] = NULL; if (textures[i]) - IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &colorsurfaces[i]); + { + if (textures[i]->d3dsurface) + surfaces[i] = (IDirect3DSurface9 *)textures[i]->d3dsurface; + else + IDirect3DTexture9_GetSurfaceLevel((IDirect3DTexture9 *)textures[i]->d3dtexture, 0, &surfaces[i]); + } } // set the render targets for real - R_Mesh_SetRenderTargetsD3D9(depthtexture ? (IDirect3DSurface9 *)depthtexture->d3dtexture : NULL, colorsurfaces[0], colorsurfaces[1], colorsurfaces[2], colorsurfaces[3]); + R_Mesh_SetRenderTargetsD3D9(surfaces[4], surfaces[0], surfaces[1], surfaces[2], surfaces[3]); // release the texture surface levels (they won't be lost while bound...) - for (i = 0;i < 4;i++) - if (textures[i]) - IDirect3DSurface9_Release(colorsurfaces[i]); + for (i = 0;i < 5;i++) + if (textures[i] && !textures[i]->d3dsurface) + IDirect3DSurface9_Release(surfaces[i]); } else R_Mesh_SetRenderTargetsD3D9(gl_state.d3drt_backbufferdepthsurface, gl_state.d3drt_backbuffercolorsurface, NULL, NULL, NULL); @@ -1381,8 +1567,6 @@ static int d3dstencilopforglfunc(int f) } #endif -extern cvar_t r_transparent_alphatocoverage; - static void GL_Backend_ResetState(void) { unsigned int i; @@ -1391,6 +1575,7 @@ static void GL_Backend_ResetState(void) gl_state.alphatest = false; gl_state.alphafunc = GL_GEQUAL; gl_state.alphafuncvalue = 0.5f; + gl_state.alphatocoverage = false; gl_state.blendfunc1 = GL_ONE; gl_state.blendfunc2 = GL_ZERO; gl_state.blend = false; @@ -1412,9 +1597,6 @@ static void GL_Backend_ResetState(void) #ifdef SUPPORTD3D { IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask); - IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest); - IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAFUNC, d3dcmpforglfunc(gl_state.alphafunc)); - IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHAREF, (int)bound(0, gl_state.alphafuncvalue * 256.0f, 255)); IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, D3DCULL_NONE); IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc)); IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest); @@ -1433,12 +1615,20 @@ static void GL_Backend_ResetState(void) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: +#ifndef USE_GLES2 CHECKGLERROR qglColorMask(1, 1, 1, 1);CHECKGLERROR qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR - qglDisable((vid_multisampling.integer && r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR - qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR + qglDisable(GL_ALPHA_TEST);CHECKGLERROR + if (qglBlendFuncSeparate) + { + qglBlendFuncSeparate(gl_state.blendfunc1, gl_state.blendfunc2, GL_ZERO, GL_ONE);CHECKGLERROR // ELUAN: Adreno 225 (and others) compositing workaround + } + else + { + qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR + } qglDisable(GL_BLEND);CHECKGLERROR qglCullFace(gl_state.cullface);CHECKGLERROR qglDisable(GL_CULL_FACE);CHECKGLERROR @@ -1449,14 +1639,14 @@ static void GL_Backend_ResetState(void) if (vid.support.arb_vertex_buffer_object) { - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + qglBindBufferARB(GL_ARRAY_BUFFER, 0); + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0); } if (vid.support.ext_framebuffer_object) { - //qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + //qglBindRenderbuffer(GL_RENDERBUFFER, 0); + qglBindFramebuffer(GL_FRAMEBUFFER, 0); } qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR @@ -1467,7 +1657,7 @@ static void GL_Backend_ResetState(void) qglColor4f(1, 1, 1, 1);CHECKGLERROR if (vid.support.ext_framebuffer_object) - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.framebufferobject); + qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.framebufferobject); gl_state.unit = MAX_TEXTUREUNITS; gl_state.clientunit = MAX_TEXTUREUNITS; @@ -1484,8 +1674,8 @@ static void GL_Backend_ResetState(void) } if (vid.support.arb_texture_cube_map) { - qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR - qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR + qglDisable(GL_TEXTURE_CUBE_MAP);CHECKGLERROR + qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR } GL_BindVBO(0); qglTexCoordPointer(2, GL_FLOAT, sizeof(float[2]), NULL);CHECKGLERROR @@ -1496,10 +1686,10 @@ static void GL_Backend_ResetState(void) qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR } CHECKGLERROR +#endif break; case RENDERPATH_SOFT: DPSOFTRAST_ColorMask(1,1,1,1); - DPSOFTRAST_AlphaTest(gl_state.alphatest); DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2); DPSOFTRAST_CullFace(gl_state.cullface); DPSOFTRAST_DepthFunc(gl_state.depthfunc); @@ -1520,18 +1710,13 @@ static void GL_Backend_ResetState(void) qglEnable(GL_DEPTH_TEST);CHECKGLERROR qglDepthMask(gl_state.depthmask);CHECKGLERROR qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]); - // if (vid.renderpath == RENDERPATH_GL20) - // { - // qglAlphaFunc(gl_state.alphafunc, gl_state.alphafuncvalue);CHECKGLERROR - // qglDisable(GL_ALPHA_TEST);CHECKGLERROR - // } if (vid.support.arb_vertex_buffer_object) { - qglBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); - qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + qglBindBufferARB(GL_ARRAY_BUFFER, 0); + qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0); } if (vid.support.ext_framebuffer_object) - qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, gl_state.defaultframebufferobject); + qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.defaultframebufferobject); qglEnableVertexAttribArray(GLSLATTRIB_POSITION); qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR qglDisableVertexAttribArray(GLSLATTRIB_COLOR); @@ -1549,7 +1734,7 @@ static void GL_Backend_ResetState(void) } if (vid.support.arb_texture_cube_map) { - qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, 0);CHECKGLERROR + qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR } } for (i = 0;i < vid.texarrayunits;i++) @@ -1578,7 +1763,7 @@ void GL_ActiveTexture(unsigned int num) if (qglActiveTexture) { CHECKGLERROR - qglActiveTexture(GL_TEXTURE0_ARB + gl_state.unit); + qglActiveTexture(GL_TEXTURE0 + gl_state.unit); CHECKGLERROR } break; @@ -1602,12 +1787,14 @@ void GL_ClientActiveTexture(unsigned int num) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: +#ifndef USE_GLES2 if (qglActiveTexture) { CHECKGLERROR - qglClientActiveTexture(GL_TEXTURE0_ARB + gl_state.clientunit); + qglClientActiveTexture(GL_TEXTURE0 + gl_state.clientunit); CHECKGLERROR } +#endif break; case RENDERPATH_D3D9: case RENDERPATH_D3D10: @@ -1638,7 +1825,14 @@ void GL_BlendFunc(int blendfunc1, int blendfunc2) case RENDERPATH_GLES1: case RENDERPATH_GLES2: CHECKGLERROR - qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR + if (qglBlendFuncSeparate) + { + qglBlendFuncSeparate(gl_state.blendfunc1, gl_state.blendfunc2, GL_ZERO, GL_ONE);CHECKGLERROR // ELUAN: Adreno 225 (and others) compositing workaround + } + else + { + qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR + } if (gl_state.blend != blendenable) { gl_state.blend = blendenable; @@ -1818,7 +2012,11 @@ void GL_DepthRange(float nearfrac, float farfrac) case RENDERPATH_GL20: case RENDERPATH_GLES1: case RENDERPATH_GLES2: +#ifdef USE_GLES2 + qglDepthRangef(gl_state.depthrange[0], gl_state.depthrange[1]); +#else qglDepthRange(gl_state.depthrange[0], gl_state.depthrange[1]); +#endif break; case RENDERPATH_D3D9: #ifdef SUPPORTD3D @@ -1870,10 +2068,12 @@ void R_SetStencilSeparate(qboolean enable, int writemask, int frontfail, int fro qglStencilMask(writemask);CHECKGLERROR qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);CHECKGLERROR - qglStencilFuncSeparate(frontcompare, backcompare, comparereference, comparereference);CHECKGLERROR + qglStencilFuncSeparate(GL_FRONT, frontcompare, comparereference, comparereference);CHECKGLERROR + qglStencilFuncSeparate(GL_BACK, backcompare, comparereference, comparereference);CHECKGLERROR } else if (vid.support.ext_stencil_two_side) { +#if defined(GL_STENCIL_TEST_TWO_SIDE_EXT) && !defined(USE_GLES2) qglEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR qglActiveStencilFaceEXT(GL_FRONT);CHECKGLERROR qglStencilMask(writemask);CHECKGLERROR @@ -1883,6 +2083,7 @@ void R_SetStencilSeparate(qboolean enable, int writemask, int frontfail, int fro qglStencilMask(writemask);CHECKGLERROR qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR +#endif } break; case RENDERPATH_D3D9: @@ -1934,7 +2135,9 @@ void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass } if (vid.support.ext_stencil_two_side) { +#ifdef GL_STENCIL_TEST_TWO_SIDE_EXT qglDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);CHECKGLERROR +#endif } qglStencilMask(writemask);CHECKGLERROR qglStencilOp(fail, zfail, zpass);CHECKGLERROR @@ -2130,31 +2333,61 @@ void GL_AlphaTest(int state) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: +#ifdef GL_ALPHA_TEST // only fixed function uses alpha test, other paths use pixel kill capability in shaders CHECKGLERROR if (gl_state.alphatest) { - qglEnable((vid_multisampling.integer && r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR + qglEnable(GL_ALPHA_TEST);CHECKGLERROR } else { - qglDisable((vid_multisampling.integer && r_transparent_alphatocoverage.integer) ? GL_SAMPLE_ALPHA_TO_COVERAGE_ARB : GL_ALPHA_TEST);CHECKGLERROR + qglDisable(GL_ALPHA_TEST);CHECKGLERROR } - break; - case RENDERPATH_D3D9: -#ifdef SUPPORTD3D -// IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHATESTENABLE, gl_state.alphatest); #endif break; + case RENDERPATH_D3D9: case RENDERPATH_D3D10: - break; case RENDERPATH_D3D11: + case RENDERPATH_SOFT: + case RENDERPATH_GL20: + case RENDERPATH_GLES2: break; + } + } +} + +void GL_AlphaToCoverage(qboolean state) +{ + if (gl_state.alphatocoverage != state) + { + gl_state.alphatocoverage = state; + switch(vid.renderpath) + { + case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GLES1: + case RENDERPATH_GLES2: + case RENDERPATH_D3D9: + case RENDERPATH_D3D10: + case RENDERPATH_D3D11: case RENDERPATH_SOFT: -// DPSOFTRAST_AlphaTest(gl_state.alphatest); break; case RENDERPATH_GL20: - case RENDERPATH_GLES2: +#ifdef GL_SAMPLE_ALPHA_TO_COVERAGE_ARB + // alpha to coverage turns the alpha value of the pixel into 0%, 25%, 50%, 75% or 100% by masking the multisample fragments accordingly + CHECKGLERROR + if (gl_state.alphatocoverage) + { + qglEnable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR +// qglEnable(GL_MULTISAMPLE_ARB);CHECKGLERROR + } + else + { + qglDisable(GL_SAMPLE_ALPHA_TO_COVERAGE_ARB);CHECKGLERROR +// qglDisable(GL_MULTISAMPLE_ARB);CHECKGLERROR + } +#endif break; } } @@ -2208,9 +2441,11 @@ void GL_Color(float cr, float cg, float cb, float ca) case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: +#ifndef USE_GLES2 CHECKGLERROR qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]); CHECKGLERROR +#endif break; case RENDERPATH_D3D9: case RENDERPATH_D3D10: @@ -2304,7 +2539,8 @@ void GL_ScissorTest(int state) void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilvalue) { - static const float blackcolor[4] = {0, 0, 0, 0}; + // opaque black - if you want transparent black, you'll need to pass in a colorvalue + static const float blackcolor[4] = {0.0f, 0.0f, 0.0f, 1.0f}; // prevent warnings when trying to clear a buffer that does not exist if (!colorvalue) colorvalue = blackcolor; @@ -2327,7 +2563,11 @@ void GL_Clear(int mask, const float *colorvalue, float depthvalue, int stencilva } if (mask & GL_DEPTH_BUFFER_BIT) { +#ifdef USE_GLES2 + qglClearDepthf(depthvalue);CHECKGLERROR +#else qglClearDepth(depthvalue);CHECKGLERROR +#endif } if (mask & GL_STENCIL_BUFFER_BIT) { @@ -2365,8 +2605,30 @@ void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpi case RENDERPATH_GLES1: case RENDERPATH_GLES2: CHECKGLERROR +#ifndef GL_BGRA + { + int i; + int r; + // int g; + int b; + // int a; + qglReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR + for (i = 0;i < width * height * 4;i += 4) + { + r = outpixels[i+0]; + // g = outpixels[i+1]; + b = outpixels[i+2]; + // a = outpixels[i+3]; + outpixels[i+0] = b; + // outpixels[i+1] = g; + outpixels[i+2] = r; + // outpixels[i+3] = a; + } + } +#else qglReadPixels(x, y, width, height, GL_BGRA, GL_UNSIGNED_BYTE, outpixels);CHECKGLERROR - break; +#endif + break; case RENDERPATH_D3D9: #ifdef SUPPORTD3D { @@ -2419,7 +2681,7 @@ void GL_ReadPixelsBGRA(int x, int y, int width, int height, unsigned char *outpi void R_Mesh_Start(void) { BACKENDACTIVECHECK - R_Mesh_ResetRenderTargets(); + R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL); R_Mesh_SetUseVBO(); if (gl_printcheckerror.integer && !gl_paranoid.integer) { @@ -2428,7 +2690,7 @@ void R_Mesh_Start(void) } } -qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings) +static qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, const char *shadertype, int numstrings, const char **strings) { int shaderobject; int shadercompiled; @@ -2440,7 +2702,7 @@ qboolean GL_Backend_CompileShader(int programobject, GLenum shadertypeenum, cons qglCompileShader(shaderobject);CHECKGLERROR qglGetShaderiv(shaderobject, GL_COMPILE_STATUS, &shadercompiled);CHECKGLERROR qglGetShaderInfoLog(shaderobject, sizeof(compilelog), NULL, compilelog);CHECKGLERROR - if (compilelog[0] && (strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error") || strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning"))) + if (compilelog[0] && ((strstr(compilelog, "error") || strstr(compilelog, "ERROR") || strstr(compilelog, "Error")) || ((strstr(compilelog, "WARNING") || strstr(compilelog, "warning") || strstr(compilelog, "Warning")) && developer.integer) || developer_extra.integer)) { int i, j, pretextlines = 0; for (i = 0;i < numstrings - 1;i++) @@ -2478,15 +2740,17 @@ unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **ver qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD3, "Attrib_TexCoord3"); qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD4, "Attrib_TexCoord4"); qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD5, "Attrib_TexCoord5"); - qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_TexCoord6"); - qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_TexCoord7"); + qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD6, "Attrib_SkeletalIndex"); + qglBindAttribLocation(programobject, GLSLATTRIB_TEXCOORD7, "Attrib_SkeletalWeight"); +#ifndef USE_GLES2 if(vid.support.gl20shaders130) qglBindFragDataLocation(programobject, 0, "dp_FragColor"); +#endif if (vertexstrings_count && !GL_Backend_CompileShader(programobject, GL_VERTEX_SHADER, "vertex", vertexstrings_count, vertexstrings_list)) goto cleanup; -#ifdef GL_GEOMETRY_SHADER +#if defined(GL_GEOMETRY_SHADER) && !defined(USE_GLES2) if (geometrystrings_count && !GL_Backend_CompileShader(programobject, GL_GEOMETRY_SHADER, "geometry", geometrystrings_count, geometrystrings_list)) goto cleanup; #endif @@ -2497,10 +2761,13 @@ unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **ver qglLinkProgram(programobject);CHECKGLERROR qglGetProgramiv(programobject, GL_LINK_STATUS, &programlinked);CHECKGLERROR qglGetProgramInfoLog(programobject, sizeof(linklog), NULL, linklog);CHECKGLERROR + if (linklog[0]) { - if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning")) + + if (strstr(linklog, "error") || strstr(linklog, "ERROR") || strstr(linklog, "Error") || strstr(linklog, "WARNING") || strstr(linklog, "warning") || strstr(linklog, "Warning") || developer_extra.integer) Con_DPrintf("program link log:\n%s\n", linklog); + // software vertex shader is ok but software fragment shader is WAY // too slow, fail program if so. // NOTE: this string might be ATI specific, but that's ok because the @@ -2510,8 +2777,10 @@ unsigned int GL_Backend_CompileProgram(int vertexstrings_count, const char **ver if (strstr(linklog, "fragment shader will run in software")) programlinked = false; } + if (!programlinked) goto cleanup; + return programobject; cleanup: qglDeleteProgram(programobject);CHECKGLERROR @@ -2525,21 +2794,9 @@ void GL_Backend_FreeProgram(unsigned int prog) CHECKGLERROR } -void GL_Backend_RenumberElements(int *out, int count, const int *in, int offset) -{ - int i; - if (offset) - { - for (i = 0;i < count;i++) - *out++ = *in++ + offset; - } - else - memcpy(out, in, sizeof(*out) * count); -} - // renders triangles using vertices from the active arrays int paranoidblah = 0; -void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, size_t element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, size_t element3s_bufferoffset) +void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtriangles, const int *element3i, const r_meshbuffer_t *element3i_indexbuffer, int element3i_bufferoffset, const unsigned short *element3s, const r_meshbuffer_t *element3s_indexbuffer, int element3s_bufferoffset) { unsigned int numelements = numtriangles * 3; int bufferobject3i; @@ -2552,13 +2809,6 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri Con_DPrintf("R_Mesh_Draw(%d, %d, %d, %d, %8p, %8p, %8x, %8p, %8p, %8x);\n", firstvertex, numvertices, firsttriangle, numtriangles, (void *)element3i, (void *)element3i_indexbuffer, (int)element3i_bufferoffset, (void *)element3s, (void *)element3s_indexbuffer, (int)element3s_bufferoffset); return; } - if (!gl_mesh_prefer_short_elements.integer) - { - if (element3i) - element3s = NULL; - if (element3i_indexbuffer) - element3i_indexbuffer = NULL; - } // adjust the pointers for firsttriangle if (element3i) element3i += firsttriangle * 3; @@ -2593,34 +2843,20 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri if (element3s) { if (!element3s_indexbuffer && gl_state.usevbo_dynamicindex) - { - if (gl_state.draw_dynamicindexbuffer) - R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3s, numelements * sizeof(*element3s)); - else - gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3s, numelements * sizeof(*element3s), "temporary", true, true, true); - element3s_indexbuffer = gl_state.draw_dynamicindexbuffer; - element3s_bufferoffset = 0; - } + element3s_indexbuffer = R_BufferData_Store(numelements * sizeof(*element3s), (void *)element3s, R_BUFFERDATA_INDEX16, &element3s_bufferoffset); } else if (element3i) { if (!element3i_indexbuffer && gl_state.usevbo_dynamicindex) - { - if (gl_state.draw_dynamicindexbuffer) - R_Mesh_UpdateMeshBuffer(gl_state.draw_dynamicindexbuffer, (void *)element3i, numelements * sizeof(*element3i)); - else - gl_state.draw_dynamicindexbuffer = R_Mesh_CreateMeshBuffer((void *)element3i, numelements * sizeof(*element3i), "temporary", true, true, false); - element3i_indexbuffer = gl_state.draw_dynamicindexbuffer; - element3i_bufferoffset = 0; - } + element3i_indexbuffer = R_BufferData_Store(numelements * sizeof(*element3i), (void *)element3i, R_BUFFERDATA_INDEX32, &element3i_bufferoffset); } bufferobject3i = element3i_indexbuffer ? element3i_indexbuffer->bufferobject : 0; bufferoffset3i = element3i_bufferoffset; bufferobject3s = element3s_indexbuffer ? element3s_indexbuffer->bufferobject : 0; bufferoffset3s = element3s_bufferoffset; - r_refdef.stats.draws++; - r_refdef.stats.draws_vertices += numvertices; - r_refdef.stats.draws_elements += numelements; + r_refdef.stats[r_stat_draws]++; + r_refdef.stats[r_stat_draws_vertices] += numvertices; + r_refdef.stats[r_stat_draws_elements] += numelements; if (gl_paranoid.integer) { unsigned int i; @@ -2695,165 +2931,277 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri CHECKGLERROR if (gl_mesh_testmanualfeeding.integer) { +#ifndef USE_GLES2 unsigned int i, j, element; const GLfloat *p; qglBegin(GL_TRIANGLES); - for (i = 0;i < (unsigned int) numtriangles * 3;i++) + if(vid.renderpath == RENDERPATH_GL20) { - if (element3i) - element = element3i[i]; - else if (element3s) - element = element3s[i]; - else - element = firstvertex + i; - for (j = 0;j < vid.texarrayunits;j++) + for (i = 0;i < (unsigned int) numtriangles * 3;i++) { - if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled) + if (element3i) + element = element3i[i]; + else if (element3s) + element = element3s[i]; + else + element = firstvertex + i; + for (j = 0;j < vid.texarrayunits;j++) { - if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT) + if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled) { - p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride); - if (vid.texarrayunits > 1) + if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT) { + p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride); if (gl_state.units[j].pointer_texcoord_components == 4) - qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2], p[3]); + qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1], p[2], p[3]); else if (gl_state.units[j].pointer_texcoord_components == 3) - qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, p[0], p[1], p[2]); + qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1], p[2]); else if (gl_state.units[j].pointer_texcoord_components == 2) - qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, p[0], p[1]); + qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, p[0], p[1]); else - qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, p[0]); + qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, p[0]); } - else + else if (gl_state.units[j].pointer_texcoord_gltype == (int)(GL_SHORT | 0x80000000)) { + const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride); if (gl_state.units[j].pointer_texcoord_components == 4) - qglTexCoord4f(p[0], p[1], p[2], p[3]); + qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1], s[2], s[3]); else if (gl_state.units[j].pointer_texcoord_components == 3) - qglTexCoord3f(p[0], p[1], p[2]); + qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1], s[2]); else if (gl_state.units[j].pointer_texcoord_components == 2) - qglTexCoord2f(p[0], p[1]); - else - qglTexCoord1f(p[0]); - } - } - else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT) - { - const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride); - if (vid.texarrayunits > 1) - { - if (gl_state.units[j].pointer_texcoord_components == 4) - qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2], s[3]); - else if (gl_state.units[j].pointer_texcoord_components == 3) - qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, s[0], s[1], s[2]); - else if (gl_state.units[j].pointer_texcoord_components == 2) - qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, s[0], s[1]); + qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, s[0], s[1]); else if (gl_state.units[j].pointer_texcoord_components == 1) - qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, s[0]); + qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, s[0]); } - else + else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE) { + const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride); if (gl_state.units[j].pointer_texcoord_components == 4) - qglTexCoord4f(s[0], s[1], s[2], s[3]); + qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 127.0f), sb[1] * (1.0f / 127.0f), sb[2] * (1.0f / 127.0f), sb[3] * (1.0f / 127.0f)); else if (gl_state.units[j].pointer_texcoord_components == 3) - qglTexCoord3f(s[0], s[1], s[2]); + qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 127.0f), sb[1] * (1.0f / 127.0f), sb[2] * (1.0f / 127.0f)); else if (gl_state.units[j].pointer_texcoord_components == 2) - qglTexCoord2f(s[0], s[1]); + qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 127.0f), sb[1] * (1.0f / 127.0f)); else if (gl_state.units[j].pointer_texcoord_components == 1) - qglTexCoord1f(s[0]); + qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 127.0f)); } - } - else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE) - { - const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride); - if (vid.texarrayunits > 1) + else if (gl_state.units[j].pointer_texcoord_gltype == GL_UNSIGNED_BYTE) { + const GLubyte *sb = (const GLubyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride); if (gl_state.units[j].pointer_texcoord_components == 4) - qglMultiTexCoord4f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2], sb[3]); + qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 255.0f), sb[1] * (1.0f / 255.0f), sb[2] * (1.0f / 255.0f), sb[3] * (1.0f / 255.0f)); else if (gl_state.units[j].pointer_texcoord_components == 3) - qglMultiTexCoord3f(GL_TEXTURE0_ARB + j, sb[0], sb[1], sb[2]); + qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 255.0f), sb[1] * (1.0f / 255.0f), sb[2] * (1.0f / 255.0f)); else if (gl_state.units[j].pointer_texcoord_components == 2) - qglMultiTexCoord2f(GL_TEXTURE0_ARB + j, sb[0], sb[1]); + qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 255.0f), sb[1] * (1.0f / 255.0f)); else if (gl_state.units[j].pointer_texcoord_components == 1) - qglMultiTexCoord1f(GL_TEXTURE0_ARB + j, sb[0]); + qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, sb[0] * (1.0f / 255.0f)); } - else + else if (gl_state.units[j].pointer_texcoord_gltype == (int)(GL_UNSIGNED_BYTE | 0x80000000)) { + const GLubyte *sb = (const GLubyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride); if (gl_state.units[j].pointer_texcoord_components == 4) - qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]); + qglVertexAttrib4f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1], sb[2], sb[3]); else if (gl_state.units[j].pointer_texcoord_components == 3) - qglTexCoord3f(sb[0], sb[1], sb[2]); + qglVertexAttrib3f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1], sb[2]); else if (gl_state.units[j].pointer_texcoord_components == 2) - qglTexCoord2f(sb[0], sb[1]); + qglVertexAttrib2f(GLSLATTRIB_TEXCOORD0 + j, sb[0], sb[1]); else if (gl_state.units[j].pointer_texcoord_components == 1) - qglTexCoord1f(sb[0]); + qglVertexAttrib1f(GLSLATTRIB_TEXCOORD0 + j, sb[0]); } } } - } - if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4) - { - if (gl_state.pointer_color_gltype == GL_FLOAT) + if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4) { - p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride); - qglColor4f(p[0], p[1], p[2], p[3]); + if (gl_state.pointer_color_gltype == GL_FLOAT) + { + p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride); + qglVertexAttrib4f(GLSLATTRIB_COLOR, p[0], p[1], p[2], p[3]); + } + else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE) + { + const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride); + qglVertexAttrib4Nub(GLSLATTRIB_COLOR, ub[0], ub[1], ub[2], ub[3]); + } } - else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE) + if (gl_state.pointer_vertex_gltype == GL_FLOAT) { - const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride); - qglColor4ub(ub[0], ub[1], ub[2], ub[3]); + p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride); + if (gl_state.pointer_vertex_components == 4) + qglVertexAttrib4f(GLSLATTRIB_POSITION, p[0], p[1], p[2], p[3]); + else if (gl_state.pointer_vertex_components == 3) + qglVertexAttrib3f(GLSLATTRIB_POSITION, p[0], p[1], p[2]); + else + qglVertexAttrib2f(GLSLATTRIB_POSITION, p[0], p[1]); } } - if (gl_state.pointer_vertex_gltype == GL_FLOAT) + } + else + { + for (i = 0;i < (unsigned int) numtriangles * 3;i++) { - p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride); - if (gl_state.pointer_vertex_components == 4) - qglVertex4f(p[0], p[1], p[2], p[3]); - else if (gl_state.pointer_vertex_components == 3) - qglVertex3f(p[0], p[1], p[2]); + if (element3i) + element = element3i[i]; + else if (element3s) + element = element3s[i]; else - qglVertex2f(p[0], p[1]); + element = firstvertex + i; + for (j = 0;j < vid.texarrayunits;j++) + { + if (gl_state.units[j].pointer_texcoord_pointer && gl_state.units[j].arrayenabled) + { + if (gl_state.units[j].pointer_texcoord_gltype == GL_FLOAT) + { + p = (const GLfloat *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride); + if (vid.texarrayunits > 1) + { + if (gl_state.units[j].pointer_texcoord_components == 4) + qglMultiTexCoord4f(GL_TEXTURE0 + j, p[0], p[1], p[2], p[3]); + else if (gl_state.units[j].pointer_texcoord_components == 3) + qglMultiTexCoord3f(GL_TEXTURE0 + j, p[0], p[1], p[2]); + else if (gl_state.units[j].pointer_texcoord_components == 2) + qglMultiTexCoord2f(GL_TEXTURE0 + j, p[0], p[1]); + else + qglMultiTexCoord1f(GL_TEXTURE0 + j, p[0]); + } + else + { + if (gl_state.units[j].pointer_texcoord_components == 4) + qglTexCoord4f(p[0], p[1], p[2], p[3]); + else if (gl_state.units[j].pointer_texcoord_components == 3) + qglTexCoord3f(p[0], p[1], p[2]); + else if (gl_state.units[j].pointer_texcoord_components == 2) + qglTexCoord2f(p[0], p[1]); + else + qglTexCoord1f(p[0]); + } + } + else if (gl_state.units[j].pointer_texcoord_gltype == GL_SHORT) + { + const GLshort *s = (const GLshort *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride); + if (vid.texarrayunits > 1) + { + if (gl_state.units[j].pointer_texcoord_components == 4) + qglMultiTexCoord4f(GL_TEXTURE0 + j, s[0], s[1], s[2], s[3]); + else if (gl_state.units[j].pointer_texcoord_components == 3) + qglMultiTexCoord3f(GL_TEXTURE0 + j, s[0], s[1], s[2]); + else if (gl_state.units[j].pointer_texcoord_components == 2) + qglMultiTexCoord2f(GL_TEXTURE0 + j, s[0], s[1]); + else if (gl_state.units[j].pointer_texcoord_components == 1) + qglMultiTexCoord1f(GL_TEXTURE0 + j, s[0]); + } + else + { + if (gl_state.units[j].pointer_texcoord_components == 4) + qglTexCoord4f(s[0], s[1], s[2], s[3]); + else if (gl_state.units[j].pointer_texcoord_components == 3) + qglTexCoord3f(s[0], s[1], s[2]); + else if (gl_state.units[j].pointer_texcoord_components == 2) + qglTexCoord2f(s[0], s[1]); + else if (gl_state.units[j].pointer_texcoord_components == 1) + qglTexCoord1f(s[0]); + } + } + else if (gl_state.units[j].pointer_texcoord_gltype == GL_BYTE) + { + const GLbyte *sb = (const GLbyte *)((const unsigned char *)gl_state.units[j].pointer_texcoord_pointer + element * gl_state.units[j].pointer_texcoord_stride); + if (vid.texarrayunits > 1) + { + if (gl_state.units[j].pointer_texcoord_components == 4) + qglMultiTexCoord4f(GL_TEXTURE0 + j, sb[0], sb[1], sb[2], sb[3]); + else if (gl_state.units[j].pointer_texcoord_components == 3) + qglMultiTexCoord3f(GL_TEXTURE0 + j, sb[0], sb[1], sb[2]); + else if (gl_state.units[j].pointer_texcoord_components == 2) + qglMultiTexCoord2f(GL_TEXTURE0 + j, sb[0], sb[1]); + else if (gl_state.units[j].pointer_texcoord_components == 1) + qglMultiTexCoord1f(GL_TEXTURE0 + j, sb[0]); + } + else + { + if (gl_state.units[j].pointer_texcoord_components == 4) + qglTexCoord4f(sb[0], sb[1], sb[2], sb[3]); + else if (gl_state.units[j].pointer_texcoord_components == 3) + qglTexCoord3f(sb[0], sb[1], sb[2]); + else if (gl_state.units[j].pointer_texcoord_components == 2) + qglTexCoord2f(sb[0], sb[1]); + else if (gl_state.units[j].pointer_texcoord_components == 1) + qglTexCoord1f(sb[0]); + } + } + } + } + if (gl_state.pointer_color_pointer && gl_state.pointer_color_enabled && gl_state.pointer_color_components == 4) + { + if (gl_state.pointer_color_gltype == GL_FLOAT) + { + p = (const GLfloat *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride); + qglColor4f(p[0], p[1], p[2], p[3]); + } + else if (gl_state.pointer_color_gltype == GL_UNSIGNED_BYTE) + { + const GLubyte *ub = (const GLubyte *)((const unsigned char *)gl_state.pointer_color_pointer + element * gl_state.pointer_color_stride); + qglColor4ub(ub[0], ub[1], ub[2], ub[3]); + } + } + if (gl_state.pointer_vertex_gltype == GL_FLOAT) + { + p = (const GLfloat *)((const unsigned char *)gl_state.pointer_vertex_pointer + element * gl_state.pointer_vertex_stride); + if (gl_state.pointer_vertex_components == 4) + qglVertex4f(p[0], p[1], p[2], p[3]); + else if (gl_state.pointer_vertex_components == 3) + qglVertex3f(p[0], p[1], p[2]); + else + qglVertex2f(p[0], p[1]); + } } } qglEnd(); CHECKGLERROR +#endif } else if (bufferobject3s) { GL_BindEBO(bufferobject3s); +#ifndef USE_GLES2 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) { qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s); CHECKGLERROR } else +#endif { - qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)(firsttriangle * sizeof(unsigned short[3]))); + qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s); CHECKGLERROR } } else if (bufferobject3i) { GL_BindEBO(bufferobject3i); +#ifndef USE_GLES2 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) { qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i); CHECKGLERROR } else +#endif { - qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)(firsttriangle * sizeof(unsigned int[3]))); + qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i); CHECKGLERROR } } else if (element3s) { GL_BindEBO(0); +#ifndef USE_GLES2 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) { qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_SHORT, element3s); CHECKGLERROR } else +#endif { qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s); CHECKGLERROR @@ -2862,12 +3210,14 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri else if (element3i) { GL_BindEBO(0); +#ifndef USE_GLES2 if (gl_mesh_drawrangeelements.integer && qglDrawRangeElements != NULL) { qglDrawRangeElements(GL_TRIANGLES, firstvertex, firstvertex + numvertices - 1, numelements, GL_UNSIGNED_INT, element3i); CHECKGLERROR } else +#endif { qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i); CHECKGLERROR @@ -2918,44 +3268,28 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri break; case RENDERPATH_GLES1: case RENDERPATH_GLES2: - // GLES does not have glDrawRangeElements, and generally - // underperforms with index buffers, so this code path is - // relatively straightforward... -#if 0 - if (gl_paranoid.integer) + // GLES does not have glDrawRangeElements so this is a bit shorter than the GL20 path + if (bufferobject3s) { - int r, prog, enabled, i; - GLsizei attriblength; - GLint attribsize; - GLenum attribtype; - GLchar attribname[1024]; - r = qglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);CHECKGLERROR - if (r != GL_FRAMEBUFFER_COMPLETE_EXT) - Con_DPrintf("fbo %i not complete (default %i)\n", gl_state.framebufferobject, gl_state.defaultframebufferobject); -#ifndef GL_CURRENT_PROGRAM -#define GL_CURRENT_PROGRAM 0x8B8D -#endif - qglGetIntegerv(GL_CURRENT_PROGRAM, &r);CHECKGLERROR - if (r < 0 || r > 10000) - Con_DPrintf("GL_CURRENT_PROGRAM = %i\n", r); - prog = r; - for (i = 0;i < 8;i++) - { - qglGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &r);CHECKGLERROR - if (!r) - continue; - qglGetActiveAttrib(prog, i, sizeof(attribname), &attriblength, &attribsize, &attribtype, attribname);CHECKGLERROR - Con_DPrintf("prog %i position %i length %i size %04X type %i name \"%s\"\n", prog, i, (int)attriblength, (int)attribsize, (int)attribtype, (char *)attribname); - } + GL_BindEBO(bufferobject3s); + qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, (void *)bufferoffset3s); + CHECKGLERROR } -#endif - if (element3s) + else if (bufferobject3i) + { + GL_BindEBO(bufferobject3i); + qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, (void *)bufferoffset3i); + CHECKGLERROR + } + else if (element3s) { + GL_BindEBO(0); qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_SHORT, element3s); CHECKGLERROR } else if (element3i) { + GL_BindEBO(0); qglDrawElements(GL_TRIANGLES, numelements, GL_UNSIGNED_INT, element3i); CHECKGLERROR } @@ -2972,41 +3306,54 @@ void R_Mesh_Draw(int firstvertex, int numvertices, int firsttriangle, int numtri // restores backend state, used when done with 3D rendering void R_Mesh_Finish(void) { - R_Mesh_ResetRenderTargets(); + R_Mesh_SetRenderTargets(0, NULL, NULL, NULL, NULL, NULL); } -r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isdynamic, qboolean isindex16) +r_meshbuffer_t *R_Mesh_CreateMeshBuffer(const void *data, size_t size, const char *name, qboolean isindexbuffer, qboolean isuniformbuffer, qboolean isdynamic, qboolean isindex16) { r_meshbuffer_t *buffer; - if (!(isdynamic ? (isindexbuffer ? gl_state.usevbo_dynamicindex : gl_state.usevbo_dynamicvertex) : (isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex))) - return NULL; + if (isuniformbuffer) + { + if (!vid.support.arb_uniform_buffer_object) + return NULL; + } + else + { + if (!vid.support.arb_vertex_buffer_object) + return NULL; + if (!isdynamic && !(isindexbuffer ? gl_state.usevbo_staticindex : gl_state.usevbo_staticvertex)) + return NULL; + } buffer = (r_meshbuffer_t *)Mem_ExpandableArray_AllocRecord(&gl_state.meshbufferarray); memset(buffer, 0, sizeof(*buffer)); buffer->bufferobject = 0; buffer->devicebuffer = NULL; - buffer->size = 0; + buffer->size = size; buffer->isindexbuffer = isindexbuffer; + buffer->isuniformbuffer = isuniformbuffer; buffer->isdynamic = isdynamic; buffer->isindex16 = isindex16; strlcpy(buffer->name, name, sizeof(buffer->name)); - R_Mesh_UpdateMeshBuffer(buffer, data, size); + R_Mesh_UpdateMeshBuffer(buffer, data, size, false, 0); return buffer; } -void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size) +void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t size, qboolean subdata, size_t offset) { if (!buffer) return; if (buffer->isindexbuffer) { - r_refdef.stats.indexbufferuploadcount++; - r_refdef.stats.indexbufferuploadsize += size; + r_refdef.stats[r_stat_indexbufferuploadcount]++; + r_refdef.stats[r_stat_indexbufferuploadsize] += (int)size; } else { - r_refdef.stats.vertexbufferuploadcount++; - r_refdef.stats.vertexbufferuploadsize += size; + r_refdef.stats[r_stat_vertexbufferuploadcount]++; + r_refdef.stats[r_stat_vertexbufferuploadsize] += (int)size; } + if (!subdata) + buffer->size = size; switch(vid.renderpath) { case RENDERPATH_GL11: @@ -3016,11 +3363,27 @@ void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t si case RENDERPATH_GLES2: if (!buffer->bufferobject) qglGenBuffersARB(1, (GLuint *)&buffer->bufferobject); - if (buffer->isindexbuffer) + if (buffer->isuniformbuffer) + GL_BindUBO(buffer->bufferobject); + else if (buffer->isindexbuffer) GL_BindEBO(buffer->bufferobject); else GL_BindVBO(buffer->bufferobject); - qglBufferDataARB(buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER_ARB : GL_ARRAY_BUFFER_ARB, size, data, buffer->isdynamic ? GL_STREAM_DRAW_ARB : GL_STATIC_DRAW_ARB); + + { + int buffertype; + buffertype = buffer->isindexbuffer ? GL_ELEMENT_ARRAY_BUFFER : GL_ARRAY_BUFFER; +#ifdef GL_UNIFORM_BUFFER + if (buffer->isuniformbuffer) + buffertype = GL_UNIFORM_BUFFER; +#endif + if (subdata) + qglBufferSubDataARB(buffertype, offset, size, data); + else + qglBufferDataARB(buffertype, size, data, buffer->isdynamic ? GL_STREAM_DRAW : GL_STATIC_DRAW); + } + if (buffer->isuniformbuffer) + GL_BindUBO(0); break; case RENDERPATH_D3D9: #ifdef SUPPORTD3D @@ -3030,17 +3393,17 @@ void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t si if (buffer->isindexbuffer) { IDirect3DIndexBuffer9 *d3d9indexbuffer = (IDirect3DIndexBuffer9 *)buffer->devicebuffer; - if (size > buffer->size || !buffer->devicebuffer) + if (offset+size > buffer->size || !buffer->devicebuffer) { if (buffer->devicebuffer) IDirect3DIndexBuffer9_Release((IDirect3DIndexBuffer9*)buffer->devicebuffer); buffer->devicebuffer = NULL; - if (FAILED(result = IDirect3DDevice9_CreateIndexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, buffer->isindex16 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9indexbuffer, NULL))) + if (FAILED(result = IDirect3DDevice9_CreateIndexBuffer(vid_d3d9dev, (unsigned int)(offset+size), buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, buffer->isindex16 ? D3DFMT_INDEX16 : D3DFMT_INDEX32, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9indexbuffer, NULL))) Sys_Error("IDirect3DDevice9_CreateIndexBuffer(%p, %d, %x, %x, %x, %p, NULL) returned %x\n", vid_d3d9dev, (int)size, buffer->isdynamic ? (int)D3DUSAGE_DYNAMIC : 0, buffer->isindex16 ? (int)D3DFMT_INDEX16 : (int)D3DFMT_INDEX32, buffer->isdynamic ? (int)D3DPOOL_DEFAULT : (int)D3DPOOL_MANAGED, &d3d9indexbuffer, (int)result); buffer->devicebuffer = (void *)d3d9indexbuffer; - buffer->size = size; + buffer->size = offset+size; } - if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0))) + if (!FAILED(IDirect3DIndexBuffer9_Lock(d3d9indexbuffer, (unsigned int)offset, (unsigned int)size, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0))) { if (data) memcpy(datapointer, data, size); @@ -3052,17 +3415,17 @@ void R_Mesh_UpdateMeshBuffer(r_meshbuffer_t *buffer, const void *data, size_t si else { IDirect3DVertexBuffer9 *d3d9vertexbuffer = (IDirect3DVertexBuffer9 *)buffer->devicebuffer; - if (size > buffer->size || !buffer->devicebuffer) + if (offset+size > buffer->size || !buffer->devicebuffer) { if (buffer->devicebuffer) IDirect3DVertexBuffer9_Release((IDirect3DVertexBuffer9*)buffer->devicebuffer); buffer->devicebuffer = NULL; - if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, size, buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL))) + if (FAILED(result = IDirect3DDevice9_CreateVertexBuffer(vid_d3d9dev, (unsigned int)(offset+size), buffer->isdynamic ? D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? D3DPOOL_DEFAULT : D3DPOOL_MANAGED, &d3d9vertexbuffer, NULL))) Sys_Error("IDirect3DDevice9_CreateVertexBuffer(%p, %d, %x, %x, %x, %p, NULL) returned %x\n", vid_d3d9dev, (int)size, buffer->isdynamic ? (int)D3DUSAGE_DYNAMIC : 0, 0, buffer->isdynamic ? (int)D3DPOOL_DEFAULT : (int)D3DPOOL_MANAGED, &d3d9vertexbuffer, (int)result); buffer->devicebuffer = (void *)d3d9vertexbuffer; - buffer->size = size; + buffer->size = offset+size; } - if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, 0, 0, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0))) + if (!FAILED(IDirect3DVertexBuffer9_Lock(d3d9vertexbuffer, (unsigned int)offset, (unsigned int)size, &datapointer, buffer->isdynamic ? D3DLOCK_DISCARD : 0))) { if (data) memcpy(datapointer, data, size); @@ -3096,6 +3459,13 @@ void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer) case RENDERPATH_GL20: case RENDERPATH_GLES1: case RENDERPATH_GLES2: + // GL clears the binding if we delete something bound + if (gl_state.uniformbufferobject == buffer->bufferobject) + gl_state.uniformbufferobject = 0; + if (gl_state.vertexbufferobject == buffer->bufferobject) + gl_state.vertexbufferobject = 0; + if (gl_state.elementbufferobject == buffer->bufferobject) + gl_state.elementbufferobject = 0; qglDeleteBuffersARB(1, (GLuint *)&buffer->bufferobject); break; case RENDERPATH_D3D9: @@ -3124,22 +3494,51 @@ void R_Mesh_DestroyMeshBuffer(r_meshbuffer_t *buffer) Mem_ExpandableArray_FreeRecord(&gl_state.meshbufferarray, (void *)buffer); } +static const char *buffertypename[R_BUFFERDATA_COUNT] = {"vertex", "index16", "index32", "uniform"}; void GL_Mesh_ListVBOs(qboolean printeach) { int i, endindex; - size_t ebocount = 0, ebomemory = 0; - size_t vbocount = 0, vbomemory = 0; + int type; + int isdynamic; + int index16count, index16mem; + int index32count, index32mem; + int vertexcount, vertexmem; + int uniformcount, uniformmem; + int totalcount, totalmem; + size_t bufferstat[R_BUFFERDATA_COUNT][2][2]; r_meshbuffer_t *buffer; - endindex = Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray); + memset(bufferstat, 0, sizeof(bufferstat)); + endindex = (int)Mem_ExpandableArray_IndexRange(&gl_state.meshbufferarray); for (i = 0;i < endindex;i++) { buffer = (r_meshbuffer_t *) Mem_ExpandableArray_RecordAtIndex(&gl_state.meshbufferarray, i); if (!buffer) continue; - if (buffer->isindexbuffer) {ebocount++;ebomemory += buffer->size;if (printeach) Con_Printf("indexbuffer #%i %s = %i bytes%s\n", i, buffer->name, (int)buffer->size, buffer->isdynamic ? " (dynamic)" : " (static)");} - else {vbocount++;vbomemory += buffer->size;if (printeach) Con_Printf("vertexbuffer #%i %s = %i bytes%s\n", i, buffer->name, (int)buffer->size, buffer->isdynamic ? " (dynamic)" : " (static)");} + if (buffer->isuniformbuffer) + type = R_BUFFERDATA_UNIFORM; + else if (buffer->isindexbuffer && buffer->isindex16) + type = R_BUFFERDATA_INDEX16; + else if (buffer->isindexbuffer) + type = R_BUFFERDATA_INDEX32; + else + type = R_BUFFERDATA_VERTEX; + isdynamic = buffer->isdynamic; + bufferstat[type][isdynamic][0]++; + bufferstat[type][isdynamic][1] += buffer->size; + if (printeach) + Con_Printf("buffer #%i %s = %i bytes (%s %s)\n", i, buffer->name, (int)buffer->size, isdynamic ? "dynamic" : "static", buffertypename[type]); } - Con_Printf("vertex buffers: %i indexbuffers totalling %i bytes (%.3f MB), %i vertexbuffers totalling %i bytes (%.3f MB), combined %i bytes (%.3fMB)\n", (int)ebocount, (int)ebomemory, ebomemory / 1048576.0, (int)vbocount, (int)vbomemory, vbomemory / 1048576.0, (int)(ebomemory + vbomemory), (ebomemory + vbomemory) / 1048576.0); + index16count = (int)(bufferstat[R_BUFFERDATA_INDEX16][0][0] + bufferstat[R_BUFFERDATA_INDEX16][1][0]); + index16mem = (int)(bufferstat[R_BUFFERDATA_INDEX16][0][1] + bufferstat[R_BUFFERDATA_INDEX16][1][1]); + index32count = (int)(bufferstat[R_BUFFERDATA_INDEX32][0][0] + bufferstat[R_BUFFERDATA_INDEX32][1][0]); + index32mem = (int)(bufferstat[R_BUFFERDATA_INDEX32][0][1] + bufferstat[R_BUFFERDATA_INDEX32][1][1]); + vertexcount = (int)(bufferstat[R_BUFFERDATA_VERTEX ][0][0] + bufferstat[R_BUFFERDATA_VERTEX ][1][0]); + vertexmem = (int)(bufferstat[R_BUFFERDATA_VERTEX ][0][1] + bufferstat[R_BUFFERDATA_VERTEX ][1][1]); + uniformcount = (int)(bufferstat[R_BUFFERDATA_UNIFORM][0][0] + bufferstat[R_BUFFERDATA_UNIFORM][1][0]); + uniformmem = (int)(bufferstat[R_BUFFERDATA_UNIFORM][0][1] + bufferstat[R_BUFFERDATA_UNIFORM][1][1]); + totalcount = index16count + index32count + vertexcount + uniformcount; + totalmem = index16mem + index32mem + vertexmem + uniformmem; + Con_Printf("%i 16bit indexbuffers totalling %i bytes (%.3f MB)\n%i 32bit indexbuffers totalling %i bytes (%.3f MB)\n%i vertexbuffers totalling %i bytes (%.3f MB)\n%i uniformbuffers totalling %i bytes (%.3f MB)\ncombined %i buffers totalling %i bytes (%.3fMB)\n", index16count, index16mem, index16mem / 10248576.0, index32count, index32mem, index32mem / 10248576.0, vertexcount, vertexmem, vertexmem / 10248576.0, uniformcount, uniformmem, uniformmem / 10248576.0, totalcount, totalmem, totalmem / 10248576.0); } @@ -3151,6 +3550,7 @@ void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: +#ifndef USE_GLES2 if (gl_state.pointer_vertex_components != components || gl_state.pointer_vertex_gltype != gltype || gl_state.pointer_vertex_stride != stride || gl_state.pointer_vertex_pointer != pointer || gl_state.pointer_vertex_vertexbuffer != vertexbuffer || gl_state.pointer_vertex_offset != bufferoffset) { int bufferobject = vertexbuffer ? vertexbuffer->bufferobject : 0; @@ -3162,8 +3562,9 @@ void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void gl_state.pointer_vertex_offset = bufferoffset; CHECKGLERROR GL_BindVBO(bufferobject); - qglVertexPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR + qglVertexPointer(components, gltype, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR } +#endif break; case RENDERPATH_GL20: case RENDERPATH_GLES2: @@ -3178,7 +3579,8 @@ void R_Mesh_VertexPointer(int components, int gltype, size_t stride, const void gl_state.pointer_vertex_offset = bufferoffset; CHECKGLERROR GL_BindVBO(bufferobject); - qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR + // LordHavoc: special flag added to gltype for unnormalized types + qglVertexAttribPointer(GLSLATTRIB_POSITION, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR } break; case RENDERPATH_D3D9: @@ -3198,6 +3600,7 @@ void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void * case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: +#ifndef USE_GLES2 CHECKGLERROR if (pointer) { @@ -3219,7 +3622,7 @@ void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void * gl_state.pointer_color_offset = bufferoffset; CHECKGLERROR GL_BindVBO(bufferobject); - qglColorPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR + qglColorPointer(components, gltype, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR } } else @@ -3234,6 +3637,7 @@ void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void * qglColor4f(gl_state.color4f[0], gl_state.color4f[1], gl_state.color4f[2], gl_state.color4f[3]);CHECKGLERROR } } +#endif break; case RENDERPATH_GL20: case RENDERPATH_GLES2: @@ -3258,7 +3662,8 @@ void R_Mesh_ColorPointer(int components, int gltype, size_t stride, const void * gl_state.pointer_color_offset = bufferoffset; CHECKGLERROR GL_BindVBO(bufferobject); - qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR + // LordHavoc: special flag added to gltype for unnormalized types + qglVertexAttribPointer(GLSLATTRIB_COLOR, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR } } else @@ -3293,6 +3698,7 @@ void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, si case RENDERPATH_GL11: case RENDERPATH_GL13: case RENDERPATH_GLES1: +#ifndef USE_GLES2 CHECKGLERROR if (pointer) { @@ -3315,7 +3721,7 @@ void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, si unit->pointer_texcoord_offset = bufferoffset; GL_ClientActiveTexture(unitnum); GL_BindVBO(bufferobject); - qglTexCoordPointer(components, gltype, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR + qglTexCoordPointer(components, gltype, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR } } else @@ -3328,6 +3734,7 @@ void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, si qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR } } +#endif break; case RENDERPATH_GL20: case RENDERPATH_GLES2: @@ -3351,7 +3758,8 @@ void R_Mesh_TexCoordPointer(unsigned int unitnum, int components, int gltype, si unit->pointer_texcoord_vertexbuffer = vertexbuffer; unit->pointer_texcoord_offset = bufferoffset; GL_BindVBO(bufferobject); - qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype, false, stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR + // LordHavoc: special flag added to gltype for unnormalized types + qglVertexAttribPointer(unitnum+GLSLATTRIB_TEXCOORD0, components, gltype & ~0x80000000, (gltype & 0x80000000) == 0, (GLsizei)stride, bufferobject ? (void *)bufferoffset : pointer);CHECKGLERROR } } else @@ -3381,7 +3789,7 @@ int R_Mesh_TexBound(unsigned int unitnum, int id) return unit->t2d; if (id == GL_TEXTURE_3D) return unit->t3d; - if (id == GL_TEXTURE_CUBE_MAP_ARB) + if (id == GL_TEXTURE_CUBE_MAP) return unit->tcubemap; return 0; } @@ -3484,7 +3892,7 @@ void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex) { case GL_TEXTURE_2D: if (unit->t2d != texnum) {GL_ActiveTexture(unitnum);unit->t2d = texnum;qglBindTexture(GL_TEXTURE_2D, unit->t2d);CHECKGLERROR}break; case GL_TEXTURE_3D: if (unit->t3d != texnum) {GL_ActiveTexture(unitnum);unit->t3d = texnum;qglBindTexture(GL_TEXTURE_3D, unit->t3d);CHECKGLERROR}break; - case GL_TEXTURE_CUBE_MAP_ARB: if (unit->tcubemap != texnum) {GL_ActiveTexture(unitnum);unit->tcubemap = texnum;qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR}break; + case GL_TEXTURE_CUBE_MAP: if (unit->tcubemap != texnum) {GL_ActiveTexture(unitnum);unit->tcubemap = texnum;qglBindTexture(GL_TEXTURE_CUBE_MAP, unit->tcubemap);CHECKGLERROR}break; } break; case RENDERPATH_GL11: @@ -3505,7 +3913,7 @@ void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex) case GL_TEXTURE_3D: tex3d = texnum; break; - case GL_TEXTURE_CUBE_MAP_ARB: + case GL_TEXTURE_CUBE_MAP: texcubemap = texnum; break; } @@ -3560,18 +3968,18 @@ void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex) { if (unit->tcubemap == 0) { - qglEnable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR + qglEnable(GL_TEXTURE_CUBE_MAP);CHECKGLERROR } } else { if (unit->tcubemap) { - qglDisable(GL_TEXTURE_CUBE_MAP_ARB);CHECKGLERROR + qglDisable(GL_TEXTURE_CUBE_MAP);CHECKGLERROR } } unit->tcubemap = texcubemap; - qglBindTexture(GL_TEXTURE_CUBE_MAP_ARB, unit->tcubemap);CHECKGLERROR + qglBindTexture(GL_TEXTURE_CUBE_MAP, unit->tcubemap);CHECKGLERROR } break; case RENDERPATH_D3D9: @@ -3630,7 +4038,6 @@ void R_Mesh_TexBind(unsigned int unitnum, rtexture_t *tex) void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix) { - gltextureunit_t *unit = gl_state.units + unitnum; switch(vid.renderpath) { case RENDERPATH_GL11: @@ -3638,8 +4045,10 @@ void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix) case RENDERPATH_GL20: case RENDERPATH_GLES1: case RENDERPATH_GLES2: +#ifdef GL_MODELVIEW if (matrix && matrix->m[3][3]) { + gltextureunit_t *unit = gl_state.units + unitnum; // texmatrix specified, check if it is different if (!unit->texmatrixenabled || memcmp(&unit->matrix, matrix, sizeof(matrix4x4_t))) { @@ -3657,6 +4066,7 @@ void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix) else { // no texmatrix specified, revert to identity + gltextureunit_t *unit = gl_state.units + unitnum; if (unit->texmatrixenabled) { unit->texmatrixenabled = false; @@ -3668,6 +4078,7 @@ void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix) qglMatrixMode(GL_MODELVIEW);CHECKGLERROR } } +#endif break; case RENDERPATH_D3D9: case RENDERPATH_D3D10: @@ -3680,6 +4091,7 @@ void R_Mesh_TexMatrix(unsigned int unitnum, const matrix4x4_t *matrix) void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, int rgbscale, int alphascale) { +#if defined(GL_TEXTURE_ENV) && !defined(USE_GLES2) gltextureunit_t *unit = gl_state.units + unitnum; CHECKGLERROR switch(vid.renderpath) @@ -3702,31 +4114,31 @@ void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, i if (combinergb != combinealpha || rgbscale != 1 || alphascale != 1) { if (combinergb == GL_DECAL) - combinergb = GL_INTERPOLATE_ARB; - if (unit->combine != GL_COMBINE_ARB) + combinergb = GL_INTERPOLATE; + if (unit->combine != GL_COMBINE) { - unit->combine = GL_COMBINE_ARB; + unit->combine = GL_COMBINE; GL_ActiveTexture(unitnum); - qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB);CHECKGLERROR - qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB_ARB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE_ARB mode + qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);CHECKGLERROR + qglTexEnvi(GL_TEXTURE_ENV, GL_SOURCE2_RGB, GL_TEXTURE);CHECKGLERROR // for GL_INTERPOLATE mode } if (unit->combinergb != combinergb) { unit->combinergb = combinergb; GL_ActiveTexture(unitnum); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, unit->combinergb);CHECKGLERROR + qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, unit->combinergb);CHECKGLERROR } if (unit->combinealpha != combinealpha) { unit->combinealpha = combinealpha; GL_ActiveTexture(unitnum); - qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, unit->combinealpha);CHECKGLERROR + qglTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, unit->combinealpha);CHECKGLERROR } if (unit->rgbscale != rgbscale) { unit->rgbscale = rgbscale; GL_ActiveTexture(unitnum); - qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE_ARB, unit->rgbscale);CHECKGLERROR + qglTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, unit->rgbscale);CHECKGLERROR } if (unit->alphascale != alphascale) { @@ -3763,6 +4175,7 @@ void R_Mesh_TexCombine(unsigned int unitnum, int combinergb, int combinealpha, i case RENDERPATH_SOFT: break; } +#endif } void R_Mesh_ResetTextureState(void) @@ -3826,6 +4239,8 @@ D3DVERTEXELEMENT9 r_vertexmesh_d3d9elements[] = {0, (int)((size_t)&((r_vertexmesh_t *)0)->tvector3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2}, {0, (int)((size_t)&((r_vertexmesh_t *)0)->normal3f ), D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3}, {0, (int)((size_t)&((r_vertexmesh_t *)0)->texcoordlightmap2f), D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4}, + {0, (int)((size_t)&((r_vertexmesh_t *)0)->skeletalindex4ub ), D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 6}, + {0, (int)((size_t)&((r_vertexmesh_t *)0)->skeletalweight4ub ), D3DDECLTYPE_UBYTE4N, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 7}, D3DDECL_END() }; @@ -3880,32 +4295,29 @@ static void R_Mesh_DestroyVertexDeclarations(void) #endif } -void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer) +void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, const r_meshbuffer_t *vertexbuffer, int bufferoffset) { // upload temporary vertexbuffer for this rendering if (!gl_state.usevbo_staticvertex) vertexbuffer = NULL; if (!vertexbuffer && gl_state.usevbo_dynamicvertex) - { - if (gl_state.preparevertices_dynamicvertexbuffer) - R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex3f, numvertices * sizeof(float[3])); - else - gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex3f, numvertices * sizeof(float[3]), "temporary", false, true, false); - vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer; - } + vertexbuffer = R_BufferData_Store(numvertices * sizeof(float[3]), (void *)vertex3f, R_BUFFERDATA_VERTEX, &bufferoffset); switch(vid.renderpath) { case RENDERPATH_GL20: case RENDERPATH_GLES2: if (vertexbuffer) { - R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0); + R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, bufferoffset); R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0); R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0); } else { @@ -3916,13 +4328,16 @@ void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, con R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0); } break; case RENDERPATH_GL13: case RENDERPATH_GLES1: if (vertexbuffer) { - R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0); + R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, bufferoffset); R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0); R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); @@ -3938,7 +4353,7 @@ void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, con case RENDERPATH_GL11: if (vertexbuffer) { - R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, 0); + R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, vertexbuffer, bufferoffset); R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL, NULL, 0); R_Mesh_TexCoordPointer(0, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); } @@ -3953,7 +4368,7 @@ void R_Mesh_PrepareVertices_Vertex3f(int numvertices, const float *vertex3f, con #ifdef SUPPORTD3D IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertex3f_d3d9decl); if (vertexbuffer) - IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(float[3])); + IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, bufferoffset, sizeof(float[3])); else IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0); gl_state.d3dvertexbuffer = (void *)vertexbuffer; @@ -3997,7 +4412,7 @@ r_vertexgeneric_t *R_Mesh_PrepareVertices_Generic_Lock(int numvertices) qboolean R_Mesh_PrepareVertices_Generic_Unlock(void) { - R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL); + R_Mesh_PrepareVertices_Generic(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexgeneric, NULL, 0); gl_state.preparevertices_vertexgeneric = NULL; gl_state.preparevertices_numvertices = 0; return true; @@ -4011,7 +4426,29 @@ void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3 { case RENDERPATH_GL20: case RENDERPATH_GLES2: - if (!vid.useinterleavedarrays) + if (gl_state.usevbo_dynamicvertex) + { + r_meshbuffer_t *buffer_vertex3f = NULL; + r_meshbuffer_t *buffer_color4f = NULL; + r_meshbuffer_t *buffer_texcoord2f = NULL; + int bufferoffset_vertex3f = 0; + int bufferoffset_color4f = 0; + int bufferoffset_texcoord2f = 0; + buffer_color4f = R_BufferData_Store(numvertices * sizeof(float[4]), color4f , R_BUFFERDATA_VERTEX, &bufferoffset_color4f ); + buffer_vertex3f = R_BufferData_Store(numvertices * sizeof(float[3]), vertex3f , R_BUFFERDATA_VERTEX, &bufferoffset_vertex3f ); + buffer_texcoord2f = R_BufferData_Store(numvertices * sizeof(float[2]), texcoord2f, R_BUFFERDATA_VERTEX, &bufferoffset_texcoord2f); + R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(float[3]) , vertex3f , buffer_vertex3f , bufferoffset_vertex3f ); + R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(float[4]) , color4f , buffer_color4f , bufferoffset_color4f ); + R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(float[2]) , texcoord2f , buffer_texcoord2f , bufferoffset_texcoord2f ); + R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(float[3]) , NULL , NULL , 0 ); + R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(float[3]) , NULL , NULL , 0 ); + R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(float[3]) , NULL , NULL , 0 ); + R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(float[2]) , NULL , NULL , 0 ); + R_Mesh_TexCoordPointer(5, 2, GL_FLOAT , sizeof(float[2]) , NULL , NULL , 0 ); + R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 ); + R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 ); + } + else if (!vid.useinterleavedarrays) { R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0); R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0); @@ -4020,6 +4457,9 @@ void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3 R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0); return; } break; @@ -4071,35 +4511,32 @@ void R_Mesh_PrepareVertices_Generic_Arrays(int numvertices, const float *vertex3 for (i = 0;i < numvertices;i++) Vector2Copy(texcoord2f + 2*i, vertex[i].texcoord2f); R_Mesh_PrepareVertices_Generic_Unlock(); - R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL); + R_Mesh_PrepareVertices_Generic(numvertices, vertex, NULL, 0); } -void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer) +void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *vertex, const r_meshbuffer_t *vertexbuffer, int bufferoffset) { // upload temporary vertexbuffer for this rendering if (!gl_state.usevbo_staticvertex) vertexbuffer = NULL; if (!vertexbuffer && gl_state.usevbo_dynamicvertex) - { - if (gl_state.preparevertices_dynamicvertexbuffer) - R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex)); - else - gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false); - vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer; - } + vertexbuffer = R_BufferData_Store(numvertices * sizeof(*vertex), (void *)vertex, R_BUFFERDATA_VERTEX, &bufferoffset); switch(vid.renderpath) { case RENDERPATH_GL20: case RENDERPATH_GLES2: if (vertexbuffer) { - R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex)); - R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex)); - R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex)); + R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex)); + R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex)); + R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex)); R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0); } else { @@ -4110,15 +4547,18 @@ void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *ve R_Mesh_TexCoordPointer(2, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(3, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0); } break; case RENDERPATH_GL13: case RENDERPATH_GLES1: if (vertexbuffer) { - R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex)); - R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex)); - R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex)); + R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex)); + R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex)); + R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex)); R_Mesh_TexCoordPointer(1, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); } else @@ -4132,9 +4572,9 @@ void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *ve case RENDERPATH_GL11: if (vertexbuffer) { - R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex)); - R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex)); - R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex)); + R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex)); + R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex)); + R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoord2f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoord2f - (unsigned char *)vertex)); } else { @@ -4147,7 +4587,7 @@ void R_Mesh_PrepareVertices_Generic(int numvertices, const r_vertexgeneric_t *ve #ifdef SUPPORTD3D IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexgeneric_d3d9decl); if (vertexbuffer) - IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex)); + IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, bufferoffset, sizeof(*vertex)); else IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0); gl_state.d3dvertexbuffer = (void *)vertexbuffer; @@ -4191,7 +4631,7 @@ r_vertexmesh_t *R_Mesh_PrepareVertices_Mesh_Lock(int numvertices) qboolean R_Mesh_PrepareVertices_Mesh_Unlock(void) { - R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL); + R_Mesh_PrepareVertices_Mesh(gl_state.preparevertices_numvertices, gl_state.preparevertices_vertexmesh, NULL, 0); gl_state.preparevertices_vertexmesh = NULL; gl_state.preparevertices_numvertices = 0; return true; @@ -4205,7 +4645,41 @@ void R_Mesh_PrepareVertices_Mesh_Arrays(int numvertices, const float *vertex3f, { case RENDERPATH_GL20: case RENDERPATH_GLES2: - if (!vid.useinterleavedarrays) + if (gl_state.usevbo_dynamicvertex) + { + r_meshbuffer_t *buffer_vertex3f = NULL; + r_meshbuffer_t *buffer_color4f = NULL; + r_meshbuffer_t *buffer_texcoordtexture2f = NULL; + r_meshbuffer_t *buffer_svector3f = NULL; + r_meshbuffer_t *buffer_tvector3f = NULL; + r_meshbuffer_t *buffer_normal3f = NULL; + r_meshbuffer_t *buffer_texcoordlightmap2f = NULL; + int bufferoffset_vertex3f = 0; + int bufferoffset_color4f = 0; + int bufferoffset_texcoordtexture2f = 0; + int bufferoffset_svector3f = 0; + int bufferoffset_tvector3f = 0; + int bufferoffset_normal3f = 0; + int bufferoffset_texcoordlightmap2f = 0; + buffer_color4f = R_BufferData_Store(numvertices * sizeof(float[4]), color4f , R_BUFFERDATA_VERTEX, &bufferoffset_color4f ); + buffer_vertex3f = R_BufferData_Store(numvertices * sizeof(float[3]), vertex3f , R_BUFFERDATA_VERTEX, &bufferoffset_vertex3f ); + buffer_svector3f = R_BufferData_Store(numvertices * sizeof(float[3]), svector3f , R_BUFFERDATA_VERTEX, &bufferoffset_svector3f ); + buffer_tvector3f = R_BufferData_Store(numvertices * sizeof(float[3]), tvector3f , R_BUFFERDATA_VERTEX, &bufferoffset_tvector3f ); + buffer_normal3f = R_BufferData_Store(numvertices * sizeof(float[3]), normal3f , R_BUFFERDATA_VERTEX, &bufferoffset_normal3f ); + buffer_texcoordtexture2f = R_BufferData_Store(numvertices * sizeof(float[2]), texcoordtexture2f , R_BUFFERDATA_VERTEX, &bufferoffset_texcoordtexture2f ); + buffer_texcoordlightmap2f = R_BufferData_Store(numvertices * sizeof(float[2]), texcoordlightmap2f, R_BUFFERDATA_VERTEX, &bufferoffset_texcoordlightmap2f); + R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(float[3]) , vertex3f , buffer_vertex3f , bufferoffset_vertex3f ); + R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(float[4]) , color4f , buffer_color4f , bufferoffset_color4f ); + R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(float[2]) , texcoordtexture2f , buffer_texcoordtexture2f , bufferoffset_texcoordtexture2f ); + R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(float[3]) , svector3f , buffer_svector3f , bufferoffset_svector3f ); + R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(float[3]) , tvector3f , buffer_tvector3f , bufferoffset_tvector3f ); + R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(float[3]) , normal3f , buffer_normal3f , bufferoffset_normal3f ); + R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(float[2]) , texcoordlightmap2f, buffer_texcoordlightmap2f, bufferoffset_texcoordlightmap2f); + R_Mesh_TexCoordPointer(5, 2, GL_FLOAT , sizeof(float[2]) , NULL , NULL , 0 ); + R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 ); + R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL , NULL , 0 ); + } + else if (!vid.useinterleavedarrays) { R_Mesh_VertexPointer(3, GL_FLOAT, sizeof(float[3]), vertex3f, NULL, 0); R_Mesh_ColorPointer(4, GL_FLOAT, sizeof(float[4]), color4f, NULL, 0); @@ -4214,6 +4688,9 @@ void R_Mesh_PrepareVertices_Mesh_Arrays(int numvertices, const float *vertex3f, R_Mesh_TexCoordPointer(2, 3, GL_FLOAT, sizeof(float[3]), tvector3f, NULL, 0); R_Mesh_TexCoordPointer(3, 3, GL_FLOAT, sizeof(float[3]), normal3f, NULL, 0); R_Mesh_TexCoordPointer(4, 2, GL_FLOAT, sizeof(float[2]), texcoordlightmap2f, NULL, 0); + R_Mesh_TexCoordPointer(5, 2, GL_FLOAT, sizeof(float[2]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0); + R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(unsigned char[4]), NULL, NULL, 0); return; } break; @@ -4276,35 +4753,32 @@ void R_Mesh_PrepareVertices_Mesh_Arrays(int numvertices, const float *vertex3f, for (i = 0;i < numvertices;i++) Vector2Copy(texcoordlightmap2f + 2*i, vertex[i].texcoordlightmap2f); R_Mesh_PrepareVertices_Mesh_Unlock(); - R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL); + R_Mesh_PrepareVertices_Mesh(numvertices, vertex, NULL, 0); } -void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer) +void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, const r_meshbuffer_t *vertexbuffer, int bufferoffset) { // upload temporary vertexbuffer for this rendering if (!gl_state.usevbo_staticvertex) vertexbuffer = NULL; if (!vertexbuffer && gl_state.usevbo_dynamicvertex) - { - if (gl_state.preparevertices_dynamicvertexbuffer) - R_Mesh_UpdateMeshBuffer(gl_state.preparevertices_dynamicvertexbuffer, vertex, numvertices * sizeof(*vertex)); - else - gl_state.preparevertices_dynamicvertexbuffer = R_Mesh_CreateMeshBuffer(vertex, numvertices * sizeof(*vertex), "temporary", false, true, false); - vertexbuffer = gl_state.preparevertices_dynamicvertexbuffer; - } + vertexbuffer = R_BufferData_Store(numvertices * sizeof(*vertex), (void *)vertex, R_BUFFERDATA_VERTEX, &bufferoffset); switch(vid.renderpath) { case RENDERPATH_GL20: case RENDERPATH_GLES2: if (vertexbuffer) { - R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex)); - R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex)); - R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex)); - R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex)); - R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex)); - R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex)); - R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex)); + R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex)); + R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex)); + R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex)); + R_Mesh_TexCoordPointer(1, 3, GL_FLOAT , sizeof(*vertex), vertex->svector3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->svector3f - (unsigned char *)vertex)); + R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->tvector3f - (unsigned char *)vertex)); + R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->normal3f - (unsigned char *)vertex)); + R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex)); + R_Mesh_TexCoordPointer(5, 2, GL_FLOAT , sizeof(*vertex), NULL, NULL, 0); + R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(*vertex), vertex->skeletalindex4ub , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->skeletalindex4ub - (unsigned char *)vertex)); + R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->skeletalweight4ub , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->skeletalweight4ub - (unsigned char *)vertex)); } else { @@ -4315,16 +4789,19 @@ void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, R_Mesh_TexCoordPointer(2, 3, GL_FLOAT , sizeof(*vertex), vertex->tvector3f , NULL, 0); R_Mesh_TexCoordPointer(3, 3, GL_FLOAT , sizeof(*vertex), vertex->normal3f , NULL, 0); R_Mesh_TexCoordPointer(4, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, NULL, 0); + R_Mesh_TexCoordPointer(5, 2, GL_FLOAT , sizeof(*vertex), NULL, NULL, 0); + R_Mesh_TexCoordPointer(6, 4, GL_UNSIGNED_BYTE | 0x80000000, sizeof(*vertex), vertex->skeletalindex4ub , NULL, 0); + R_Mesh_TexCoordPointer(7, 4, GL_UNSIGNED_BYTE, sizeof(*vertex), vertex->skeletalweight4ub , NULL, 0); } break; case RENDERPATH_GL13: case RENDERPATH_GLES1: if (vertexbuffer) { - R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex)); - R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex)); - R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex)); - R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex)); + R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex)); + R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex)); + R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex)); + R_Mesh_TexCoordPointer(1, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordlightmap2f, vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoordlightmap2f - (unsigned char *)vertex)); } else { @@ -4337,9 +4814,9 @@ void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, case RENDERPATH_GL11: if (vertexbuffer) { - R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex)); - R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex)); - R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex)); + R_Mesh_VertexPointer( 3, GL_FLOAT , sizeof(*vertex), vertex->vertex3f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->vertex3f - (unsigned char *)vertex)); + R_Mesh_ColorPointer( 4, GL_FLOAT , sizeof(*vertex), vertex->color4f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->color4f - (unsigned char *)vertex)); + R_Mesh_TexCoordPointer(0, 2, GL_FLOAT , sizeof(*vertex), vertex->texcoordtexture2f , vertexbuffer, bufferoffset + (int)((unsigned char *)vertex->texcoordtexture2f - (unsigned char *)vertex)); } else { @@ -4352,7 +4829,7 @@ void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, #ifdef SUPPORTD3D IDirect3DDevice9_SetVertexDeclaration(vid_d3d9dev, r_vertexmesh_d3d9decl); if (vertexbuffer) - IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, 0, sizeof(*vertex)); + IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, (IDirect3DVertexBuffer9*)vertexbuffer->devicebuffer, bufferoffset, sizeof(*vertex)); else IDirect3DDevice9_SetStreamSource(vid_d3d9dev, 0, NULL, 0, 0); gl_state.d3dvertexbuffer = (void *)vertexbuffer; @@ -4377,3 +4854,61 @@ void R_Mesh_PrepareVertices_Mesh(int numvertices, const r_vertexmesh_t *vertex, break; } } + +void GL_BlendEquationSubtract(qboolean negated) +{ + if(negated) + { + switch(vid.renderpath) + { + case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GL20: + case RENDERPATH_GLES1: + case RENDERPATH_GLES2: + qglBlendEquationEXT(GL_FUNC_REVERSE_SUBTRACT); + break; + case RENDERPATH_D3D9: +#ifdef SUPPORTD3D + IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_BLENDOP, D3DBLENDOP_SUBTRACT); +#endif + break; + case RENDERPATH_D3D10: + Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); + break; + case RENDERPATH_D3D11: + Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); + break; + case RENDERPATH_SOFT: + DPSOFTRAST_BlendSubtract(true); + break; + } + } + else + { + switch(vid.renderpath) + { + case RENDERPATH_GL11: + case RENDERPATH_GL13: + case RENDERPATH_GL20: + case RENDERPATH_GLES1: + case RENDERPATH_GLES2: + qglBlendEquationEXT(GL_FUNC_ADD); + break; + case RENDERPATH_D3D9: +#ifdef SUPPORTD3D + IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_BLENDOP, D3DBLENDOP_ADD); +#endif + break; + case RENDERPATH_D3D10: + Con_DPrintf("FIXME D3D10 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); + break; + case RENDERPATH_D3D11: + Con_DPrintf("FIXME D3D11 %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__); + break; + case RENDERPATH_SOFT: + DPSOFTRAST_BlendSubtract(false); + break; + } + } +}