/** * @brief GL_SelectTexture * @param[in] unit */ void GL_SelectTexture(int unit) { if (glState.currenttmu == unit) { return; } if (unit == 0) { qglActiveTextureARB(GL_TEXTURE0_ARB); Ren_LogComment("glActiveTextureARB( GL_TEXTURE0_ARB )\n"); qglClientActiveTextureARB(GL_TEXTURE0_ARB); Ren_LogComment("glClientActiveTextureARB( GL_TEXTURE0_ARB )\n"); } else if (unit == 1) { qglActiveTextureARB(GL_TEXTURE1_ARB); Ren_LogComment("glActiveTextureARB( GL_TEXTURE1_ARB )\n"); qglClientActiveTextureARB(GL_TEXTURE1_ARB); Ren_LogComment("glClientActiveTextureARB( GL_TEXTURE1_ARB )\n"); } else { Ren_Drop("GL_SelectTexture: unit = %i", unit); } glState.currenttmu = unit; }
void GL_Bind(image_t *image) { int texnum; if (!image) { Ren_Warning("GL_Bind: NULL image\n"); image = tr.defaultImage; } else { Ren_LogComment("--- GL_Bind( %s ) ---\n", image->name); } texnum = image->texnum; if (r_nobind->integer && tr.blackImage) { // performance evaluation option texnum = tr.blackImage->texnum; image = tr.blackImage; } if (glState.currenttextures[glState.currenttmu] != texnum) { image->frameUsed = tr.frameCount; glState.currenttextures[glState.currenttmu] = texnum; glBindTexture(image->type, texnum); } }
/* ============ R_BindVBO ============ */ void R_BindVBO(VBO_t *vbo) { if (!vbo) { //R_BindNullVBO(); Ren_Drop("R_BindNullVBO: NULL vbo"); return; } Ren_LogComment("--- R_BindVBO( %s ) ---\n", vbo->name); if (glState.currentVBO != vbo) { glState.currentVBO = vbo; glState.vertexAttribPointersSet = 0; glState.vertexAttribsInterpolation = 0; glState.vertexAttribsOldFrame = 0; glState.vertexAttribsNewFrame = 0; glBindBuffer(GL_ARRAY_BUFFER, vbo->vertexesVBO); backEnd.pc.c_vboVertexBuffers++; //GL_VertexAttribPointers(ATTR_BITS); } }
void R_BindFBO(FBO_t *fbo) { if (!fbo) { R_BindNullFBO(); return; } Ren_LogComment("--- R_BindFBO( %s ) ---\n", fbo->name); if (glState.currentFBO != fbo) { glBindFramebuffer(GL_FRAMEBUFFER, fbo->frameBuffer); /* if(fbo->colorBuffers[0]) { glBindRenderbuffer(GL_RENDERBUFFER, fbo->colorBuffers[0]); } */ /* if(fbo->depthBuffer) { glBindRenderbuffer(GL_RENDERBUFFER, fbo->depthBuffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, fbo->depthBuffer); } */ glState.currentFBO = fbo; } }
/* ============ R_BindNullIBO ============ */ void R_BindNullIBO(void) { Ren_LogComment("--- R_BindNullIBO ---\n"); if (glState.currentIBO) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glState.currentIBO = NULL; glState.vertexAttribPointersSet = 0; } }
void R_BindNullFBO(void) { Ren_LogComment("--- R_BindNullFBO ---\n"); if (glState.currentFBO && glConfig2.framebufferObjectAvailable) { glBindFramebuffer(GL_FRAMEBUFFER, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0); glState.currentFBO = NULL; } }
/* ============ R_BindNullVBO ============ */ void R_BindNullVBO(void) { Ren_LogComment("--- R_BindNullVBO ---\n"); if (glState.currentVBO) { glBindBuffer(GL_ARRAY_BUFFER, 0); glState.currentVBO = NULL; } GL_CheckErrors(); }
/** * @brief RB_SwapBuffers * @param[in] data * @return */ const void *RB_SwapBuffers(const void *data) { const swapBuffersCommand_t *cmd; // finish any 2D drawing if needed if (tess.numIndexes) { RB_EndSurface(); } // texture swapping test if (r_showImages->integer) { RB_ShowImages(); } RB_GammaScreen(); cmd = ( const swapBuffersCommand_t * ) data; // we measure overdraw by reading back the stencil buffer and // counting up the number of increments that have happened if (r_measureOverdraw->integer) { int i; long sum = 0; unsigned char *stencilReadback; stencilReadback = ri.Hunk_AllocateTempMemory(glConfig.vidWidth * glConfig.vidHeight); qglReadPixels(0, 0, glConfig.vidWidth, glConfig.vidHeight, GL_STENCIL_INDEX, GL_UNSIGNED_BYTE, stencilReadback); for (i = 0; i < glConfig.vidWidth * glConfig.vidHeight; i++) { sum += stencilReadback[i]; } backEnd.pc.c_overDraw += sum; ri.Hunk_FreeTempMemory(stencilReadback); } if (!glState.finishCalled) { qglFinish(); } Ren_LogComment("***************** RB_SwapBuffers *****************\n\n\n"); ri.GLimp_SwapFrame(); backEnd.projection2D = qfalse; return ( const void * ) (cmd + 1); }
void GL_SelectTexture(int unit) { if (glState.currenttmu == unit) { return; } if (unit >= 0 && unit <= 31) { glActiveTexture(GL_TEXTURE0 + unit); Ren_LogComment("glActiveTexture( GL_TEXTURE%i )\n", unit); } else { Ren_Drop("GL_SelectTexture: unit = %i", unit); } glState.currenttmu = unit; }
/* ============ R_BindIBO ============ */ void R_BindIBO(IBO_t *ibo) { if (!ibo) { //R_BindNullIBO(); Ren_Drop("R_BindIBO: NULL ibo"); return; } Ren_LogComment("--- R_BindIBO( %s ) ---\n", ibo->name); if (glState.currentIBO != ibo) { glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo->indexesVBO); glState.currentIBO = ibo; backEnd.pc.c_vboIndexBuffers++; } }
/* @@@@@@@@@@@@@@@@@@@@@ RE_RenderScene Draw a 3D view into a part of the window, then return to 2D drawing. Rendering a scene may require multiple views to be rendered to handle mirrors, @@@@@@@@@@@@@@@@@@@@@ */ void RE_RenderScene(const refdef_t *fd) { viewParms_t parms; int startTime; if (!tr.registered) { return; } Ren_LogComment("====== RE_RenderScene =====\n"); if (r_norefresh->integer) { return; } startTime = ri.Milliseconds(); if (!tr.world && !(fd->rdflags & RDF_NOWORLDMODEL)) { Ren_Drop("R_RenderScene: NULL worldmodel"); } memcpy(tr.refdef.text, fd->text, sizeof(tr.refdef.text)); tr.refdef.x = fd->x; tr.refdef.y = fd->y; tr.refdef.width = fd->width; tr.refdef.height = fd->height; tr.refdef.fov_x = fd->fov_x; tr.refdef.fov_y = fd->fov_y; VectorCopy(fd->vieworg, tr.refdef.vieworg); VectorCopy(fd->viewaxis[0], tr.refdef.viewaxis[0]); VectorCopy(fd->viewaxis[1], tr.refdef.viewaxis[1]); VectorCopy(fd->viewaxis[2], tr.refdef.viewaxis[2]); tr.refdef.time = fd->time; tr.refdef.rdflags = fd->rdflags; if (fd->rdflags & RDF_SKYBOXPORTAL) { skyboxportal = 1; } // copy the areamask data over and note if it has changed, which // will force a reset of the visible leafs even if the view hasn't moved tr.refdef.areamaskModified = qfalse; if (!(tr.refdef.rdflags & RDF_NOWORLDMODEL)) { int areaDiff; int i; // compare the area bits areaDiff = 0; for (i = 0 ; i < MAX_MAP_AREA_BYTES / 4 ; i++) { areaDiff |= ((int *)tr.refdef.areamask)[i] ^ ((int *)fd->areamask)[i]; ((int *)tr.refdef.areamask)[i] = ((int *)fd->areamask)[i]; } if (areaDiff) { // a door just opened or something tr.refdef.areamaskModified = qtrue; } } // derived info tr.refdef.floatTime = (double)tr.refdef.time * 0.001; tr.refdef.numDrawSurfs = r_firstSceneDrawSurf; tr.refdef.drawSurfs = backEndData->drawSurfs; tr.refdef.num_entities = r_numentities - r_firstSceneEntity; tr.refdef.entities = &backEndData->entities[r_firstSceneEntity]; tr.refdef.num_dlights = r_numdlights - r_firstSceneDlight; tr.refdef.dlights = &backEndData->dlights[r_firstSceneDlight]; tr.refdef.dlightBits = 0; tr.refdef.num_coronas = r_numcoronas - r_firstSceneCorona; tr.refdef.coronas = &backEndData->coronas[r_firstSceneCorona]; tr.refdef.numPolys = r_numpolys - r_firstScenePoly; tr.refdef.polys = &backEndData->polys[r_firstScenePoly]; tr.refdef.numPolyBuffers = r_numpolybuffers - r_firstScenePolybuffer; tr.refdef.polybuffers = &backEndData->polybuffers[r_firstScenePolybuffer]; tr.refdef.numDecalProjectors = r_numDecalProjectors - r_firstSceneDecalProjector; tr.refdef.decalProjectors = &backEndData->decalProjectors[r_firstSceneDecalProjector]; tr.refdef.numDecals = 0; tr.refdef.decals = &backEndData->decals[r_firstSceneDecal]; // a single frame may have multiple scenes draw inside it -- // a 3D game view, 3D status bar renderings, 3D menus, etc. // They need to be distinguished by the light flare code, because // the visibility state for a given surface may be different in // each scene / view. tr.frameSceneNum++; tr.sceneCount++; // setup view parms for the initial view // set up viewport // The refdef takes 0-at-the-top y coordinates, so // convert to GL's 0-at-the-bottom space memset(&parms, 0, sizeof(parms)); parms.viewportX = tr.refdef.x; parms.viewportY = glConfig.vidHeight - (tr.refdef.y + tr.refdef.height); parms.viewportWidth = tr.refdef.width; parms.viewportHeight = tr.refdef.height; parms.isPortal = qfalse; parms.fovX = tr.refdef.fov_x; parms.fovY = tr.refdef.fov_y; VectorCopy(fd->vieworg, parms.orientation.origin); VectorCopy(fd->viewaxis[0], parms.orientation.axis[0]); VectorCopy(fd->viewaxis[1], parms.orientation.axis[1]); VectorCopy(fd->viewaxis[2], parms.orientation.axis[2]); VectorCopy(fd->vieworg, parms.pvsOrigin); R_RenderView(&parms); // the next scene rendered in this frame will tack on after this one r_firstSceneDrawSurf = tr.refdef.numDrawSurfs; r_firstSceneDecal += tr.refdef.numDecals; r_firstSceneEntity = r_numentities; r_firstSceneDlight = r_numdlights; r_firstScenePoly = r_numpolys; r_firstScenePolybuffer = r_numpolybuffers; tr.frontEndMsec += ri.Milliseconds() - startTime; }
void GL_Unbind() { Ren_LogComment("--- GL_Unbind() ---\n"); glBindTexture(GL_TEXTURE_2D, 0); }
/* @@@@@@@@@@@@@@@@@@@@@ RE_RenderScene Draw a 3D view into a part of the window, then return to 2D drawing. Rendering a scene may require multiple views to be rendered to handle mirrors, @@@@@@@@@@@@@@@@@@@@@ */ void RE_RenderScene(const refdef_t *fd) { viewParms_t parms; int startTime; if (!tr.registered) { return; } Ren_LogComment("====== RE_RenderScene =====\n"); if (r_norefresh->integer) { return; } startTime = ri.Milliseconds(); if (!tr.world && !(fd->rdflags & RDF_NOWORLDMODEL)) { Ren_Drop("R_RenderScene: NULL worldmodel"); } Com_Memcpy(tr.refdef.text, fd->text, sizeof(tr.refdef.text)); tr.refdef.x = fd->x; tr.refdef.y = fd->y; tr.refdef.width = fd->width; tr.refdef.height = fd->height; tr.refdef.fov_x = fd->fov_x; tr.refdef.fov_y = fd->fov_y; VectorCopy(fd->vieworg, tr.refdef.vieworg); VectorCopy(fd->viewaxis[0], tr.refdef.viewaxis[0]); VectorCopy(fd->viewaxis[1], tr.refdef.viewaxis[1]); VectorCopy(fd->viewaxis[2], tr.refdef.viewaxis[2]); tr.refdef.time = fd->time; tr.refdef.rdflags = fd->rdflags; /* if(fd->rdflags & RDF_SKYBOXPORTAL) { Ren_Print("skyboxportal = 1\n"); } */ // copy the areamask data over and note if it has changed, which // will force a reset of the visible leafs even if the view hasn't moved tr.refdef.areamaskModified = qfalse; if (!(tr.refdef.rdflags & RDF_NOWORLDMODEL) && !((tr.refdef.rdflags & RDF_SKYBOXPORTAL) && tr.world->numSkyNodes > 0)) { int areaDiff; int i; // compare the area bits areaDiff = 0; for (i = 0; i < MAX_MAP_AREA_BYTES / 4; i++) { areaDiff |= ((int *)tr.refdef.areamask)[i] ^ ((int *)fd->areamask)[i]; ((int *)tr.refdef.areamask)[i] = ((int *)fd->areamask)[i]; } if (areaDiff) { // a door just opened or something tr.refdef.areamaskModified = qtrue; } } R_AddWorldLightsToScene(); // derived info tr.refdef.floatTime = tr.refdef.time * 0.001f; tr.refdef.numDrawSurfs = r_firstSceneDrawSurf; tr.refdef.drawSurfs = backEndData->drawSurfs; tr.refdef.numInteractions = r_firstSceneInteraction; tr.refdef.interactions = backEndData->interactions; tr.refdef.numEntities = r_numEntities - r_firstSceneEntity; tr.refdef.entities = &backEndData->entities[r_firstSceneEntity]; tr.refdef.numLights = r_numLights - r_firstSceneLight; tr.refdef.lights = &backEndData->lights[r_firstSceneLight]; tr.refdef.num_coronas = r_numcoronas - r_firstSceneCorona; tr.refdef.coronas = &backEndData->coronas[r_firstSceneCorona]; tr.refdef.numPolys = r_numPolys - r_firstScenePoly; tr.refdef.polys = &backEndData->polys[r_firstScenePoly]; tr.refdef.numPolybuffers = r_numPolybuffers - r_firstScenePolybuffer; tr.refdef.polybuffers = &backEndData->polybuffers[r_firstScenePolybuffer]; tr.refdef.numDecalProjectors = r_numDecalProjectors - r_firstSceneDecalProjector; tr.refdef.decalProjectors = &backEndData->decalProjectors[r_firstSceneDecalProjector]; tr.refdef.numDecals = 0; tr.refdef.decals = &backEndData->decals[r_firstSceneDecal]; // a single frame may have multiple scenes draw inside it -- // a 3D game view, 3D status bar renderings, 3D menus, etc. // They need to be distinguished by the light flare code, because // the visibility state for a given surface may be different in // each scene / view. tr.frameSceneNum++; tr.sceneCount++; // a scene can have multiple views caused by mirrors or portals // the number of views is restricted so we can use hardware occlusion queries // and put them into the BSP nodes for each view tr.viewCount = -1; // setup view parms for the initial view // // set up viewport // The refdef takes 0-at-the-top y coordinates, so // convert to GL's 0-at-the-bottom space // Com_Memset(&parms, 0, sizeof(parms)); #if 1 if (tr.refdef.pixelTarget == NULL) { parms.viewportX = tr.refdef.x; parms.viewportY = glConfig.vidHeight - (tr.refdef.y + tr.refdef.height); } else { // Driver bug, if we try and do pixel target work along the top edge of a window // we can end up capturing part of the status bar. (see screenshot corruption..) // Soooo.. use the middle. parms.viewportX = glConfig.vidWidth / 2; parms.viewportY = glConfig.vidHeight / 2; } #else parms.viewportX = tr.refdef.x; parms.viewportY = glConfig.vidHeight - (tr.refdef.y + tr.refdef.height); #endif parms.viewportWidth = tr.refdef.width; parms.viewportHeight = tr.refdef.height; Vector4Set(parms.viewportVerts[0], parms.viewportX, parms.viewportY, 0, 1); Vector4Set(parms.viewportVerts[1], parms.viewportX + parms.viewportWidth, parms.viewportY, 0, 1); Vector4Set(parms.viewportVerts[2], parms.viewportX + parms.viewportWidth, parms.viewportY + parms.viewportHeight, 0, 1); Vector4Set(parms.viewportVerts[3], parms.viewportX, parms.viewportY + parms.viewportHeight, 0, 1); parms.isPortal = qfalse; parms.fovX = tr.refdef.fov_x; parms.fovY = tr.refdef.fov_y; parms.stereoFrame = tr.refdef.stereoFrame; VectorCopy(fd->vieworg, parms.orientation.origin); VectorCopy(fd->viewaxis[0], parms.orientation.axis[0]); VectorCopy(fd->viewaxis[1], parms.orientation.axis[1]); VectorCopy(fd->viewaxis[2], parms.orientation.axis[2]); VectorCopy(fd->vieworg, parms.pvsOrigin); R_RenderView(&parms); // the next scene rendered in this frame will tack on after this one r_firstSceneDrawSurf = tr.refdef.numDrawSurfs; r_firstSceneInteraction = tr.refdef.numInteractions; r_firstSceneDecal += tr.refdef.numDecals; r_firstSceneEntity = r_numEntities; r_firstSceneLight = r_numLights; r_firstScenePoly = r_numPolys; r_firstScenePolybuffer = r_numPolybuffers; tr.frontEndMsec += ri.Milliseconds() - startTime; }
/** * @brief Will be called once for each RE_EndFrame */ void RE_BeginFrame() { drawBufferCommand_t *cmd; if (!tr.registered) { return; } Ren_LogComment("--- RE_BeginFrame ---\n"); glState.finishCalled = qfalse; tr.frameCount++; tr.frameSceneNum = 0; tr.viewCount = 0; // do overdraw measurement if (r_measureOverdraw->integer) { if (glConfig.stencilBits < 4) { Ren_Print("Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits); ri.Cvar_Set("r_measureOverdraw", "0"); } else if (r_shadows->integer == 2) { Ren_Print("Warning: stencil shadows and overdraw measurement are mutually exclusive\n"); ri.Cvar_Set("r_measureOverdraw", "0"); } else { R_IssuePendingRenderCommands(); glEnable(GL_STENCIL_TEST); glStencilMask(~0U); GL_ClearStencil(0U); glStencilFunc(GL_ALWAYS, 0U, ~0U); glStencilOp(GL_KEEP, GL_INCR, GL_INCR); } r_measureOverdraw->modified = qfalse; } else { // this is only reached if it was on and is now off if (r_measureOverdraw->modified) { R_IssuePendingRenderCommands(); glDisable(GL_STENCIL_TEST); } r_measureOverdraw->modified = qfalse; } // texturemode stuff if (r_textureMode->modified) { R_IssuePendingRenderCommands(); GL_TextureMode(r_textureMode->string); r_textureMode->modified = qfalse; } // gamma stuff if (r_gamma->modified) { r_gamma->modified = qfalse; R_IssuePendingRenderCommands(); R_SetColorMappings(); } // check for errors if (!r_ignoreGLErrors->integer) { int err; char s[128]; R_IssuePendingRenderCommands(); if ((err = glGetError()) != GL_NO_ERROR) { switch (err) { case GL_INVALID_ENUM: Q_strcpy(s, "GL_INVALID_ENUM"); break; case GL_INVALID_VALUE: Q_strcpy(s, "GL_INVALID_VALUE"); break; case GL_INVALID_OPERATION: Q_strcpy(s, "GL_INVALID_OPERATION"); break; case GL_STACK_OVERFLOW: Q_strcpy(s, "GL_STACK_OVERFLOW"); break; case GL_STACK_UNDERFLOW: Q_strcpy(s, "GL_STACK_UNDERFLOW"); break; case GL_OUT_OF_MEMORY: Q_strcpy(s, "GL_OUT_OF_MEMORY"); break; case GL_TABLE_TOO_LARGE: Q_strcpy(s, "GL_TABLE_TOO_LARGE"); break; case GL_INVALID_FRAMEBUFFER_OPERATION_EXT: Q_strcpy(s, "GL_INVALID_FRAMEBUFFER_OPERATION_EXT"); break; default: Com_sprintf(s, sizeof(s), "0x%X", err); break; } //Ren_Fatal( "caught OpenGL error: %s in file %s line %i", s, filename, line); Ren_Fatal("RE_BeginFrame() - glGetError() failed (%s)!\n", s); } } // draw buffer stuff cmd = (drawBufferCommand_t *)R_GetCommandBuffer(sizeof(*cmd)); if (!cmd) { return; } cmd->commandId = RC_DRAW_BUFFER; if (!Q_stricmp(r_drawBuffer->string, "GL_FRONT")) { cmd->buffer = (int)GL_FRONT; } else { cmd->buffer = (int)GL_BACK; } }