doom3quest/Projects/Android/jni/d3es-multithread-master/neo/renderer/tr_backend.cpp
Simon 4201c1deca Working stereo
very jittery though
2020-09-09 23:16:24 +01:00

436 lines
11 KiB
C++

/*
===========================================================================
Doom 3 GPL Source Code
Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
This file is part of the Doom 3 GPL Source Code ("Doom 3 Source Code").
Doom 3 Source Code is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Doom 3 Source Code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
===========================================================================
*/
#include "sys/platform.h"
#include "renderer/tr_local.h"
frameData_t *frameData;
backEndState_t backEnd;
const unsigned int NUM_FRAME_DATA = 2;
frameData_t *smpFrameData[NUM_FRAME_DATA];
volatile unsigned int smpFrame;
/*
======================
RB_SetDefaultGLState
This should initialize all GL state that any part of the entire program
may touch, including the editor.
======================
*/
void RB_SetDefaultGLState( void ) {
int i;
// Clear value for the Depth buffer
qglClearDepthf(1.0f);
// make sure our GL state vector is set correctly
memset( &backEnd.glState, 0, sizeof( backEnd.glState ) );
backEnd.glState.forceGlState = true;
// All color channels are used
qglColorMask( 1, 1, 1, 1 );
qglEnable( GL_DEPTH_TEST );
qglEnable( GL_BLEND );
qglEnable( GL_SCISSOR_TEST );
qglEnable( GL_CULL_FACE );
qglDisable( GL_STENCIL_TEST );
qglDepthMask( GL_TRUE );
qglDepthFunc( GL_ALWAYS );
qglCullFace( GL_FRONT_AND_BACK );
if ( r_useScissor.GetBool() ) {
qglScissor( 0, 0, glConfig.vidWidth, glConfig.vidHeight );
}
backEnd.glState.currentTexture = -1; // Force texture unit to be reset
for ( i = glConfig.maxTextureUnits - 1 ; i >= 0 ; i-- ) {
GL_SelectTexture( i );
globalImages->BindNull();
}
// Last active texture is Tex0
}
/*
====================
GL_SelectTexture
====================
*/
void GL_SelectTexture( int unit ) {
if ( backEnd.glState.currentTexture != unit ) {
qglActiveTexture(GL_TEXTURE0 + unit);
backEnd.glState.currentTexture = unit;
}
}
/*
====================
GL_Cull
This handles the flipping needed when the view being
rendered is a mirored view.
====================
*/
void GL_Cull( int cullType ) {
if ( backEnd.glState.faceCulling == cullType ) {
return;
}
if ( cullType == CT_TWO_SIDED ) {
qglDisable( GL_CULL_FACE );
} else {
if ( backEnd.glState.faceCulling == CT_TWO_SIDED ) {
qglEnable( GL_CULL_FACE );
}
if ( cullType == CT_BACK_SIDED ) {
if ( backEnd.viewDef->isMirror ) {
qglCullFace( GL_FRONT );
} else {
qglCullFace( GL_BACK );
}
} else {
if ( backEnd.viewDef->isMirror ) {
qglCullFace( GL_BACK );
} else {
qglCullFace( GL_FRONT );
}
}
}
backEnd.glState.faceCulling = cullType;
}
/*
=================
GL_ClearStateDelta
Clears the state delta bits, so the next GL_State
will set every item
=================
*/
void GL_ClearStateDelta( void ) {
backEnd.glState.forceGlState = true;
}
/*
====================
GL_State
This routine is responsible for setting the most commonly changed state
====================
*/
void GL_State( int stateBits ) {
int diff;
if ( !r_useStateCaching.GetBool() || backEnd.glState.forceGlState ) {
// make sure everything is set all the time, so we
// can see if our delta checking is screwing up
diff = -1;
backEnd.glState.forceGlState = false;
} else {
diff = stateBits ^ backEnd.glState.glStateBits;
if ( !diff ) {
return;
}
}
//
// check depthFunc bits
//
if ( diff & ( GLS_DEPTHFUNC_EQUAL | GLS_DEPTHFUNC_LESS | GLS_DEPTHFUNC_ALWAYS ) ) {
if ( stateBits & GLS_DEPTHFUNC_EQUAL ) {
qglDepthFunc( GL_EQUAL );
} else if ( stateBits & GLS_DEPTHFUNC_ALWAYS ) {
qglDepthFunc( GL_ALWAYS );
} else {
qglDepthFunc( GL_LEQUAL );
}
}
//
// check blend bits
//
if ( diff & ( GLS_SRCBLEND_BITS | GLS_DSTBLEND_BITS ) ) {
GLenum srcFactor, dstFactor;
switch ( stateBits & GLS_SRCBLEND_BITS ) {
case GLS_SRCBLEND_ZERO:
srcFactor = GL_ZERO;
break;
case GLS_SRCBLEND_ONE:
srcFactor = GL_ONE;
break;
case GLS_SRCBLEND_DST_COLOR:
srcFactor = GL_DST_COLOR;
break;
case GLS_SRCBLEND_ONE_MINUS_DST_COLOR:
srcFactor = GL_ONE_MINUS_DST_COLOR;
break;
case GLS_SRCBLEND_SRC_ALPHA:
srcFactor = GL_SRC_ALPHA;
break;
case GLS_SRCBLEND_ONE_MINUS_SRC_ALPHA:
srcFactor = GL_ONE_MINUS_SRC_ALPHA;
break;
case GLS_SRCBLEND_DST_ALPHA:
srcFactor = GL_DST_ALPHA;
break;
case GLS_SRCBLEND_ONE_MINUS_DST_ALPHA:
srcFactor = GL_ONE_MINUS_DST_ALPHA;
break;
case GLS_SRCBLEND_ALPHA_SATURATE:
srcFactor = GL_SRC_ALPHA_SATURATE;
break;
default:
srcFactor = GL_ONE; // to get warning to shut up
common->Error( "GL_State: invalid src blend state bits\n" );
break;
}
switch ( stateBits & GLS_DSTBLEND_BITS ) {
case GLS_DSTBLEND_ZERO:
dstFactor = GL_ZERO;
break;
case GLS_DSTBLEND_ONE:
dstFactor = GL_ONE;
break;
case GLS_DSTBLEND_SRC_COLOR:
dstFactor = GL_SRC_COLOR;
break;
case GLS_DSTBLEND_ONE_MINUS_SRC_COLOR:
dstFactor = GL_ONE_MINUS_SRC_COLOR;
break;
case GLS_DSTBLEND_SRC_ALPHA:
dstFactor = GL_SRC_ALPHA;
break;
case GLS_DSTBLEND_ONE_MINUS_SRC_ALPHA:
dstFactor = GL_ONE_MINUS_SRC_ALPHA;
break;
case GLS_DSTBLEND_DST_ALPHA:
dstFactor = GL_DST_ALPHA;
break;
case GLS_DSTBLEND_ONE_MINUS_DST_ALPHA:
dstFactor = GL_ONE_MINUS_DST_ALPHA;
break;
default:
dstFactor = GL_ONE; // to get warning to shut up
common->Error( "GL_State: invalid dst blend state bits\n" );
break;
}
qglBlendFunc( srcFactor, dstFactor );
}
//
// check depthmask
//
if ( diff & GLS_DEPTHMASK ) {
if ( stateBits & GLS_DEPTHMASK ) {
qglDepthMask( GL_FALSE );
} else {
qglDepthMask( GL_TRUE );
}
}
//
// check colormask
//
if ( diff & (GLS_REDMASK|GLS_GREENMASK|GLS_BLUEMASK|GLS_ALPHAMASK) ) {
GLboolean r, g, b, a;
r = ( stateBits & GLS_REDMASK ) ? 0 : 1;
g = ( stateBits & GLS_GREENMASK ) ? 0 : 1;
b = ( stateBits & GLS_BLUEMASK ) ? 0 : 1;
a = ( stateBits & GLS_ALPHAMASK ) ? 0 : 1;
qglColorMask( r, g, b, a );
}
backEnd.glState.glStateBits = stateBits;
}
/*
============================================================================
RENDER BACK END THREAD FUNCTIONS
============================================================================
*/
/*
=============
RB_SetBuffer
=============
*/
static void RB_SetBuffer( const void *data ) {
const setBufferCommand_t *cmd;
// see which draw buffer we want to render the frame to
cmd = (const setBufferCommand_t *)data;
backEnd.frameCount = cmd->frameCount;
// Disabled for OES2
//qglDrawBuffer( cmd->buffer );
GLimp_SetupFrame();
// clear screen for debugging
// automatically enable this with several other debug tools
// that might leave unrendered portions of the screen
if ( r_clear.GetFloat() || idStr::Length( r_clear.GetString() ) != 1 || r_lockSurfaces.GetBool() || r_singleArea.GetBool() ) {
float c[3];
if ( sscanf( r_clear.GetString(), "%f %f %f", &c[0], &c[1], &c[2] ) == 3 ) {
qglClearColor( c[0], c[1], c[2], 1 );
} else if ( r_clear.GetInteger() == 2 ) {
qglClearColor( 0.0f, 0.0f, 0.0f, 1.0f );
} else {
qglClearColor( 0.4f, 0.0f, 0.25f, 1.0f );
}
qglClear( GL_COLOR_BUFFER_BIT );
}
}
/*
=============
RB_SwapBuffers
=============
*/
const void RB_SwapBuffers( const void *data ) {
#ifdef WEBGL
// GAB Note Dec 2018: Clear the Alpha channel, so that final render will not blend with the HTML5 background (canvas with premultiplied alpha)
qglColorMask(0, 0, 0, 1);
qglClear(GL_COLOR_BUFFER_BIT);
#endif
// force a gl sync if requested
if ( r_finish.GetBool() ) {
qglFinish();
}
// don't flip if drawing to front buffer
GLimp_SwapBuffers();
}
/*
=============
RB_CopyRender
Copy part of the current framebuffer to an image
=============
*/
const void RB_CopyRender( const void *data ) {
const copyRenderCommand_t *cmd;
cmd = (const copyRenderCommand_t *)data;
if ( r_skipCopyTexture.GetBool() ) {
return;
}
if (cmd->image) {
cmd->image->CopyFramebuffer( cmd->x, cmd->y, cmd->imageWidth, cmd->imageHeight, false );
}
}
/*
====================
RB_ExecuteBackEndCommands
This function will be called syncronously if running without
smp extensions, or asyncronously by another thread.
====================
*/
int backEndStartTime, backEndFinishTime;
void RB_ExecuteBackEndCommands( const emptyCommand_t *cmds ) {
// r_debugRenderToTexture
int c_draw3d = 0, c_draw2d = 0, c_setBuffers = 0, c_swapBuffers = 0, c_copyRenders = 0;
if ( cmds->commandId == RC_NOP && !cmds->next ) {
return;
}
{
const emptyCommand_t *cmd = cmds;
backEndStartTime = Sys_Milliseconds();
// needed for editor rendering
RB_SetDefaultGLState();
for (; cmd; cmd = (const emptyCommand_t *) cmd->next) {
switch (cmd->commandId) {
case RC_NOP:
break;
case RC_DRAW_VIEW:
RB_DrawView(cmd);
if (((const drawSurfsCommand_t *) cmd)->viewDef->viewEntitys) {
c_draw3d++;
} else {
c_draw2d++;
}
break;
case RC_SET_BUFFER:
RB_SetBuffer(cmd);
c_setBuffers++;
break;
case RC_SWAP_BUFFERS:
RB_SwapBuffers(cmd);
c_swapBuffers++;
break;
case RC_COPY_RENDER:
RB_CopyRender(cmd);
c_copyRenders++;
break;
default:
common->Error("RB_ExecuteBackEndCommands: bad commandId");
break;
}
}
}
// stop rendering on this thread
backEndFinishTime = Sys_Milliseconds();
backEnd.pc.msec = backEndFinishTime - backEndStartTime;
if ( r_debugRenderToTexture.GetInteger() == 1 ) {
common->Printf( "3d: %i, 2d: %i, SetBuf: %i, SwpBuf: %i, CpyRenders: %i, CpyFrameBuf: %i\n", c_draw3d, c_draw2d, c_setBuffers, c_swapBuffers, c_copyRenders, backEnd.c_copyFrameBuffer );
backEnd.c_copyFrameBuffer = 0;
}
}