tr_cmds.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. #include "tr_local.h"
  19. volatile renderCommandList_t *renderCommandList;
  20. volatile qboolean renderThreadActive;
  21. /*
  22. =====================
  23. R_PerformanceCounters
  24. =====================
  25. */
  26. void R_PerformanceCounters( void ) {
  27. if ( !r_speeds->integer ) {
  28. // clear the counters even if we aren't printing
  29. Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
  30. Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
  31. return;
  32. }
  33. if (r_speeds->integer == 1) {
  34. ri.Printf (PRINT_ALL, "%i/%i shaders/surfs %i leafs %i verts %i/%i tris %.2f mtex %.2f dc\n",
  35. backEnd.pc.c_shaders, backEnd.pc.c_surfaces, tr.pc.c_leafs, backEnd.pc.c_vertexes,
  36. backEnd.pc.c_indexes/3, backEnd.pc.c_totalIndexes/3,
  37. R_SumOfUsedImages()/(1000000.0f), backEnd.pc.c_overDraw / (float)(glConfig.vidWidth * glConfig.vidHeight) );
  38. } else if (r_speeds->integer == 2) {
  39. ri.Printf (PRINT_ALL, "(patch) %i sin %i sclip %i sout %i bin %i bclip %i bout\n",
  40. tr.pc.c_sphere_cull_patch_in, tr.pc.c_sphere_cull_patch_clip, tr.pc.c_sphere_cull_patch_out,
  41. tr.pc.c_box_cull_patch_in, tr.pc.c_box_cull_patch_clip, tr.pc.c_box_cull_patch_out );
  42. ri.Printf (PRINT_ALL, "(md3) %i sin %i sclip %i sout %i bin %i bclip %i bout\n",
  43. tr.pc.c_sphere_cull_md3_in, tr.pc.c_sphere_cull_md3_clip, tr.pc.c_sphere_cull_md3_out,
  44. tr.pc.c_box_cull_md3_in, tr.pc.c_box_cull_md3_clip, tr.pc.c_box_cull_md3_out );
  45. } else if (r_speeds->integer == 3) {
  46. ri.Printf (PRINT_ALL, "viewcluster: %i\n", tr.viewCluster );
  47. } else if (r_speeds->integer == 4) {
  48. if ( backEnd.pc.c_dlightVertexes ) {
  49. ri.Printf (PRINT_ALL, "dlight srf:%i culled:%i verts:%i tris:%i\n",
  50. tr.pc.c_dlightSurfaces, tr.pc.c_dlightSurfacesCulled,
  51. backEnd.pc.c_dlightVertexes, backEnd.pc.c_dlightIndexes / 3 );
  52. }
  53. }
  54. else if (r_speeds->integer == 5 )
  55. {
  56. ri.Printf( PRINT_ALL, "zFar: %.0f\n", tr.viewParms.zFar );
  57. }
  58. else if (r_speeds->integer == 6 )
  59. {
  60. ri.Printf( PRINT_ALL, "flare adds:%i tests:%i renders:%i\n",
  61. backEnd.pc.c_flareAdds, backEnd.pc.c_flareTests, backEnd.pc.c_flareRenders );
  62. }
  63. Com_Memset( &tr.pc, 0, sizeof( tr.pc ) );
  64. Com_Memset( &backEnd.pc, 0, sizeof( backEnd.pc ) );
  65. }
  66. /*
  67. ====================
  68. R_InitCommandBuffers
  69. ====================
  70. */
  71. void R_InitCommandBuffers( void ) {
  72. glConfig.smpActive = qfalse;
  73. if ( r_smp->integer ) {
  74. ri.Printf( PRINT_ALL, "Trying SMP acceleration...\n" );
  75. if ( GLimp_SpawnRenderThread( RB_RenderThread ) ) {
  76. ri.Printf( PRINT_ALL, "...succeeded.\n" );
  77. glConfig.smpActive = qtrue;
  78. } else {
  79. ri.Printf( PRINT_ALL, "...failed.\n" );
  80. }
  81. }
  82. }
  83. /*
  84. ====================
  85. R_ShutdownCommandBuffers
  86. ====================
  87. */
  88. void R_ShutdownCommandBuffers( void ) {
  89. // kill the rendering thread
  90. if ( glConfig.smpActive ) {
  91. GLimp_WakeRenderer( NULL );
  92. glConfig.smpActive = qfalse;
  93. }
  94. }
  95. /*
  96. ====================
  97. R_IssueRenderCommands
  98. ====================
  99. */
  100. int c_blockedOnRender;
  101. int c_blockedOnMain;
  102. void R_IssueRenderCommands( qboolean runPerformanceCounters ) {
  103. renderCommandList_t *cmdList;
  104. cmdList = &backEndData[tr.smpFrame]->commands;
  105. assert(cmdList); // bk001205
  106. // add an end-of-list command
  107. *(int *)(cmdList->cmds + cmdList->used) = RC_END_OF_LIST;
  108. // clear it out, in case this is a sync and not a buffer flip
  109. cmdList->used = 0;
  110. if ( glConfig.smpActive ) {
  111. // if the render thread is not idle, wait for it
  112. if ( renderThreadActive ) {
  113. c_blockedOnRender++;
  114. if ( r_showSmp->integer ) {
  115. ri.Printf( PRINT_ALL, "R" );
  116. }
  117. } else {
  118. c_blockedOnMain++;
  119. if ( r_showSmp->integer ) {
  120. ri.Printf( PRINT_ALL, "." );
  121. }
  122. }
  123. // sleep until the renderer has completed
  124. GLimp_FrontEndSleep();
  125. }
  126. // at this point, the back end thread is idle, so it is ok
  127. // to look at it's performance counters
  128. if ( runPerformanceCounters ) {
  129. R_PerformanceCounters();
  130. }
  131. // actually start the commands going
  132. if ( !r_skipBackEnd->integer ) {
  133. // let it start on the new batch
  134. if ( !glConfig.smpActive ) {
  135. RB_ExecuteRenderCommands( cmdList->cmds );
  136. } else {
  137. GLimp_WakeRenderer( cmdList );
  138. }
  139. }
  140. }
  141. /*
  142. ====================
  143. R_SyncRenderThread
  144. Issue any pending commands and wait for them to complete.
  145. After exiting, the render thread will have completed its work
  146. and will remain idle and the main thread is free to issue
  147. OpenGL calls until R_IssueRenderCommands is called.
  148. ====================
  149. */
  150. void R_SyncRenderThread( void ) {
  151. if ( !tr.registered ) {
  152. return;
  153. }
  154. R_IssueRenderCommands( qfalse );
  155. if ( !glConfig.smpActive ) {
  156. return;
  157. }
  158. GLimp_FrontEndSleep();
  159. }
  160. /*
  161. ============
  162. R_GetCommandBuffer
  163. make sure there is enough command space, waiting on the
  164. render thread if needed.
  165. ============
  166. */
  167. void *R_GetCommandBuffer( int bytes ) {
  168. renderCommandList_t *cmdList;
  169. cmdList = &backEndData[tr.smpFrame]->commands;
  170. // always leave room for the end of list command
  171. if ( cmdList->used + bytes + 4 > MAX_RENDER_COMMANDS ) {
  172. if ( bytes > MAX_RENDER_COMMANDS - 4 ) {
  173. ri.Error( ERR_FATAL, "R_GetCommandBuffer: bad size %i", bytes );
  174. }
  175. // if we run out of room, just start dropping commands
  176. return NULL;
  177. }
  178. cmdList->used += bytes;
  179. return cmdList->cmds + cmdList->used - bytes;
  180. }
  181. /*
  182. =============
  183. R_AddDrawSurfCmd
  184. =============
  185. */
  186. void R_AddDrawSurfCmd( drawSurf_t *drawSurfs, int numDrawSurfs ) {
  187. drawSurfsCommand_t *cmd;
  188. cmd = R_GetCommandBuffer( sizeof( *cmd ) );
  189. if ( !cmd ) {
  190. return;
  191. }
  192. cmd->commandId = RC_DRAW_SURFS;
  193. cmd->drawSurfs = drawSurfs;
  194. cmd->numDrawSurfs = numDrawSurfs;
  195. cmd->refdef = tr.refdef;
  196. cmd->viewParms = tr.viewParms;
  197. }
  198. /*
  199. =============
  200. RE_SetColor
  201. Passing NULL will set the color to white
  202. =============
  203. */
  204. void RE_SetColor( const float *rgba ) {
  205. setColorCommand_t *cmd;
  206. if ( !tr.registered ) {
  207. return;
  208. }
  209. cmd = R_GetCommandBuffer( sizeof( *cmd ) );
  210. if ( !cmd ) {
  211. return;
  212. }
  213. cmd->commandId = RC_SET_COLOR;
  214. if ( !rgba ) {
  215. static float colorWhite[4] = { 1, 1, 1, 1 };
  216. rgba = colorWhite;
  217. }
  218. cmd->color[0] = rgba[0];
  219. cmd->color[1] = rgba[1];
  220. cmd->color[2] = rgba[2];
  221. cmd->color[3] = rgba[3];
  222. }
  223. /*
  224. =============
  225. RE_StretchPic
  226. =============
  227. */
  228. void RE_StretchPic ( float x, float y, float w, float h,
  229. float s1, float t1, float s2, float t2, qhandle_t hShader ) {
  230. stretchPicCommand_t *cmd;
  231. if (!tr.registered) {
  232. return;
  233. }
  234. cmd = R_GetCommandBuffer( sizeof( *cmd ) );
  235. if ( !cmd ) {
  236. return;
  237. }
  238. cmd->commandId = RC_STRETCH_PIC;
  239. cmd->shader = R_GetShaderByHandle( hShader );
  240. cmd->x = x;
  241. cmd->y = y;
  242. cmd->w = w;
  243. cmd->h = h;
  244. cmd->s1 = s1;
  245. cmd->t1 = t1;
  246. cmd->s2 = s2;
  247. cmd->t2 = t2;
  248. }
  249. /*
  250. ====================
  251. RE_BeginFrame
  252. If running in stereo, RE_BeginFrame will be called twice
  253. for each RE_EndFrame
  254. ====================
  255. */
  256. void RE_BeginFrame( stereoFrame_t stereoFrame ) {
  257. drawBufferCommand_t *cmd;
  258. if ( !tr.registered ) {
  259. return;
  260. }
  261. glState.finishCalled = qfalse;
  262. tr.frameCount++;
  263. tr.frameSceneNum = 0;
  264. //
  265. // do overdraw measurement
  266. //
  267. if ( r_measureOverdraw->integer )
  268. {
  269. if ( glConfig.stencilBits < 4 )
  270. {
  271. ri.Printf( PRINT_ALL, "Warning: not enough stencil bits to measure overdraw: %d\n", glConfig.stencilBits );
  272. ri.Cvar_Set( "r_measureOverdraw", "0" );
  273. r_measureOverdraw->modified = qfalse;
  274. }
  275. else if ( r_shadows->integer == 2 )
  276. {
  277. ri.Printf( PRINT_ALL, "Warning: stencil shadows and overdraw measurement are mutually exclusive\n" );
  278. ri.Cvar_Set( "r_measureOverdraw", "0" );
  279. r_measureOverdraw->modified = qfalse;
  280. }
  281. else
  282. {
  283. R_SyncRenderThread();
  284. qglEnable( GL_STENCIL_TEST );
  285. qglStencilMask( ~0U );
  286. qglClearStencil( 0U );
  287. qglStencilFunc( GL_ALWAYS, 0U, ~0U );
  288. qglStencilOp( GL_KEEP, GL_INCR, GL_INCR );
  289. }
  290. r_measureOverdraw->modified = qfalse;
  291. }
  292. else
  293. {
  294. // this is only reached if it was on and is now off
  295. if ( r_measureOverdraw->modified ) {
  296. R_SyncRenderThread();
  297. qglDisable( GL_STENCIL_TEST );
  298. }
  299. r_measureOverdraw->modified = qfalse;
  300. }
  301. //
  302. // texturemode stuff
  303. //
  304. if ( r_textureMode->modified ) {
  305. R_SyncRenderThread();
  306. GL_TextureMode( r_textureMode->string );
  307. r_textureMode->modified = qfalse;
  308. }
  309. //
  310. // gamma stuff
  311. //
  312. if ( r_gamma->modified ) {
  313. r_gamma->modified = qfalse;
  314. R_SyncRenderThread();
  315. R_SetColorMappings();
  316. }
  317. // check for errors
  318. if ( !r_ignoreGLErrors->integer ) {
  319. int err;
  320. R_SyncRenderThread();
  321. if ( ( err = qglGetError() ) != GL_NO_ERROR ) {
  322. ri.Error( ERR_FATAL, "RE_BeginFrame() - glGetError() failed (0x%x)!\n", err );
  323. }
  324. }
  325. //
  326. // draw buffer stuff
  327. //
  328. cmd = R_GetCommandBuffer( sizeof( *cmd ) );
  329. if ( !cmd ) {
  330. return;
  331. }
  332. cmd->commandId = RC_DRAW_BUFFER;
  333. if ( glConfig.stereoEnabled ) {
  334. if ( stereoFrame == STEREO_LEFT ) {
  335. cmd->buffer = (int)GL_BACK_LEFT;
  336. } else if ( stereoFrame == STEREO_RIGHT ) {
  337. cmd->buffer = (int)GL_BACK_RIGHT;
  338. } else {
  339. ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is enabled, but stereoFrame was %i", stereoFrame );
  340. }
  341. } else {
  342. if ( stereoFrame != STEREO_CENTER ) {
  343. ri.Error( ERR_FATAL, "RE_BeginFrame: Stereo is disabled, but stereoFrame was %i", stereoFrame );
  344. }
  345. if ( !Q_stricmp( r_drawBuffer->string, "GL_FRONT" ) ) {
  346. cmd->buffer = (int)GL_FRONT;
  347. } else {
  348. cmd->buffer = (int)GL_BACK;
  349. }
  350. }
  351. }
  352. /*
  353. =============
  354. RE_EndFrame
  355. Returns the number of msec spent in the back end
  356. =============
  357. */
  358. void RE_EndFrame( int *frontEndMsec, int *backEndMsec ) {
  359. swapBuffersCommand_t *cmd;
  360. if ( !tr.registered ) {
  361. return;
  362. }
  363. cmd = R_GetCommandBuffer( sizeof( *cmd ) );
  364. if ( !cmd ) {
  365. return;
  366. }
  367. cmd->commandId = RC_SWAP_BUFFERS;
  368. R_IssueRenderCommands( qtrue );
  369. // use the other buffers next frame, because another CPU
  370. // may still be rendering into the current ones
  371. R_ToggleSmpFrame();
  372. if ( frontEndMsec ) {
  373. *frontEndMsec = tr.frontEndMsec;
  374. }
  375. tr.frontEndMsec = 0;
  376. if ( backEndMsec ) {
  377. *backEndMsec = backEnd.pc.msec;
  378. }
  379. backEnd.pc.msec = 0;
  380. }