コード例 #1
0
ファイル: tr_backend.c プロジェクト: etlegacy/etlegacy
/**
 * @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;
}
コード例 #2
0
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);
	}
}
コード例 #3
0
ファイル: tr_vbo.c プロジェクト: dustinduse/etlegacy
/*
============
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);
	}
}
コード例 #4
0
ファイル: tr_fbo.c プロジェクト: dustinduse/etlegacy
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;
	}
}
コード例 #5
0
ファイル: tr_vbo.c プロジェクト: dustinduse/etlegacy
/*
============
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;
	}
}
コード例 #6
0
ファイル: tr_fbo.c プロジェクト: dustinduse/etlegacy
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;
	}
}
コード例 #7
0
ファイル: tr_vbo.c プロジェクト: dustinduse/etlegacy
/*
============
R_BindNullVBO
============
*/
void R_BindNullVBO(void)
{
	Ren_LogComment("--- R_BindNullVBO ---\n");

	if (glState.currentVBO)
	{
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glState.currentVBO = NULL;
	}

	GL_CheckErrors();
}
コード例 #8
0
ファイル: tr_backend.c プロジェクト: etlegacy/etlegacy
/**
 * @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);
}
コード例 #9
0
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;
}
コード例 #10
0
ファイル: tr_vbo.c プロジェクト: dustinduse/etlegacy
/*
============
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++;
	}
}
コード例 #11
0
ファイル: tr_scene.c プロジェクト: dustinduse/etlegacy
/*
@@@@@@@@@@@@@@@@@@@@@
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;
}
コード例 #12
0
void GL_Unbind()
{
	Ren_LogComment("--- GL_Unbind() ---\n");

	glBindTexture(GL_TEXTURE_2D, 0);
}
コード例 #13
0
ファイル: tr_scene.c プロジェクト: rafal1137/etlegacy
/*
@@@@@@@@@@@@@@@@@@@@@
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;
}
コード例 #14
0
ファイル: tr_cmds.c プロジェクト: etlegacy/etlegacy
/**
 * @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;
	}
}