+ matrix4x4_t tempmatrix, basematrix;
+ const float nudge = 1.0 - 1.0 / (1<<23);
+ float m[16];
+ memset(v, 0, sizeof(*v));
+
+ v->type = R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP;
+ v->cameramatrix = *cameramatrix;
+ v->x = x;
+ v->y = y;
+ v->z = 0;
+ v->width = width;
+ v->height = height;
+ v->depth = 1;
+ memset(m, 0, sizeof(m));
+ m[ 0] = 1.0 / frustumx;
+ m[ 5] = 1.0 / frustumy;
+ m[10] = -nudge;
+ m[11] = -1;
+ m[14] = -2 * nearclip * nudge;
+ v->screentodepth[0] = (m[10] + 1) * 0.5 - 1;
+ v->screentodepth[1] = m[14] * -0.5;
+
+ Matrix4x4_Invert_Full(&tempmatrix, &v->cameramatrix);
+ Matrix4x4_CreateRotate(&basematrix, -90, 1, 0, 0);
+ Matrix4x4_ConcatRotate(&basematrix, 90, 0, 0, 1);
+ Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
+
+ if (nearplane)
+ R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
+
+ if(v_flipped.integer)
+ {
+ m[0] = -m[0];
+ m[4] = -m[4];
+ m[8] = -m[8];
+ m[12] = -m[12];
+ }
+
+ Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
+}
+
+float cubeviewmatrix[6][16] =
+{
+ // standard cubemap projections
+ { // +X
+ 0, 0,-1, 0,
+ 0,-1, 0, 0,
+ -1, 0, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // -X
+ 0, 0, 1, 0,
+ 0,-1, 0, 0,
+ 1, 0, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // +Y
+ 1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // -Y
+ 1, 0, 0, 0,
+ 0, 0, 1, 0,
+ 0,-1, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // +Z
+ 1, 0, 0, 0,
+ 0,-1, 0, 0,
+ 0, 0,-1, 0,
+ 0, 0, 0, 1,
+ },
+ { // -Z
+ -1, 0, 0, 0,
+ 0,-1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1,
+ },
+};
+float rectviewmatrix[6][16] =
+{
+ // sign-preserving cubemap projections
+ { // +X
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 1, 0, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // -X
+ 0, 0, 1, 0,
+ 0, 1, 0, 0,
+ 1, 0, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // +Y
+ 1, 0, 0, 0,
+ 0, 0,-1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // -Y
+ 1, 0, 0, 0,
+ 0, 0, 1, 0,
+ 0, 1, 0, 0,
+ 0, 0, 0, 1,
+ },
+ { // +Z
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0,-1, 0,
+ 0, 0, 0, 1,
+ },
+ { // -Z
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1,
+ },
+};
+
+void R_Viewport_InitCubeSideView(r_viewport_t *v, const matrix4x4_t *cameramatrix, int side, int size, float nearclip, float farclip, const float *nearplane)
+{
+ matrix4x4_t tempmatrix, basematrix;
+ float m[16];
+ memset(v, 0, sizeof(*v));
+ v->type = R_VIEWPORTTYPE_PERSPECTIVECUBESIDE;
+ v->cameramatrix = *cameramatrix;
+ v->width = size;
+ v->height = size;
+ v->depth = 1;
+ memset(m, 0, sizeof(m));
+ m[0] = m[5] = 1.0f;
+ m[10] = -(farclip + nearclip) / (farclip - nearclip);
+ m[11] = -1;
+ m[14] = -2 * nearclip * farclip / (farclip - nearclip);
+
+ Matrix4x4_FromArrayFloatGL(&basematrix, cubeviewmatrix[side]);
+ Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
+ Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
+
+ if (nearplane)
+ R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
+
+ 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)
+{
+ 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->width = size;
+ v->height = size;
+ v->depth = 1;
+ memset(m, 0, sizeof(m));
+ m[0] = m[5] = 1.0f * ((float)size - border) / size;
+ m[10] = -(farclip + nearclip) / (farclip - nearclip);
+ m[11] = -1;
+ m[14] = -2 * nearclip * farclip / (farclip - nearclip);
+
+ Matrix4x4_FromArrayFloatGL(&basematrix, rectviewmatrix[side]);
+ Matrix4x4_Invert_Simple(&tempmatrix, &v->cameramatrix);
+ Matrix4x4_Concat(&v->viewmatrix, &basematrix, &tempmatrix);
+
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL20:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ case RENDERPATH_SOFT:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ break;
+ case RENDERPATH_D3D9:
+ m[5] *= -1;
+ 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;
+ }
+
+ if (nearplane)
+ R_Viewport_ApplyNearClipPlaneFloatGL(v, m, nearplane[0], nearplane[1], nearplane[2], nearplane[3]);
+
+ Matrix4x4_FromArrayFloatGL(&v->projectmatrix, m);
+}
+
+void R_SetViewport(const r_viewport_t *v)
+{
+ gl_viewport = *v;
+
+ // FIXME: v_flipped_state is evil, this probably breaks somewhere
+ GL_SetMirrorState(v_flipped.integer && (v->type == R_VIEWPORTTYPE_PERSPECTIVE || v->type == R_VIEWPORTTYPE_PERSPECTIVE_INFINITEFARCLIP));
+
+ // copy over the matrices to our state
+ gl_viewmatrix = v->viewmatrix;
+ gl_projectionmatrix = v->projectmatrix;
+
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL11:
+ case RENDERPATH_GLES1:
+#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
+ {
+ D3DVIEWPORT9 d3dviewport;
+ d3dviewport.X = gl_viewport.x;
+ d3dviewport.Y = gl_viewport.y;
+ d3dviewport.Width = gl_viewport.width;
+ d3dviewport.Height = gl_viewport.height;
+ d3dviewport.MinZ = gl_state.depthrange[0];
+ d3dviewport.MaxZ = gl_state.depthrange[1];
+ IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
+ }
+#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_Viewport(v->x, v->y, v->width, v->height);
+ break;
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES2:
+ CHECKGLERROR
+ qglViewport(v->x, v->y, v->width, v->height);CHECKGLERROR
+ break;
+ }
+
+ // force an update of the derived matrices
+ gl_modelmatrixchanged = true;
+ R_EntityMatrix(&gl_modelmatrix);
+}
+
+void R_GetViewport(r_viewport_t *v)
+{
+ *v = gl_viewport;
+}
+
+static void GL_BindVBO(int bufferobject)
+{
+ if (gl_state.vertexbufferobject != bufferobject)
+ {
+ gl_state.vertexbufferobject = bufferobject;
+ CHECKGLERROR
+ qglBindBufferARB(GL_ARRAY_BUFFER, bufferobject);CHECKGLERROR
+ }
+}
+
+static void GL_BindEBO(int bufferobject)
+{
+ if (gl_state.elementbufferobject != bufferobject)
+ {
+ gl_state.elementbufferobject = 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)
+{
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ 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:
+ return 1;
+ case RENDERPATH_SOFT:
+ return 1;
+ }
+ return 0;
+}
+
+void R_Mesh_DestroyFramebufferObject(int fbo)
+{
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ if (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:
+ case RENDERPATH_D3D11:
+ break;
+ case RENDERPATH_SOFT:
+ break;
+ }
+}
+
+#ifdef SUPPORTD3D
+void R_Mesh_SetRenderTargetsD3D9(IDirect3DSurface9 *depthsurface, IDirect3DSurface9 *colorsurface0, IDirect3DSurface9 *colorsurface1, IDirect3DSurface9 *colorsurface2, IDirect3DSurface9 *colorsurface3)
+{
+ gl_state.framebufferobject = depthsurface != gl_state.d3drt_backbufferdepthsurface || colorsurface0 != gl_state.d3drt_backbuffercolorsurface;
+ if (gl_state.d3drt_depthsurface != depthsurface)
+ {
+ gl_state.d3drt_depthsurface = depthsurface;
+ IDirect3DDevice9_SetDepthStencilSurface(vid_d3d9dev, gl_state.d3drt_depthsurface);
+ }
+ if (gl_state.d3drt_colorsurfaces[0] != colorsurface0)
+ {
+ gl_state.d3drt_colorsurfaces[0] = colorsurface0;
+ IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 0, gl_state.d3drt_colorsurfaces[0]);
+ }
+ if (gl_state.d3drt_colorsurfaces[1] != colorsurface1)
+ {
+ gl_state.d3drt_colorsurfaces[1] = colorsurface1;
+ IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 1, gl_state.d3drt_colorsurfaces[1]);
+ }
+ if (gl_state.d3drt_colorsurfaces[2] != colorsurface2)
+ {
+ gl_state.d3drt_colorsurfaces[2] = colorsurface2;
+ IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 2, gl_state.d3drt_colorsurfaces[2]);
+ }
+ if (gl_state.d3drt_colorsurfaces[3] != colorsurface3)
+ {
+ gl_state.d3drt_colorsurfaces[3] = colorsurface3;
+ IDirect3DDevice9_SetRenderTarget(vid_d3d9dev, 3, gl_state.d3drt_colorsurfaces[3]);
+ }
+}
+#endif
+
+void R_Mesh_SetRenderTargets(int fbo, rtexture_t *depthtexture, rtexture_t *colortexture, rtexture_t *colortexture2, rtexture_t *colortexture3, rtexture_t *colortexture4)
+{
+ unsigned int i;
+ unsigned int j;
+ rtexture_t *textures[5];
+ Vector4Set(textures, colortexture, colortexture2, colortexture3, colortexture4);
+ textures[4] = depthtexture;
+ // unbind any matching textures immediately, otherwise D3D will complain about a bound texture being used as a render target
+ for (j = 0;j < 5;j++)
+ if (textures[j])
+ for (i = 0;i < vid.teximageunits;i++)
+ if (gl_state.units[i].texture == textures[j])
+ R_Mesh_TexBind(i, NULL);
+ // set up framebuffer object or render targets for the active rendering API
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ if (gl_state.framebufferobject != fbo)
+ {
+ gl_state.framebufferobject = fbo;
+ qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.framebufferobject ? gl_state.framebufferobject : gl_state.defaultframebufferobject);
+ }
+ break;
+ case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+ // set up the new render targets, a NULL depthtexture intentionally binds nothing
+ // TODO: optimize: keep surface pointer around in rtexture_t until texture is freed or lost
+ if (fbo)
+ {
+ IDirect3DSurface9 *surfaces[5];
+ for (i = 0;i < 5;i++)
+ {
+ surfaces[i] = NULL;
+ if (textures[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(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 < 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);
+#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:
+ if (fbo)
+ {
+ int width, height;
+ unsigned int *pointers[5];
+ memset(pointers, 0, sizeof(pointers));
+ for (i = 0;i < 5;i++)
+ pointers[i] = textures[i] ? (unsigned int *)DPSOFTRAST_Texture_GetPixelPointer(textures[i]->texnum, 0) : NULL;
+ width = DPSOFTRAST_Texture_GetWidth(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
+ height = DPSOFTRAST_Texture_GetHeight(textures[0] ? textures[0]->texnum : textures[4]->texnum, 0);
+ DPSOFTRAST_SetRenderTargets(width, height, pointers[4], pointers[0], pointers[1], pointers[2], pointers[3]);
+ }
+ else
+ DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
+ break;
+ }
+}
+
+#ifdef SUPPORTD3D
+static int d3dcmpforglfunc(int f)
+{
+ switch(f)
+ {
+ case GL_NEVER: return D3DCMP_NEVER;
+ case GL_LESS: return D3DCMP_LESS;
+ case GL_EQUAL: return D3DCMP_EQUAL;
+ case GL_LEQUAL: return D3DCMP_LESSEQUAL;
+ case GL_GREATER: return D3DCMP_GREATER;
+ case GL_NOTEQUAL: return D3DCMP_NOTEQUAL;
+ case GL_GEQUAL: return D3DCMP_GREATEREQUAL;
+ case GL_ALWAYS: return D3DCMP_ALWAYS;
+ default: Con_DPrintf("Unknown GL_DepthFunc\n");return D3DCMP_ALWAYS;
+ }
+}
+
+static int d3dstencilopforglfunc(int f)
+{
+ switch(f)
+ {
+ case GL_KEEP: return D3DSTENCILOP_KEEP;
+ case GL_INCR: return D3DSTENCILOP_INCR; // note: GL_INCR is clamped, D3DSTENCILOP_INCR wraps
+ case GL_DECR: return D3DSTENCILOP_DECR; // note: GL_DECR is clamped, D3DSTENCILOP_DECR wraps
+ default: Con_DPrintf("Unknown GL_StencilFunc\n");return D3DSTENCILOP_KEEP;
+ }
+}
+#endif
+
+static void GL_Backend_ResetState(void)
+{
+ unsigned int i;
+ gl_state.active = true;
+ gl_state.depthtest = true;
+ 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;
+ gl_state.depthmask = GL_TRUE;
+ gl_state.colormask = 15;
+ gl_state.color4f[0] = gl_state.color4f[1] = gl_state.color4f[2] = gl_state.color4f[3] = 1;
+ gl_state.lockrange_first = 0;
+ gl_state.lockrange_count = 0;
+ gl_state.cullface = GL_FRONT;
+ gl_state.cullfaceenable = false;
+ gl_state.polygonoffset[0] = 0;
+ gl_state.polygonoffset[1] = 0;
+ gl_state.framebufferobject = 0;
+ gl_state.depthfunc = GL_LEQUAL;
+
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+ {
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_COLORWRITEENABLE, gl_state.colormask);
+ 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);
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
+ }
+#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_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(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
+ qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+ qglEnable(GL_DEPTH_TEST);CHECKGLERROR
+ qglDepthMask(gl_state.depthmask);CHECKGLERROR
+ qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
+
+ if (vid.support.arb_vertex_buffer_object)
+ {
+ qglBindBufferARB(GL_ARRAY_BUFFER, 0);
+ qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+
+ if (vid.support.ext_framebuffer_object)
+ {
+ //qglBindRenderbuffer(GL_RENDERBUFFER, 0);
+ qglBindFramebuffer(GL_FRAMEBUFFER, 0);
+ }
+
+ qglVertexPointer(3, GL_FLOAT, sizeof(float[3]), NULL);CHECKGLERROR
+ qglEnableClientState(GL_VERTEX_ARRAY);CHECKGLERROR
+
+ qglColorPointer(4, GL_FLOAT, sizeof(float[4]), NULL);CHECKGLERROR
+ qglDisableClientState(GL_COLOR_ARRAY);CHECKGLERROR
+ qglColor4f(1, 1, 1, 1);CHECKGLERROR
+
+ if (vid.support.ext_framebuffer_object)
+ qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.framebufferobject);
+
+ gl_state.unit = MAX_TEXTUREUNITS;
+ gl_state.clientunit = MAX_TEXTUREUNITS;
+ for (i = 0;i < vid.texunits;i++)
+ {
+ GL_ActiveTexture(i);
+ GL_ClientActiveTexture(i);
+ qglDisable(GL_TEXTURE_2D);CHECKGLERROR
+ qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
+ if (vid.support.ext_texture_3d)
+ {
+ qglDisable(GL_TEXTURE_3D);CHECKGLERROR
+ qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
+ }
+ if (vid.support.arb_texture_cube_map)
+ {
+ 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
+ qglDisableClientState(GL_TEXTURE_COORD_ARRAY);CHECKGLERROR
+ qglMatrixMode(GL_TEXTURE);CHECKGLERROR
+ qglLoadIdentity();CHECKGLERROR
+ qglMatrixMode(GL_MODELVIEW);CHECKGLERROR
+ qglTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);CHECKGLERROR
+ }
+ CHECKGLERROR
+#endif
+ break;
+ case RENDERPATH_SOFT:
+ DPSOFTRAST_ColorMask(1,1,1,1);
+ DPSOFTRAST_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
+ DPSOFTRAST_CullFace(gl_state.cullface);
+ DPSOFTRAST_DepthFunc(gl_state.depthfunc);
+ DPSOFTRAST_DepthMask(gl_state.depthmask);
+ DPSOFTRAST_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
+ DPSOFTRAST_SetRenderTargets(vid.width, vid.height, vid.softdepthpixels, vid.softpixels, NULL, NULL, NULL);
+ DPSOFTRAST_Viewport(0, 0, vid.width, vid.height);
+ break;
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES2:
+ CHECKGLERROR
+ qglColorMask(1, 1, 1, 1);CHECKGLERROR
+ qglBlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);CHECKGLERROR
+ qglDisable(GL_BLEND);CHECKGLERROR
+ qglCullFace(gl_state.cullface);CHECKGLERROR
+ qglDisable(GL_CULL_FACE);CHECKGLERROR
+ qglDepthFunc(GL_LEQUAL);CHECKGLERROR
+ qglEnable(GL_DEPTH_TEST);CHECKGLERROR
+ qglDepthMask(gl_state.depthmask);CHECKGLERROR
+ qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
+ if (vid.support.arb_vertex_buffer_object)
+ {
+ qglBindBufferARB(GL_ARRAY_BUFFER, 0);
+ qglBindBufferARB(GL_ELEMENT_ARRAY_BUFFER, 0);
+ }
+ if (vid.support.ext_framebuffer_object)
+ qglBindFramebuffer(GL_FRAMEBUFFER, gl_state.defaultframebufferobject);
+ qglEnableVertexAttribArray(GLSLATTRIB_POSITION);
+ qglVertexAttribPointer(GLSLATTRIB_POSITION, 3, GL_FLOAT, false, sizeof(float[3]), NULL);CHECKGLERROR
+ qglDisableVertexAttribArray(GLSLATTRIB_COLOR);
+ qglVertexAttribPointer(GLSLATTRIB_COLOR, 4, GL_FLOAT, false, sizeof(float[4]), NULL);CHECKGLERROR
+ qglVertexAttrib4f(GLSLATTRIB_COLOR, 1, 1, 1, 1);
+ gl_state.unit = MAX_TEXTUREUNITS;
+ gl_state.clientunit = MAX_TEXTUREUNITS;
+ for (i = 0;i < vid.teximageunits;i++)
+ {
+ GL_ActiveTexture(i);
+ qglBindTexture(GL_TEXTURE_2D, 0);CHECKGLERROR
+ if (vid.support.ext_texture_3d)
+ {
+ qglBindTexture(GL_TEXTURE_3D, 0);CHECKGLERROR
+ }
+ if (vid.support.arb_texture_cube_map)
+ {
+ qglBindTexture(GL_TEXTURE_CUBE_MAP, 0);CHECKGLERROR
+ }
+ }
+ for (i = 0;i < vid.texarrayunits;i++)
+ {
+ GL_BindVBO(0);
+ qglVertexAttribPointer(i+GLSLATTRIB_TEXCOORD0, 2, GL_FLOAT, false, sizeof(float[2]), NULL);CHECKGLERROR
+ qglDisableVertexAttribArray(i+GLSLATTRIB_TEXCOORD0);CHECKGLERROR
+ }
+ CHECKGLERROR
+ break;
+ }
+}
+
+void GL_ActiveTexture(unsigned int num)
+{
+ if (gl_state.unit != num)
+ {
+ gl_state.unit = num;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ if (qglActiveTexture)
+ {
+ CHECKGLERROR
+ qglActiveTexture(GL_TEXTURE0 + gl_state.unit);
+ CHECKGLERROR
+ }
+ break;
+ case RENDERPATH_D3D9:
+ case RENDERPATH_D3D10:
+ case RENDERPATH_D3D11:
+ break;
+ case RENDERPATH_SOFT:
+ break;
+ }
+ }
+}
+
+void GL_ClientActiveTexture(unsigned int num)
+{
+ if (gl_state.clientunit != num)
+ {
+ gl_state.clientunit = num;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GLES1:
+#ifndef USE_GLES2
+ if (qglActiveTexture)
+ {
+ CHECKGLERROR
+ qglClientActiveTexture(GL_TEXTURE0 + gl_state.clientunit);
+ CHECKGLERROR
+ }
+#endif
+ break;
+ case RENDERPATH_D3D9:
+ case RENDERPATH_D3D10:
+ case RENDERPATH_D3D11:
+ break;
+ case RENDERPATH_SOFT:
+ break;
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES2:
+ break;
+ }
+ }
+}
+
+void GL_BlendFunc(int blendfunc1, int blendfunc2)
+{
+ if (gl_state.blendfunc1 != blendfunc1 || gl_state.blendfunc2 != blendfunc2)
+ {
+ qboolean blendenable;
+ gl_state.blendfunc1 = blendfunc1;
+ gl_state.blendfunc2 = blendfunc2;
+ blendenable = (gl_state.blendfunc1 != GL_ONE || gl_state.blendfunc2 != GL_ZERO);
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ 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;
+ if (!gl_state.blend)
+ {
+ qglDisable(GL_BLEND);CHECKGLERROR
+ }
+ else
+ {
+ qglEnable(GL_BLEND);CHECKGLERROR
+ }
+ }
+ break;
+ case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+ {
+ int i;
+ int glblendfunc[2];
+ D3DBLEND d3dblendfunc[2];
+ glblendfunc[0] = gl_state.blendfunc1;
+ glblendfunc[1] = gl_state.blendfunc2;
+ for (i = 0;i < 2;i++)
+ {
+ switch(glblendfunc[i])
+ {
+ case GL_ZERO: d3dblendfunc[i] = D3DBLEND_ZERO;break;
+ case GL_ONE: d3dblendfunc[i] = D3DBLEND_ONE;break;
+ case GL_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_SRCCOLOR;break;
+ case GL_ONE_MINUS_SRC_COLOR: d3dblendfunc[i] = D3DBLEND_INVSRCCOLOR;break;
+ case GL_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_SRCALPHA;break;
+ case GL_ONE_MINUS_SRC_ALPHA: d3dblendfunc[i] = D3DBLEND_INVSRCALPHA;break;
+ case GL_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_DESTALPHA;break;
+ case GL_ONE_MINUS_DST_ALPHA: d3dblendfunc[i] = D3DBLEND_INVDESTALPHA;break;
+ case GL_DST_COLOR: d3dblendfunc[i] = D3DBLEND_DESTCOLOR;break;
+ case GL_ONE_MINUS_DST_COLOR: d3dblendfunc[i] = D3DBLEND_INVDESTCOLOR;break;
+ }
+ }
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SRCBLEND, d3dblendfunc[0]);
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DESTBLEND, d3dblendfunc[1]);
+ if (gl_state.blend != blendenable)
+ {
+ gl_state.blend = blendenable;
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ALPHABLENDENABLE, gl_state.blend);
+ }
+ }
+#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_BlendFunc(gl_state.blendfunc1, gl_state.blendfunc2);
+ break;
+ }
+ }
+}
+
+void GL_DepthMask(int state)
+{
+ if (gl_state.depthmask != state)
+ {
+ gl_state.depthmask = state;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ CHECKGLERROR
+ qglDepthMask(gl_state.depthmask);CHECKGLERROR
+ break;
+ case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZWRITEENABLE, gl_state.depthmask);
+#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_DepthMask(gl_state.depthmask);
+ break;
+ }
+ }
+}
+
+void GL_DepthTest(int state)
+{
+ if (gl_state.depthtest != state)
+ {
+ gl_state.depthtest = state;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ CHECKGLERROR
+ if (gl_state.depthtest)
+ {
+ qglEnable(GL_DEPTH_TEST);CHECKGLERROR
+ }
+ else
+ {
+ qglDisable(GL_DEPTH_TEST);CHECKGLERROR
+ }
+ break;
+ case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZENABLE, gl_state.depthtest);
+#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_DepthTest(gl_state.depthtest);
+ break;
+ }
+ }
+}
+
+void GL_DepthFunc(int state)
+{
+ if (gl_state.depthfunc != state)
+ {
+ gl_state.depthfunc = state;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ CHECKGLERROR
+ qglDepthFunc(gl_state.depthfunc);CHECKGLERROR
+ break;
+ case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_ZFUNC, d3dcmpforglfunc(gl_state.depthfunc));
+#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_DepthFunc(gl_state.depthfunc);
+ break;
+ }
+ }
+}
+
+void GL_DepthRange(float nearfrac, float farfrac)
+{
+ if (gl_state.depthrange[0] != nearfrac || gl_state.depthrange[1] != farfrac)
+ {
+ gl_state.depthrange[0] = nearfrac;
+ gl_state.depthrange[1] = farfrac;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ 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
+ {
+ D3DVIEWPORT9 d3dviewport;
+ d3dviewport.X = gl_viewport.x;
+ d3dviewport.Y = gl_viewport.y;
+ d3dviewport.Width = gl_viewport.width;
+ d3dviewport.Height = gl_viewport.height;
+ d3dviewport.MinZ = gl_state.depthrange[0];
+ d3dviewport.MaxZ = gl_state.depthrange[1];
+ IDirect3DDevice9_SetViewport(vid_d3d9dev, &d3dviewport);
+ }
+#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_DepthRange(gl_state.depthrange[0], gl_state.depthrange[1]);
+ break;
+ }
+ }
+}
+
+void R_SetStencilSeparate(qboolean enable, int writemask, int frontfail, int frontzfail, int frontzpass, int backfail, int backzfail, int backzpass, int frontcompare, int backcompare, int comparereference, int comparemask)
+{
+ switch (vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ CHECKGLERROR
+ if (enable)
+ {
+ qglEnable(GL_STENCIL_TEST);CHECKGLERROR
+ }
+ else
+ {
+ qglDisable(GL_STENCIL_TEST);CHECKGLERROR
+ }
+ if (vid.support.ati_separate_stencil)
+ {
+ qglStencilMask(writemask);CHECKGLERROR
+ qglStencilOpSeparate(GL_FRONT, frontfail, frontzfail, frontzpass);CHECKGLERROR
+ qglStencilOpSeparate(GL_BACK, backfail, backzfail, backzpass);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
+ qglStencilOp(frontfail, frontzfail, frontzpass);CHECKGLERROR
+ qglStencilFunc(frontcompare, comparereference, comparemask);CHECKGLERROR
+ qglActiveStencilFaceEXT(GL_BACK);CHECKGLERROR
+ qglStencilMask(writemask);CHECKGLERROR
+ qglStencilOp(backfail, backzfail, backzpass);CHECKGLERROR
+ qglStencilFunc(backcompare, comparereference, comparemask);CHECKGLERROR
+#endif
+ }
+ break;
+ case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(frontfail));
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(frontzfail));
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(frontzpass));
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(frontcompare));
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFAIL, d3dstencilopforglfunc(backfail));
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILZFAIL, d3dstencilopforglfunc(backzfail));
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILPASS, d3dstencilopforglfunc(backzpass));
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CCW_STENCILFUNC, d3dcmpforglfunc(backcompare));
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
+#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:
+ //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+ break;
+ }
+}
+
+void R_SetStencil(qboolean enable, int writemask, int fail, int zfail, int zpass, int compare, int comparereference, int comparemask)
+{
+ switch (vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ CHECKGLERROR
+ if (enable)
+ {
+ qglEnable(GL_STENCIL_TEST);CHECKGLERROR
+ }
+ else
+ {
+ qglDisable(GL_STENCIL_TEST);CHECKGLERROR
+ }
+ 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
+ qglStencilFunc(compare, comparereference, comparemask);CHECKGLERROR
+ CHECKGLERROR
+ break;
+ case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+ if (vid.support.ati_separate_stencil)
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_TWOSIDEDSTENCILMODE, true);
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILENABLE, enable);
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILWRITEMASK, writemask);
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFAIL, d3dstencilopforglfunc(fail));
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILZFAIL, d3dstencilopforglfunc(zfail));
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILPASS, d3dstencilopforglfunc(zpass));
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILFUNC, d3dcmpforglfunc(compare));
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILREF, comparereference);
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_STENCILMASK, comparemask);
+#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:
+ //Con_DPrintf("FIXME SOFT %s:%i %s\n", __FILE__, __LINE__, __FUNCTION__);
+ break;
+ }
+}
+
+void GL_PolygonOffset(float planeoffset, float depthoffset)
+{
+ if (gl_state.polygonoffset[0] != planeoffset || gl_state.polygonoffset[1] != depthoffset)
+ {
+ gl_state.polygonoffset[0] = planeoffset;
+ gl_state.polygonoffset[1] = depthoffset;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ qglPolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
+ break;
+ case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_SLOPESCALEDEPTHBIAS, gl_state.polygonoffset[0]);
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_DEPTHBIAS, gl_state.polygonoffset[1] * (1.0f / 16777216.0f));
+#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_PolygonOffset(gl_state.polygonoffset[0], gl_state.polygonoffset[1]);
+ break;
+ }
+ }
+}
+
+void GL_SetMirrorState(qboolean state)
+{
+ if (v_flipped_state != state)
+ {
+ v_flipped_state = state;
+ if (gl_state.cullface == GL_BACK)
+ gl_state.cullface = GL_FRONT;
+ else if (gl_state.cullface == GL_FRONT)
+ gl_state.cullface = GL_BACK;
+ else
+ return;
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ qglCullFace(gl_state.cullface);CHECKGLERROR
+ break;
+ case RENDERPATH_D3D9:
+#ifdef SUPPORTD3D
+ IDirect3DDevice9_SetRenderState(vid_d3d9dev, D3DRS_CULLMODE, gl_state.cullface == GL_FRONT ? D3DCULL_CCW : D3DCULL_CW);
+#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_CullFace(gl_state.cullface);
+ break;
+ }
+ }
+}
+
+void GL_CullFace(int state)
+{
+ if(v_flipped_state)
+ {
+ if(state == GL_FRONT)
+ state = GL_BACK;
+ else if(state == GL_BACK)
+ state = GL_FRONT;
+ }
+
+ switch(vid.renderpath)
+ {
+ case RENDERPATH_GL11:
+ case RENDERPATH_GL13:
+ case RENDERPATH_GL20:
+ case RENDERPATH_GLES1:
+ case RENDERPATH_GLES2:
+ CHECKGLERROR
+
+ if (state != GL_NONE)
+ {
+ if (!gl_state.cullfaceenable)
+ {
+ gl_state.cullfaceenable = true;
+ qglEnable(GL_CULL_FACE);CHECKGLERROR
+ }
+ if (gl_state.cullface != state)
+ {
+ gl_state.cullface = state;
+ qglCullFace(gl_state.cullface);CHECKGLERROR
+ }
+ }
+ else