RenderSystem_init.cpp 89 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. In addition, the Doom 3 BFG Edition 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 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
  17. 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.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../idlib/precompiled.h"
  22. #include "tr_local.h"
  23. // Vista OpenGL wrapper check
  24. #include "../sys/win32/win_local.h"
  25. // DeviceContext bypasses RenderSystem to work directly with this
  26. idGuiModel * tr_guiModel;
  27. // functions that are not called every frame
  28. glconfig_t glConfig;
  29. idCVar r_requestStereoPixelFormat( "r_requestStereoPixelFormat", "1", CVAR_RENDERER, "Ask for a stereo GL pixel format on startup" );
  30. idCVar r_debugContext( "r_debugContext", "0", CVAR_RENDERER, "Enable various levels of context debug." );
  31. idCVar r_glDriver( "r_glDriver", "", CVAR_RENDERER, "\"opengl32\", etc." );
  32. idCVar r_skipIntelWorkarounds( "r_skipIntelWorkarounds", "0", CVAR_RENDERER | CVAR_BOOL, "skip workarounds for Intel driver bugs" );
  33. idCVar r_multiSamples( "r_multiSamples", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "number of antialiasing samples" );
  34. idCVar r_vidMode( "r_vidMode", "0", CVAR_ARCHIVE | CVAR_RENDERER | CVAR_INTEGER, "fullscreen video mode number" );
  35. idCVar r_displayRefresh( "r_displayRefresh", "0", CVAR_RENDERER | CVAR_INTEGER | CVAR_NOCHEAT, "optional display refresh rate option for vid mode", 0.0f, 240.0f );
  36. idCVar r_fullscreen( "r_fullscreen", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "0 = windowed, 1 = full screen on monitor 1, 2 = full screen on monitor 2, etc" );
  37. idCVar r_customWidth( "r_customWidth", "1280", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "custom screen width. set r_vidMode to -1 to activate" );
  38. idCVar r_customHeight( "r_customHeight", "720", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "custom screen height. set r_vidMode to -1 to activate" );
  39. idCVar r_windowX( "r_windowX", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "Non-fullscreen parameter" );
  40. idCVar r_windowY( "r_windowY", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "Non-fullscreen parameter" );
  41. idCVar r_windowWidth( "r_windowWidth", "1280", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "Non-fullscreen parameter" );
  42. idCVar r_windowHeight( "r_windowHeight", "720", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "Non-fullscreen parameter" );
  43. idCVar r_useViewBypass( "r_useViewBypass", "1", CVAR_RENDERER | CVAR_INTEGER, "bypass a frame of latency to the view" );
  44. idCVar r_useLightPortalFlow( "r_useLightPortalFlow", "1", CVAR_RENDERER | CVAR_BOOL, "use a more precise area reference determination" );
  45. idCVar r_singleTriangle( "r_singleTriangle", "0", CVAR_RENDERER | CVAR_BOOL, "only draw a single triangle per primitive" );
  46. idCVar r_checkBounds( "r_checkBounds", "0", CVAR_RENDERER | CVAR_BOOL, "compare all surface bounds with precalculated ones" );
  47. idCVar r_useConstantMaterials( "r_useConstantMaterials", "1", CVAR_RENDERER | CVAR_BOOL, "use pre-calculated material registers if possible" );
  48. idCVar r_useSilRemap( "r_useSilRemap", "1", CVAR_RENDERER | CVAR_BOOL, "consider verts with the same XYZ, but different ST the same for shadows" );
  49. idCVar r_useNodeCommonChildren( "r_useNodeCommonChildren", "1", CVAR_RENDERER | CVAR_BOOL, "stop pushing reference bounds early when possible" );
  50. idCVar r_useShadowSurfaceScissor( "r_useShadowSurfaceScissor", "1", CVAR_RENDERER | CVAR_BOOL, "scissor shadows by the scissor rect of the interaction surfaces" );
  51. idCVar r_useCachedDynamicModels( "r_useCachedDynamicModels", "1", CVAR_RENDERER | CVAR_BOOL, "cache snapshots of dynamic models" );
  52. idCVar r_useSeamlessCubeMap( "r_useSeamlessCubeMap", "1", CVAR_RENDERER | CVAR_BOOL, "use ARB_seamless_cube_map if available" );
  53. idCVar r_useSRGB( "r_useSRGB", "0", CVAR_RENDERER | CVAR_INTEGER | CVAR_ARCHIVE, "1 = both texture and framebuffer, 2 = framebuffer only, 3 = texture only" );
  54. idCVar r_maxAnisotropicFiltering( "r_maxAnisotropicFiltering", "8", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "limit aniso filtering" );
  55. idCVar r_useTrilinearFiltering( "r_useTrilinearFiltering", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "Extra quality filtering" );
  56. idCVar r_lodBias( "r_lodBias", "0.5", CVAR_RENDERER | CVAR_ARCHIVE, "image lod bias" );
  57. idCVar r_useStateCaching( "r_useStateCaching", "1", CVAR_RENDERER | CVAR_BOOL, "avoid redundant state changes in GL_*() calls" );
  58. idCVar r_znear( "r_znear", "3", CVAR_RENDERER | CVAR_FLOAT, "near Z clip plane distance", 0.001f, 200.0f );
  59. idCVar r_ignoreGLErrors( "r_ignoreGLErrors", "1", CVAR_RENDERER | CVAR_BOOL, "ignore GL errors" );
  60. idCVar r_swapInterval( "r_swapInterval", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "0 = tear, 1 = swap-tear where available, 2 = always v-sync" );
  61. idCVar r_gamma( "r_gamma", "1.0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_FLOAT, "changes gamma tables", 0.5f, 3.0f );
  62. idCVar r_brightness( "r_brightness", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_FLOAT, "changes gamma tables", 0.5f, 2.0f );
  63. idCVar r_jitter( "r_jitter", "0", CVAR_RENDERER | CVAR_BOOL, "randomly subpixel jitter the projection matrix" );
  64. idCVar r_skipStaticInteractions( "r_skipStaticInteractions", "0", CVAR_RENDERER | CVAR_BOOL, "skip interactions created at level load" );
  65. idCVar r_skipDynamicInteractions( "r_skipDynamicInteractions", "0", CVAR_RENDERER | CVAR_BOOL, "skip interactions created after level load" );
  66. idCVar r_skipSuppress( "r_skipSuppress", "0", CVAR_RENDERER | CVAR_BOOL, "ignore the per-view suppressions" );
  67. idCVar r_skipPostProcess( "r_skipPostProcess", "0", CVAR_RENDERER | CVAR_BOOL, "skip all post-process renderings" );
  68. idCVar r_skipInteractions( "r_skipInteractions", "0", CVAR_RENDERER | CVAR_BOOL, "skip all light/surface interaction drawing" );
  69. idCVar r_skipDynamicTextures( "r_skipDynamicTextures", "0", CVAR_RENDERER | CVAR_BOOL, "don't dynamically create textures" );
  70. idCVar r_skipCopyTexture( "r_skipCopyTexture", "0", CVAR_RENDERER | CVAR_BOOL, "do all rendering, but don't actually copyTexSubImage2D" );
  71. idCVar r_skipBackEnd( "r_skipBackEnd", "0", CVAR_RENDERER | CVAR_BOOL, "don't draw anything" );
  72. idCVar r_skipRender( "r_skipRender", "0", CVAR_RENDERER | CVAR_BOOL, "skip 3D rendering, but pass 2D" );
  73. idCVar r_skipRenderContext( "r_skipRenderContext", "0", CVAR_RENDERER | CVAR_BOOL, "NULL the rendering context during backend 3D rendering" );
  74. idCVar r_skipTranslucent( "r_skipTranslucent", "0", CVAR_RENDERER | CVAR_BOOL, "skip the translucent interaction rendering" );
  75. idCVar r_skipAmbient( "r_skipAmbient", "0", CVAR_RENDERER | CVAR_BOOL, "bypasses all non-interaction drawing" );
  76. idCVar r_skipNewAmbient( "r_skipNewAmbient", "0", CVAR_RENDERER | CVAR_BOOL | CVAR_ARCHIVE, "bypasses all vertex/fragment program ambient drawing" );
  77. idCVar r_skipBlendLights( "r_skipBlendLights", "0", CVAR_RENDERER | CVAR_BOOL, "skip all blend lights" );
  78. idCVar r_skipFogLights( "r_skipFogLights", "0", CVAR_RENDERER | CVAR_BOOL, "skip all fog lights" );
  79. idCVar r_skipDeforms( "r_skipDeforms", "0", CVAR_RENDERER | CVAR_BOOL, "leave all deform materials in their original state" );
  80. idCVar r_skipFrontEnd( "r_skipFrontEnd", "0", CVAR_RENDERER | CVAR_BOOL, "bypasses all front end work, but 2D gui rendering still draws" );
  81. idCVar r_skipUpdates( "r_skipUpdates", "0", CVAR_RENDERER | CVAR_BOOL, "1 = don't accept any entity or light updates, making everything static" );
  82. idCVar r_skipDecals( "r_skipDecals", "0", CVAR_RENDERER | CVAR_BOOL, "skip decal surfaces" );
  83. idCVar r_skipOverlays( "r_skipOverlays", "0", CVAR_RENDERER | CVAR_BOOL, "skip overlay surfaces" );
  84. idCVar r_skipSpecular( "r_skipSpecular", "0", CVAR_RENDERER | CVAR_BOOL | CVAR_CHEAT | CVAR_ARCHIVE, "use black for specular1" );
  85. idCVar r_skipBump( "r_skipBump", "0", CVAR_RENDERER | CVAR_BOOL | CVAR_ARCHIVE, "uses a flat surface instead of the bump map" );
  86. idCVar r_skipDiffuse( "r_skipDiffuse", "0", CVAR_RENDERER | CVAR_BOOL, "use black for diffuse" );
  87. idCVar r_skipSubviews( "r_skipSubviews", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = don't render any gui elements on surfaces" );
  88. idCVar r_skipGuiShaders( "r_skipGuiShaders", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = skip all gui elements on surfaces, 2 = skip drawing but still handle events, 3 = draw but skip events", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  89. idCVar r_skipParticles( "r_skipParticles", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = skip all particle systems", 0, 1, idCmdSystem::ArgCompletion_Integer<0,1> );
  90. idCVar r_skipShadows( "r_skipShadows", "0", CVAR_RENDERER | CVAR_BOOL | CVAR_ARCHIVE, "disable shadows" );
  91. idCVar r_useLightPortalCulling( "r_useLightPortalCulling", "1", CVAR_RENDERER | CVAR_INTEGER, "0 = none, 1 = cull frustum corners to plane, 2 = exact clip the frustum faces", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  92. idCVar r_useLightAreaCulling( "r_useLightAreaCulling", "1", CVAR_RENDERER | CVAR_BOOL, "0 = off, 1 = on" );
  93. idCVar r_useLightScissors( "r_useLightScissors", "3", CVAR_RENDERER | CVAR_INTEGER, "0 = no scissor, 1 = non-clipped scissor, 2 = near-clipped scissor, 3 = fully-clipped scissor", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  94. idCVar r_useEntityPortalCulling( "r_useEntityPortalCulling", "1", CVAR_RENDERER | CVAR_INTEGER, "0 = none, 1 = cull frustum corners to plane, 2 = exact clip the frustum faces", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  95. idCVar r_logFile( "r_logFile", "0", CVAR_RENDERER | CVAR_INTEGER, "number of frames to emit GL logs" );
  96. idCVar r_clear( "r_clear", "2", CVAR_RENDERER, "force screen clear every frame, 1 = purple, 2 = black, 'r g b' = custom" );
  97. idCVar r_offsetFactor( "r_offsetfactor", "0", CVAR_RENDERER | CVAR_FLOAT, "polygon offset parameter" );
  98. idCVar r_offsetUnits( "r_offsetunits", "-600", CVAR_RENDERER | CVAR_FLOAT, "polygon offset parameter" );
  99. idCVar r_shadowPolygonOffset( "r_shadowPolygonOffset", "-1", CVAR_RENDERER | CVAR_FLOAT, "bias value added to depth test for stencil shadow drawing" );
  100. idCVar r_shadowPolygonFactor( "r_shadowPolygonFactor", "0", CVAR_RENDERER | CVAR_FLOAT, "scale value for stencil shadow drawing" );
  101. idCVar r_subviewOnly( "r_subviewOnly", "0", CVAR_RENDERER | CVAR_BOOL, "1 = don't render main view, allowing subviews to be debugged" );
  102. idCVar r_testGamma( "r_testGamma", "0", CVAR_RENDERER | CVAR_FLOAT, "if > 0 draw a grid pattern to test gamma levels", 0, 195 );
  103. idCVar r_testGammaBias( "r_testGammaBias", "0", CVAR_RENDERER | CVAR_FLOAT, "if > 0 draw a grid pattern to test gamma levels" );
  104. idCVar r_lightScale( "r_lightScale", "3", CVAR_ARCHIVE | CVAR_RENDERER | CVAR_FLOAT, "all light intensities are multiplied by this" );
  105. idCVar r_flareSize( "r_flareSize", "1", CVAR_RENDERER | CVAR_FLOAT, "scale the flare deforms from the material def" );
  106. idCVar r_skipPrelightShadows( "r_skipPrelightShadows", "0", CVAR_RENDERER | CVAR_BOOL, "skip the dmap generated static shadow volumes" );
  107. idCVar r_useScissor( "r_useScissor", "1", CVAR_RENDERER | CVAR_BOOL, "scissor clip as portals and lights are processed" );
  108. idCVar r_useLightDepthBounds( "r_useLightDepthBounds", "1", CVAR_RENDERER | CVAR_BOOL, "use depth bounds test on lights to reduce both shadow and interaction fill" );
  109. idCVar r_useShadowDepthBounds( "r_useShadowDepthBounds", "1", CVAR_RENDERER | CVAR_BOOL, "use depth bounds test on individual shadow volumes to reduce shadow fill" );
  110. idCVar r_screenFraction( "r_screenFraction", "100", CVAR_RENDERER | CVAR_INTEGER, "for testing fill rate, the resolution of the entire screen can be changed" );
  111. idCVar r_usePortals( "r_usePortals", "1", CVAR_RENDERER | CVAR_BOOL, " 1 = use portals to perform area culling, otherwise draw everything" );
  112. idCVar r_singleLight( "r_singleLight", "-1", CVAR_RENDERER | CVAR_INTEGER, "suppress all but one light" );
  113. idCVar r_singleEntity( "r_singleEntity", "-1", CVAR_RENDERER | CVAR_INTEGER, "suppress all but one entity" );
  114. idCVar r_singleSurface( "r_singleSurface", "-1", CVAR_RENDERER | CVAR_INTEGER, "suppress all but one surface on each entity" );
  115. idCVar r_singleArea( "r_singleArea", "0", CVAR_RENDERER | CVAR_BOOL, "only draw the portal area the view is actually in" );
  116. idCVar r_orderIndexes( "r_orderIndexes", "1", CVAR_RENDERER | CVAR_BOOL, "perform index reorganization to optimize vertex use" );
  117. idCVar r_lightAllBackFaces( "r_lightAllBackFaces", "0", CVAR_RENDERER | CVAR_BOOL, "light all the back faces, even when they would be shadowed" );
  118. // visual debugging info
  119. idCVar r_showPortals( "r_showPortals", "0", CVAR_RENDERER | CVAR_BOOL, "draw portal outlines in color based on passed / not passed" );
  120. idCVar r_showUnsmoothedTangents( "r_showUnsmoothedTangents", "0", CVAR_RENDERER | CVAR_BOOL, "if 1, put all nvidia register combiner programming in display lists" );
  121. idCVar r_showSilhouette( "r_showSilhouette", "0", CVAR_RENDERER | CVAR_BOOL, "highlight edges that are casting shadow planes" );
  122. idCVar r_showVertexColor( "r_showVertexColor", "0", CVAR_RENDERER | CVAR_BOOL, "draws all triangles with the solid vertex color" );
  123. idCVar r_showUpdates( "r_showUpdates", "0", CVAR_RENDERER | CVAR_BOOL, "report entity and light updates and ref counts" );
  124. idCVar r_showDemo( "r_showDemo", "0", CVAR_RENDERER | CVAR_BOOL, "report reads and writes to the demo file" );
  125. idCVar r_showDynamic( "r_showDynamic", "0", CVAR_RENDERER | CVAR_BOOL, "report stats on dynamic surface generation" );
  126. idCVar r_showTrace( "r_showTrace", "0", CVAR_RENDERER | CVAR_INTEGER, "show the intersection of an eye trace with the world", idCmdSystem::ArgCompletion_Integer<0,2> );
  127. idCVar r_showIntensity( "r_showIntensity", "0", CVAR_RENDERER | CVAR_BOOL, "draw the screen colors based on intensity, red = 0, green = 128, blue = 255" );
  128. idCVar r_showLights( "r_showLights", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = just print volumes numbers, highlighting ones covering the view, 2 = also draw planes of each volume, 3 = also draw edges of each volume", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  129. idCVar r_showShadows( "r_showShadows", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = visualize the stencil shadow volumes, 2 = draw filled in", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  130. idCVar r_showLightScissors( "r_showLightScissors", "0", CVAR_RENDERER | CVAR_BOOL, "show light scissor rectangles" );
  131. idCVar r_showLightCount( "r_showLightCount", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = colors surfaces based on light count, 2 = also count everything through walls, 3 = also print overdraw", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  132. idCVar r_showViewEntitys( "r_showViewEntitys", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = displays the bounding boxes of all view models, 2 = print index numbers" );
  133. idCVar r_showTris( "r_showTris", "0", CVAR_RENDERER | CVAR_INTEGER, "enables wireframe rendering of the world, 1 = only draw visible ones, 2 = draw all front facing, 3 = draw all, 4 = draw with alpha", 0, 4, idCmdSystem::ArgCompletion_Integer<0,4> );
  134. idCVar r_showSurfaceInfo( "r_showSurfaceInfo", "0", CVAR_RENDERER | CVAR_BOOL, "show surface material name under crosshair" );
  135. idCVar r_showNormals( "r_showNormals", "0", CVAR_RENDERER | CVAR_FLOAT, "draws wireframe normals" );
  136. idCVar r_showMemory( "r_showMemory", "0", CVAR_RENDERER | CVAR_BOOL, "print frame memory utilization" );
  137. idCVar r_showCull( "r_showCull", "0", CVAR_RENDERER | CVAR_BOOL, "report sphere and box culling stats" );
  138. idCVar r_showAddModel( "r_showAddModel", "0", CVAR_RENDERER | CVAR_BOOL, "report stats from tr_addModel" );
  139. idCVar r_showDepth( "r_showDepth", "0", CVAR_RENDERER | CVAR_BOOL, "display the contents of the depth buffer and the depth range" );
  140. idCVar r_showSurfaces( "r_showSurfaces", "0", CVAR_RENDERER | CVAR_BOOL, "report surface/light/shadow counts" );
  141. idCVar r_showPrimitives( "r_showPrimitives", "0", CVAR_RENDERER | CVAR_INTEGER, "report drawsurf/index/vertex counts" );
  142. idCVar r_showEdges( "r_showEdges", "0", CVAR_RENDERER | CVAR_BOOL, "draw the sil edges" );
  143. idCVar r_showTexturePolarity( "r_showTexturePolarity", "0", CVAR_RENDERER | CVAR_BOOL, "shade triangles by texture area polarity" );
  144. idCVar r_showTangentSpace( "r_showTangentSpace", "0", CVAR_RENDERER | CVAR_INTEGER, "shade triangles by tangent space, 1 = use 1st tangent vector, 2 = use 2nd tangent vector, 3 = use normal vector", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  145. idCVar r_showDominantTri( "r_showDominantTri", "0", CVAR_RENDERER | CVAR_BOOL, "draw lines from vertexes to center of dominant triangles" );
  146. idCVar r_showTextureVectors( "r_showTextureVectors", "0", CVAR_RENDERER | CVAR_FLOAT, " if > 0 draw each triangles texture (tangent) vectors" );
  147. idCVar r_showOverDraw( "r_showOverDraw", "0", CVAR_RENDERER | CVAR_INTEGER, "1 = geometry overdraw, 2 = light interaction overdraw, 3 = geometry and light interaction overdraw", 0, 3, idCmdSystem::ArgCompletion_Integer<0,3> );
  148. idCVar r_useEntityCallbacks( "r_useEntityCallbacks", "1", CVAR_RENDERER | CVAR_BOOL, "if 0, issue the callback immediately at update time, rather than defering" );
  149. idCVar r_showSkel( "r_showSkel", "0", CVAR_RENDERER | CVAR_INTEGER, "draw the skeleton when model animates, 1 = draw model with skeleton, 2 = draw skeleton only", 0, 2, idCmdSystem::ArgCompletion_Integer<0,2> );
  150. idCVar r_jointNameScale( "r_jointNameScale", "0.02", CVAR_RENDERER | CVAR_FLOAT, "size of joint names when r_showskel is set to 1" );
  151. idCVar r_jointNameOffset( "r_jointNameOffset", "0.5", CVAR_RENDERER | CVAR_FLOAT, "offset of joint names when r_showskel is set to 1" );
  152. idCVar r_debugLineDepthTest( "r_debugLineDepthTest", "0", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "perform depth test on debug lines" );
  153. idCVar r_debugLineWidth( "r_debugLineWidth", "1", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_BOOL, "width of debug lines" );
  154. idCVar r_debugArrowStep( "r_debugArrowStep", "120", CVAR_RENDERER | CVAR_ARCHIVE | CVAR_INTEGER, "step size of arrow cone line rotation in degrees", 0, 120 );
  155. idCVar r_debugPolygonFilled( "r_debugPolygonFilled", "1", CVAR_RENDERER | CVAR_BOOL, "draw a filled polygon" );
  156. idCVar r_materialOverride( "r_materialOverride", "", CVAR_RENDERER, "overrides all materials", idCmdSystem::ArgCompletion_Decl<DECL_MATERIAL> );
  157. idCVar r_debugRenderToTexture( "r_debugRenderToTexture", "0", CVAR_RENDERER | CVAR_INTEGER, "" );
  158. idCVar stereoRender_enable( "stereoRender_enable", "0", CVAR_INTEGER | CVAR_ARCHIVE, "1 = side-by-side compressed, 2 = top and bottom compressed, 3 = side-by-side, 4 = 720 frame packed, 5 = interlaced, 6 = OpenGL quad buffer" );
  159. idCVar stereoRender_swapEyes( "stereoRender_swapEyes", "0", CVAR_BOOL | CVAR_ARCHIVE, "reverse eye adjustments" );
  160. idCVar stereoRender_deGhost( "stereoRender_deGhost", "0.05", CVAR_FLOAT | CVAR_ARCHIVE, "subtract from opposite eye to reduce ghosting" );
  161. // GL_ARB_multitexture
  162. PFNGLACTIVETEXTUREPROC qglActiveTextureARB;
  163. PFNGLCLIENTACTIVETEXTUREPROC qglClientActiveTextureARB;
  164. // GL_EXT_direct_state_access
  165. PFNGLBINDMULTITEXTUREEXTPROC qglBindMultiTextureEXT;
  166. // GL_ARB_texture_compression
  167. PFNGLCOMPRESSEDTEXIMAGE2DARBPROC qglCompressedTexImage2DARB;
  168. PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC qglCompressedTexSubImage2DARB;
  169. PFNGLGETCOMPRESSEDTEXIMAGEARBPROC qglGetCompressedTexImageARB;
  170. // GL_ARB_vertex_buffer_object
  171. PFNGLBINDBUFFERARBPROC qglBindBufferARB;
  172. PFNGLBINDBUFFERRANGEPROC qglBindBufferRange;
  173. PFNGLDELETEBUFFERSARBPROC qglDeleteBuffersARB;
  174. PFNGLGENBUFFERSARBPROC qglGenBuffersARB;
  175. PFNGLISBUFFERARBPROC qglIsBufferARB;
  176. PFNGLBUFFERDATAARBPROC qglBufferDataARB;
  177. PFNGLBUFFERSUBDATAARBPROC qglBufferSubDataARB;
  178. PFNGLGETBUFFERSUBDATAARBPROC qglGetBufferSubDataARB;
  179. PFNGLMAPBUFFERARBPROC qglMapBufferARB;
  180. PFNGLUNMAPBUFFERARBPROC qglUnmapBufferARB;
  181. PFNGLGETBUFFERPARAMETERIVARBPROC qglGetBufferParameterivARB;
  182. PFNGLGETBUFFERPOINTERVARBPROC qglGetBufferPointervARB;
  183. // GL_ARB_map_buffer_range
  184. PFNGLMAPBUFFERRANGEPROC qglMapBufferRange;
  185. // GL_ARB_draw_elements_base_vertex
  186. PFNGLDRAWELEMENTSBASEVERTEXPROC qglDrawElementsBaseVertex;
  187. // GL_ARB_vertex_array_object
  188. PFNGLGENVERTEXARRAYSPROC qglGenVertexArrays;
  189. PFNGLBINDVERTEXARRAYPROC qglBindVertexArray;
  190. PFNGLDELETEVERTEXARRAYSPROC qglDeleteVertexArrays;
  191. // GL_ARB_vertex_program / GL_ARB_fragment_program
  192. PFNGLVERTEXATTRIBPOINTERARBPROC qglVertexAttribPointerARB;
  193. PFNGLENABLEVERTEXATTRIBARRAYARBPROC qglEnableVertexAttribArrayARB;
  194. PFNGLDISABLEVERTEXATTRIBARRAYARBPROC qglDisableVertexAttribArrayARB;
  195. PFNGLPROGRAMSTRINGARBPROC qglProgramStringARB;
  196. PFNGLBINDPROGRAMARBPROC qglBindProgramARB;
  197. PFNGLGENPROGRAMSARBPROC qglGenProgramsARB;
  198. PFNGLDELETEPROGRAMSARBPROC qglDeleteProgramsARB;
  199. PFNGLPROGRAMENVPARAMETER4FVARBPROC qglProgramEnvParameter4fvARB;
  200. PFNGLPROGRAMLOCALPARAMETER4FVARBPROC qglProgramLocalParameter4fvARB;
  201. // GLSL / OpenGL 2.0
  202. PFNGLCREATESHADERPROC qglCreateShader;
  203. PFNGLDELETESHADERPROC qglDeleteShader;
  204. PFNGLSHADERSOURCEPROC qglShaderSource;
  205. PFNGLCOMPILESHADERPROC qglCompileShader;
  206. PFNGLGETSHADERIVPROC qglGetShaderiv;
  207. PFNGLGETSHADERINFOLOGPROC qglGetShaderInfoLog;
  208. PFNGLCREATEPROGRAMPROC qglCreateProgram;
  209. PFNGLDELETEPROGRAMPROC qglDeleteProgram;
  210. PFNGLATTACHSHADERPROC qglAttachShader;
  211. PFNGLDETACHSHADERPROC qglDetachShader;
  212. PFNGLLINKPROGRAMPROC qglLinkProgram;
  213. PFNGLUSEPROGRAMPROC qglUseProgram;
  214. PFNGLGETPROGRAMIVPROC qglGetProgramiv;
  215. PFNGLGETPROGRAMINFOLOGPROC qglGetProgramInfoLog;
  216. PFNGLPROGRAMPARAMETERIPROC qglProgramParameteri;
  217. PFNGLBINDATTRIBLOCATIONPROC qglBindAttribLocation;
  218. PFNGLGETUNIFORMLOCATIONPROC qglGetUniformLocation;
  219. PFNGLUNIFORM1IPROC qglUniform1i;
  220. PFNGLUNIFORM4FVPROC qglUniform4fv;
  221. // GL_ARB_uniform_buffer_object
  222. PFNGLGETUNIFORMBLOCKINDEXPROC qglGetUniformBlockIndex;
  223. PFNGLUNIFORMBLOCKBINDINGPROC qglUniformBlockBinding;
  224. // GL_ATI_separate_stencil / OpenGL 2.0
  225. PFNGLSTENCILOPSEPARATEATIPROC qglStencilOpSeparate;
  226. PFNGLSTENCILFUNCSEPARATEATIPROC qglStencilFuncSeparate;
  227. // GL_EXT_depth_bounds_test
  228. PFNGLDEPTHBOUNDSEXTPROC qglDepthBoundsEXT;
  229. // GL_ARB_sync
  230. PFNGLFENCESYNCPROC qglFenceSync;
  231. PFNGLISSYNCPROC qglIsSync;
  232. PFNGLCLIENTWAITSYNCPROC qglClientWaitSync;
  233. PFNGLDELETESYNCPROC qglDeleteSync;
  234. // GL_ARB_occlusion_query
  235. PFNGLGENQUERIESARBPROC qglGenQueriesARB;
  236. PFNGLDELETEQUERIESARBPROC qglDeleteQueriesARB;
  237. PFNGLISQUERYARBPROC qglIsQueryARB;
  238. PFNGLBEGINQUERYARBPROC qglBeginQueryARB;
  239. PFNGLENDQUERYARBPROC qglEndQueryARB;
  240. PFNGLGETQUERYIVARBPROC qglGetQueryivARB;
  241. PFNGLGETQUERYOBJECTIVARBPROC qglGetQueryObjectivARB;
  242. PFNGLGETQUERYOBJECTUIVARBPROC qglGetQueryObjectuivARB;
  243. // GL_ARB_timer_query / GL_EXT_timer_query
  244. PFNGLGETQUERYOBJECTUI64VEXTPROC qglGetQueryObjectui64vEXT;
  245. // GL_ARB_debug_output
  246. PFNGLDEBUGMESSAGECONTROLARBPROC qglDebugMessageControlARB;
  247. PFNGLDEBUGMESSAGEINSERTARBPROC qglDebugMessageInsertARB;
  248. PFNGLDEBUGMESSAGECALLBACKARBPROC qglDebugMessageCallbackARB;
  249. PFNGLGETDEBUGMESSAGELOGARBPROC qglGetDebugMessageLogARB;
  250. PFNGLGETSTRINGIPROC qglGetStringi;
  251. /*
  252. ========================
  253. glBindMultiTextureEXT
  254. As of 2011/09/16 the Intel drivers for "Sandy Bridge" and "Ivy Bridge" integrated graphics do not support this extension.
  255. ========================
  256. */
  257. void APIENTRY glBindMultiTextureEXT( GLenum texunit, GLenum target, GLuint texture ) {
  258. qglActiveTextureARB( texunit );
  259. qglBindTexture( target, texture );
  260. }
  261. /*
  262. =================
  263. R_CheckExtension
  264. =================
  265. */
  266. bool R_CheckExtension( char *name ) {
  267. if ( !strstr( glConfig.extensions_string, name ) ) {
  268. common->Printf( "X..%s not found\n", name );
  269. return false;
  270. }
  271. common->Printf( "...using %s\n", name );
  272. return true;
  273. }
  274. /*
  275. ========================
  276. DebugCallback
  277. For ARB_debug_output
  278. ========================
  279. */
  280. static void CALLBACK DebugCallback(unsigned int source, unsigned int type,
  281. unsigned int id, unsigned int severity, int length, const char * message, void * userParam) {
  282. // it probably isn't safe to do an idLib::Printf at this point
  283. OutputDebugString( message );
  284. OutputDebugString( "\n" );
  285. }
  286. /*
  287. ==================
  288. R_CheckPortableExtensions
  289. ==================
  290. */
  291. static void R_CheckPortableExtensions() {
  292. glConfig.glVersion = atof( glConfig.version_string );
  293. const char * badVideoCard = idLocalization::GetString( "#str_06780" );
  294. if ( glConfig.glVersion < 2.0f ) {
  295. idLib::FatalError( badVideoCard );
  296. }
  297. if ( idStr::Icmpn( glConfig.renderer_string, "ATI ", 4 ) == 0 || idStr::Icmpn( glConfig.renderer_string, "AMD ", 4 ) == 0 ) {
  298. glConfig.vendor = VENDOR_AMD;
  299. } else if ( idStr::Icmpn( glConfig.renderer_string, "NVIDIA", 6 ) == 0 ) {
  300. glConfig.vendor = VENDOR_NVIDIA;
  301. } else if ( idStr::Icmpn( glConfig.renderer_string, "Intel", 5 ) == 0 ) {
  302. glConfig.vendor = VENDOR_INTEL;
  303. }
  304. // GL_ARB_multitexture
  305. glConfig.multitextureAvailable = R_CheckExtension( "GL_ARB_multitexture" );
  306. if ( glConfig.multitextureAvailable ) {
  307. qglActiveTextureARB = (void(APIENTRY *)(GLenum))GLimp_ExtensionPointer( "glActiveTextureARB" );
  308. qglClientActiveTextureARB = (void(APIENTRY *)(GLenum))GLimp_ExtensionPointer( "glClientActiveTextureARB" );
  309. }
  310. // GL_EXT_direct_state_access
  311. glConfig.directStateAccess = R_CheckExtension( "GL_EXT_direct_state_access" );
  312. if ( glConfig.directStateAccess ) {
  313. qglBindMultiTextureEXT = (PFNGLBINDMULTITEXTUREEXTPROC)GLimp_ExtensionPointer( "glBindMultiTextureEXT" );
  314. } else {
  315. qglBindMultiTextureEXT = glBindMultiTextureEXT;
  316. }
  317. // GL_ARB_texture_compression + GL_S3_s3tc
  318. // DRI drivers may have GL_ARB_texture_compression but no GL_EXT_texture_compression_s3tc
  319. glConfig.textureCompressionAvailable = R_CheckExtension( "GL_ARB_texture_compression" ) && R_CheckExtension( "GL_EXT_texture_compression_s3tc" );
  320. if ( glConfig.textureCompressionAvailable ) {
  321. qglCompressedTexImage2DARB = (PFNGLCOMPRESSEDTEXIMAGE2DARBPROC)GLimp_ExtensionPointer( "glCompressedTexImage2DARB" );
  322. qglCompressedTexSubImage2DARB = (PFNGLCOMPRESSEDTEXSUBIMAGE2DARBPROC)GLimp_ExtensionPointer( "glCompressedTexSubImage2DARB" );
  323. qglGetCompressedTexImageARB = (PFNGLGETCOMPRESSEDTEXIMAGEARBPROC)GLimp_ExtensionPointer( "glGetCompressedTexImageARB" );
  324. }
  325. // GL_EXT_texture_filter_anisotropic
  326. glConfig.anisotropicFilterAvailable = R_CheckExtension( "GL_EXT_texture_filter_anisotropic" );
  327. if ( glConfig.anisotropicFilterAvailable ) {
  328. qglGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glConfig.maxTextureAnisotropy );
  329. common->Printf( " maxTextureAnisotropy: %f\n", glConfig.maxTextureAnisotropy );
  330. } else {
  331. glConfig.maxTextureAnisotropy = 1;
  332. }
  333. // GL_EXT_texture_lod_bias
  334. // The actual extension is broken as specificed, storing the state in the texture unit instead
  335. // of the texture object. The behavior in GL 1.4 is the behavior we use.
  336. glConfig.textureLODBiasAvailable = ( glConfig.glVersion >= 1.4 || R_CheckExtension( "GL_EXT_texture_lod_bias" ) );
  337. if ( glConfig.textureLODBiasAvailable ) {
  338. common->Printf( "...using %s\n", "GL_EXT_texture_lod_bias" );
  339. } else {
  340. common->Printf( "X..%s not found\n", "GL_EXT_texture_lod_bias" );
  341. }
  342. // GL_ARB_seamless_cube_map
  343. glConfig.seamlessCubeMapAvailable = R_CheckExtension( "GL_ARB_seamless_cube_map" );
  344. r_useSeamlessCubeMap.SetModified(); // the CheckCvars() next frame will enable / disable it
  345. // GL_ARB_framebuffer_sRGB
  346. glConfig.sRGBFramebufferAvailable = R_CheckExtension( "GL_ARB_framebuffer_sRGB" );
  347. r_useSRGB.SetModified(); // the CheckCvars() next frame will enable / disable it
  348. // GL_ARB_vertex_buffer_object
  349. glConfig.vertexBufferObjectAvailable = R_CheckExtension( "GL_ARB_vertex_buffer_object" );
  350. if ( glConfig.vertexBufferObjectAvailable ) {
  351. qglBindBufferARB = (PFNGLBINDBUFFERARBPROC)GLimp_ExtensionPointer( "glBindBufferARB" );
  352. qglBindBufferRange = (PFNGLBINDBUFFERRANGEPROC)GLimp_ExtensionPointer( "glBindBufferRange" );
  353. qglDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)GLimp_ExtensionPointer( "glDeleteBuffersARB" );
  354. qglGenBuffersARB = (PFNGLGENBUFFERSARBPROC)GLimp_ExtensionPointer( "glGenBuffersARB" );
  355. qglIsBufferARB = (PFNGLISBUFFERARBPROC)GLimp_ExtensionPointer( "glIsBufferARB" );
  356. qglBufferDataARB = (PFNGLBUFFERDATAARBPROC)GLimp_ExtensionPointer( "glBufferDataARB" );
  357. qglBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)GLimp_ExtensionPointer( "glBufferSubDataARB" );
  358. qglGetBufferSubDataARB = (PFNGLGETBUFFERSUBDATAARBPROC)GLimp_ExtensionPointer( "glGetBufferSubDataARB" );
  359. qglMapBufferARB = (PFNGLMAPBUFFERARBPROC)GLimp_ExtensionPointer( "glMapBufferARB" );
  360. qglUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)GLimp_ExtensionPointer( "glUnmapBufferARB" );
  361. qglGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)GLimp_ExtensionPointer( "glGetBufferParameterivARB" );
  362. qglGetBufferPointervARB = (PFNGLGETBUFFERPOINTERVARBPROC)GLimp_ExtensionPointer( "glGetBufferPointervARB" );
  363. }
  364. // GL_ARB_map_buffer_range, map a section of a buffer object's data store
  365. glConfig.mapBufferRangeAvailable = R_CheckExtension( "GL_ARB_map_buffer_range" );
  366. if ( glConfig.mapBufferRangeAvailable ) {
  367. qglMapBufferRange = (PFNGLMAPBUFFERRANGEPROC)GLimp_ExtensionPointer( "glMapBufferRange" );
  368. }
  369. // GL_ARB_vertex_array_object
  370. glConfig.vertexArrayObjectAvailable = R_CheckExtension( "GL_ARB_vertex_array_object" );
  371. if ( glConfig.vertexArrayObjectAvailable ) {
  372. qglGenVertexArrays = (PFNGLGENVERTEXARRAYSPROC)GLimp_ExtensionPointer( "glGenVertexArrays" );
  373. qglBindVertexArray = (PFNGLBINDVERTEXARRAYPROC)GLimp_ExtensionPointer( "glBindVertexArray" );
  374. qglDeleteVertexArrays = (PFNGLDELETEVERTEXARRAYSPROC)GLimp_ExtensionPointer( "glDeleteVertexArrays" );
  375. }
  376. // GL_ARB_draw_elements_base_vertex
  377. glConfig.drawElementsBaseVertexAvailable = R_CheckExtension( "GL_ARB_draw_elements_base_vertex" );
  378. if ( glConfig.drawElementsBaseVertexAvailable ) {
  379. qglDrawElementsBaseVertex = (PFNGLDRAWELEMENTSBASEVERTEXPROC)GLimp_ExtensionPointer( "glDrawElementsBaseVertex" );
  380. }
  381. // GL_ARB_vertex_program / GL_ARB_fragment_program
  382. glConfig.fragmentProgramAvailable = R_CheckExtension( "GL_ARB_fragment_program" );
  383. if ( glConfig.fragmentProgramAvailable ) {
  384. qglVertexAttribPointerARB = (PFNGLVERTEXATTRIBPOINTERARBPROC)GLimp_ExtensionPointer( "glVertexAttribPointerARB" );
  385. qglEnableVertexAttribArrayARB = (PFNGLENABLEVERTEXATTRIBARRAYARBPROC)GLimp_ExtensionPointer( "glEnableVertexAttribArrayARB" );
  386. qglDisableVertexAttribArrayARB = (PFNGLDISABLEVERTEXATTRIBARRAYARBPROC)GLimp_ExtensionPointer( "glDisableVertexAttribArrayARB" );
  387. qglProgramStringARB = (PFNGLPROGRAMSTRINGARBPROC)GLimp_ExtensionPointer( "glProgramStringARB" );
  388. qglBindProgramARB = (PFNGLBINDPROGRAMARBPROC)GLimp_ExtensionPointer( "glBindProgramARB" );
  389. qglGenProgramsARB = (PFNGLGENPROGRAMSARBPROC)GLimp_ExtensionPointer( "glGenProgramsARB" );
  390. qglDeleteProgramsARB = (PFNGLDELETEPROGRAMSARBPROC)GLimp_ExtensionPointer( "glDeleteProgramsARB" );
  391. qglProgramEnvParameter4fvARB = (PFNGLPROGRAMENVPARAMETER4FVARBPROC)GLimp_ExtensionPointer( "glProgramEnvParameter4fvARB" );
  392. qglProgramLocalParameter4fvARB = (PFNGLPROGRAMLOCALPARAMETER4FVARBPROC)GLimp_ExtensionPointer( "glProgramLocalParameter4fvARB" );
  393. qglGetIntegerv( GL_MAX_TEXTURE_COORDS_ARB, (GLint *)&glConfig.maxTextureCoords );
  394. qglGetIntegerv( GL_MAX_TEXTURE_IMAGE_UNITS_ARB, (GLint *)&glConfig.maxTextureImageUnits );
  395. }
  396. // GLSL, core in OpenGL > 2.0
  397. glConfig.glslAvailable = ( glConfig.glVersion >= 2.0f );
  398. if ( glConfig.glslAvailable ) {
  399. qglCreateShader = (PFNGLCREATESHADERPROC)GLimp_ExtensionPointer( "glCreateShader" );
  400. qglDeleteShader = (PFNGLDELETESHADERPROC)GLimp_ExtensionPointer( "glDeleteShader" );
  401. qglShaderSource = (PFNGLSHADERSOURCEPROC)GLimp_ExtensionPointer( "glShaderSource" );
  402. qglCompileShader = (PFNGLCOMPILESHADERPROC)GLimp_ExtensionPointer( "glCompileShader" );
  403. qglGetShaderiv = (PFNGLGETSHADERIVPROC)GLimp_ExtensionPointer( "glGetShaderiv" );
  404. qglGetShaderInfoLog = (PFNGLGETSHADERINFOLOGPROC)GLimp_ExtensionPointer( "glGetShaderInfoLog" );
  405. qglCreateProgram = (PFNGLCREATEPROGRAMPROC)GLimp_ExtensionPointer( "glCreateProgram" );
  406. qglDeleteProgram = (PFNGLDELETEPROGRAMPROC)GLimp_ExtensionPointer( "glDeleteProgram" );
  407. qglAttachShader = (PFNGLATTACHSHADERPROC)GLimp_ExtensionPointer( "glAttachShader" );
  408. qglDetachShader = (PFNGLDETACHSHADERPROC)GLimp_ExtensionPointer( "glDetachShader" );
  409. qglLinkProgram = (PFNGLLINKPROGRAMPROC)GLimp_ExtensionPointer( "glLinkProgram" );
  410. qglUseProgram = (PFNGLUSEPROGRAMPROC)GLimp_ExtensionPointer( "glUseProgram" );
  411. qglGetProgramiv = (PFNGLGETPROGRAMIVPROC)GLimp_ExtensionPointer( "glGetProgramiv" );
  412. qglGetProgramInfoLog = (PFNGLGETPROGRAMINFOLOGPROC)GLimp_ExtensionPointer( "glGetProgramInfoLog" );
  413. qglBindAttribLocation = (PFNGLBINDATTRIBLOCATIONPROC)GLimp_ExtensionPointer( "glBindAttribLocation" );
  414. qglGetUniformLocation = (PFNGLGETUNIFORMLOCATIONPROC)GLimp_ExtensionPointer( "glGetUniformLocation" );
  415. qglUniform1i = (PFNGLUNIFORM1IPROC)GLimp_ExtensionPointer( "glUniform1i" );
  416. qglUniform4fv = (PFNGLUNIFORM4FVPROC)GLimp_ExtensionPointer( "glUniform4fv" );
  417. }
  418. // GL_ARB_uniform_buffer_object
  419. glConfig.uniformBufferAvailable = R_CheckExtension( "GL_ARB_uniform_buffer_object" );
  420. if ( glConfig.uniformBufferAvailable ) {
  421. qglGetUniformBlockIndex = (PFNGLGETUNIFORMBLOCKINDEXPROC)GLimp_ExtensionPointer( "glGetUniformBlockIndex" );
  422. qglUniformBlockBinding = (PFNGLUNIFORMBLOCKBINDINGPROC)GLimp_ExtensionPointer( "glUniformBlockBinding" );
  423. qglGetIntegerv( GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, (GLint *)&glConfig.uniformBufferOffsetAlignment );
  424. if ( glConfig.uniformBufferOffsetAlignment < 256 ) {
  425. glConfig.uniformBufferOffsetAlignment = 256;
  426. }
  427. }
  428. // ATI_separate_stencil / OpenGL 2.0 separate stencil
  429. glConfig.twoSidedStencilAvailable = ( glConfig.glVersion >= 2.0f ) || R_CheckExtension( "GL_ATI_separate_stencil" );
  430. if ( glConfig.twoSidedStencilAvailable ) {
  431. qglStencilOpSeparate = (PFNGLSTENCILOPSEPARATEATIPROC)GLimp_ExtensionPointer( "glStencilOpSeparate" );
  432. qglStencilFuncSeparate = (PFNGLSTENCILFUNCSEPARATEATIPROC)GLimp_ExtensionPointer( "glStencilFuncSeparate" );
  433. }
  434. // GL_EXT_depth_bounds_test
  435. glConfig.depthBoundsTestAvailable = R_CheckExtension( "GL_EXT_depth_bounds_test" );
  436. if ( glConfig.depthBoundsTestAvailable ) {
  437. qglDepthBoundsEXT = (PFNGLDEPTHBOUNDSEXTPROC)GLimp_ExtensionPointer( "glDepthBoundsEXT" );
  438. }
  439. // GL_ARB_sync
  440. glConfig.syncAvailable = R_CheckExtension( "GL_ARB_sync" ) &&
  441. // as of 5/24/2012 (driver version 15.26.12.64.2761) sync objects
  442. // do not appear to work for the Intel HD 4000 graphics
  443. ( glConfig.vendor != VENDOR_INTEL || r_skipIntelWorkarounds.GetBool() );
  444. if ( glConfig.syncAvailable ) {
  445. qglFenceSync = (PFNGLFENCESYNCPROC)GLimp_ExtensionPointer( "glFenceSync" );
  446. qglIsSync = (PFNGLISSYNCPROC)GLimp_ExtensionPointer( "glIsSync" );
  447. qglClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)GLimp_ExtensionPointer( "glClientWaitSync" );
  448. qglDeleteSync = (PFNGLDELETESYNCPROC)GLimp_ExtensionPointer( "glDeleteSync" );
  449. }
  450. // GL_ARB_occlusion_query
  451. glConfig.occlusionQueryAvailable = R_CheckExtension( "GL_ARB_occlusion_query" );
  452. if ( glConfig.occlusionQueryAvailable ) {
  453. // defined in GL_ARB_occlusion_query, which is required for GL_EXT_timer_query
  454. qglGenQueriesARB = (PFNGLGENQUERIESARBPROC)GLimp_ExtensionPointer( "glGenQueriesARB" );
  455. qglDeleteQueriesARB = (PFNGLDELETEQUERIESARBPROC)GLimp_ExtensionPointer( "glDeleteQueriesARB" );
  456. qglIsQueryARB = (PFNGLISQUERYARBPROC)GLimp_ExtensionPointer( "glIsQueryARB" );
  457. qglBeginQueryARB = (PFNGLBEGINQUERYARBPROC)GLimp_ExtensionPointer( "glBeginQueryARB" );
  458. qglEndQueryARB = (PFNGLENDQUERYARBPROC)GLimp_ExtensionPointer( "glEndQueryARB" );
  459. qglGetQueryivARB = (PFNGLGETQUERYIVARBPROC)GLimp_ExtensionPointer( "glGetQueryivARB" );
  460. qglGetQueryObjectivARB = (PFNGLGETQUERYOBJECTIVARBPROC)GLimp_ExtensionPointer( "glGetQueryObjectivARB" );
  461. qglGetQueryObjectuivARB = (PFNGLGETQUERYOBJECTUIVARBPROC)GLimp_ExtensionPointer( "glGetQueryObjectuivARB" );
  462. }
  463. // GL_ARB_timer_query
  464. glConfig.timerQueryAvailable = R_CheckExtension( "GL_ARB_timer_query" ) || R_CheckExtension( "GL_EXT_timer_query" );
  465. if ( glConfig.timerQueryAvailable ) {
  466. qglGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC)GLimp_ExtensionPointer( "glGetQueryObjectui64vARB" );
  467. if ( qglGetQueryObjectui64vEXT == NULL ) {
  468. qglGetQueryObjectui64vEXT = (PFNGLGETQUERYOBJECTUI64VEXTPROC)GLimp_ExtensionPointer( "glGetQueryObjectui64vEXT" );
  469. }
  470. }
  471. // GL_ARB_debug_output
  472. glConfig.debugOutputAvailable = R_CheckExtension( "GL_ARB_debug_output" );
  473. if ( glConfig.debugOutputAvailable ) {
  474. qglDebugMessageControlARB = (PFNGLDEBUGMESSAGECONTROLARBPROC)GLimp_ExtensionPointer( "glDebugMessageControlARB" );
  475. qglDebugMessageInsertARB = (PFNGLDEBUGMESSAGEINSERTARBPROC)GLimp_ExtensionPointer( "glDebugMessageInsertARB" );
  476. qglDebugMessageCallbackARB = (PFNGLDEBUGMESSAGECALLBACKARBPROC)GLimp_ExtensionPointer( "glDebugMessageCallbackARB" );
  477. qglGetDebugMessageLogARB = (PFNGLGETDEBUGMESSAGELOGARBPROC)GLimp_ExtensionPointer( "glGetDebugMessageLogARB" );
  478. if ( r_debugContext.GetInteger() >= 1 ) {
  479. qglDebugMessageCallbackARB( DebugCallback, NULL );
  480. }
  481. if ( r_debugContext.GetInteger() >= 2 ) {
  482. // force everything to happen in the main thread instead of in a separate driver thread
  483. glEnable( GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB );
  484. }
  485. if ( r_debugContext.GetInteger() >= 3 ) {
  486. // enable all the low priority messages
  487. qglDebugMessageControlARB( GL_DONT_CARE,
  488. GL_DONT_CARE,
  489. GL_DEBUG_SEVERITY_LOW_ARB,
  490. 0, NULL, true );
  491. }
  492. }
  493. // GL_ARB_multitexture
  494. if ( !glConfig.multitextureAvailable ) {
  495. idLib::Error( "GL_ARB_multitexture not available" );
  496. }
  497. // GL_ARB_texture_compression + GL_EXT_texture_compression_s3tc
  498. if ( !glConfig.textureCompressionAvailable ) {
  499. idLib::Error( "GL_ARB_texture_compression or GL_EXT_texture_compression_s3tc not available" );
  500. }
  501. // GL_ARB_vertex_buffer_object
  502. if ( !glConfig.vertexBufferObjectAvailable ) {
  503. idLib::Error( "GL_ARB_vertex_buffer_object not available" );
  504. }
  505. // GL_ARB_map_buffer_range
  506. if ( !glConfig.mapBufferRangeAvailable ) {
  507. idLib::Error( "GL_ARB_map_buffer_range not available" );
  508. }
  509. // GL_ARB_vertex_array_object
  510. if ( !glConfig.vertexArrayObjectAvailable ) {
  511. idLib::Error( "GL_ARB_vertex_array_object not available" );
  512. }
  513. // GL_ARB_draw_elements_base_vertex
  514. if ( !glConfig.drawElementsBaseVertexAvailable ) {
  515. idLib::Error( "GL_ARB_draw_elements_base_vertex not available" );
  516. }
  517. // GL_ARB_vertex_program / GL_ARB_fragment_program
  518. if ( !glConfig.fragmentProgramAvailable ) {
  519. idLib::Error( "GL_ARB_fragment_program not available" );
  520. }
  521. // GLSL
  522. if ( !glConfig.glslAvailable ) {
  523. idLib::Error( "GLSL not available" );
  524. }
  525. // GL_ARB_uniform_buffer_object
  526. if ( !glConfig.uniformBufferAvailable ) {
  527. idLib::Error( "GL_ARB_uniform_buffer_object not available" );
  528. }
  529. // GL_EXT_stencil_two_side
  530. if ( !glConfig.twoSidedStencilAvailable ) {
  531. idLib::Error( "GL_ATI_separate_stencil not available" );
  532. }
  533. // generate one global Vertex Array Object (VAO)
  534. qglGenVertexArrays( 1, &glConfig.global_vao );
  535. qglBindVertexArray( glConfig.global_vao );
  536. }
  537. static bool r_initialized = false;
  538. /*
  539. =============================
  540. R_IsInitialized
  541. =============================
  542. */
  543. bool R_IsInitialized() {
  544. return r_initialized;
  545. }
  546. /*
  547. =============================
  548. R_SetNewMode
  549. r_fullScreen -1 borderless window at exact desktop coordinates
  550. r_fullScreen 0 bordered window at exact desktop coordinates
  551. r_fullScreen 1 fullscreen on monitor 1 at r_vidMode
  552. r_fullScreen 2 fullscreen on monitor 2 at r_vidMode
  553. ...
  554. r_vidMode -1 use r_customWidth / r_customHeight, even if they don't appear on the mode list
  555. r_vidMode 0 use first mode returned by EnumDisplaySettings()
  556. r_vidMode 1 use second mode returned by EnumDisplaySettings()
  557. ...
  558. r_displayRefresh 0 don't specify refresh
  559. r_displayRefresh 70 specify 70 hz, etc
  560. =============================
  561. */
  562. void R_SetNewMode( const bool fullInit ) {
  563. // try up to three different configurations
  564. for ( int i = 0 ; i < 3 ; i++ ) {
  565. if ( i == 0 && stereoRender_enable.GetInteger() != STEREO3D_QUAD_BUFFER ) {
  566. continue; // don't even try for a stereo mode
  567. }
  568. glimpParms_t parms;
  569. if ( r_fullscreen.GetInteger() <= 0 ) {
  570. // use explicit position / size for window
  571. parms.x = r_windowX.GetInteger();
  572. parms.y = r_windowY.GetInteger();
  573. parms.width = r_windowWidth.GetInteger();
  574. parms.height = r_windowHeight.GetInteger();
  575. // may still be -1 to force a borderless window
  576. parms.fullScreen = r_fullscreen.GetInteger();
  577. parms.displayHz = 0; // ignored
  578. } else {
  579. // get the mode list for this monitor
  580. idList<vidMode_t> modeList;
  581. if ( !R_GetModeListForDisplay( r_fullscreen.GetInteger()-1, modeList ) ) {
  582. idLib::Printf( "r_fullscreen reset from %i to 1 because mode list failed.", r_fullscreen.GetInteger() );
  583. r_fullscreen.SetInteger( 1 );
  584. R_GetModeListForDisplay( r_fullscreen.GetInteger()-1, modeList );
  585. }
  586. if ( modeList.Num() < 1 ) {
  587. idLib::Printf( "Going to safe mode because mode list failed." );
  588. goto safeMode;
  589. }
  590. parms.x = 0; // ignored
  591. parms.y = 0; // ignored
  592. parms.fullScreen = r_fullscreen.GetInteger();
  593. // set the parameters we are trying
  594. if ( r_vidMode.GetInteger() < 0 ) {
  595. // try forcing a specific mode, even if it isn't on the list
  596. parms.width = r_customWidth.GetInteger();
  597. parms.height = r_customHeight.GetInteger();
  598. parms.displayHz = r_displayRefresh.GetInteger();
  599. } else {
  600. if ( r_vidMode.GetInteger() > modeList.Num() ) {
  601. idLib::Printf( "r_vidMode reset from %i to 0.\n", r_vidMode.GetInteger() );
  602. r_vidMode.SetInteger( 0 );
  603. }
  604. parms.width = modeList[ r_vidMode.GetInteger() ].width;
  605. parms.height = modeList[ r_vidMode.GetInteger() ].height;
  606. parms.displayHz = modeList[ r_vidMode.GetInteger() ].displayHz;
  607. }
  608. }
  609. parms.multiSamples = r_multiSamples.GetInteger();
  610. if ( i == 0 ) {
  611. parms.stereo = ( stereoRender_enable.GetInteger() == STEREO3D_QUAD_BUFFER );
  612. } else {
  613. parms.stereo = false;
  614. }
  615. if ( fullInit ) {
  616. // create the context as well as setting up the window
  617. if ( GLimp_Init( parms ) ) {
  618. // it worked
  619. break;
  620. }
  621. } else {
  622. // just rebuild the window
  623. if ( GLimp_SetScreenParms( parms ) ) {
  624. // it worked
  625. break;
  626. }
  627. }
  628. if ( i == 2 ) {
  629. common->FatalError( "Unable to initialize OpenGL" );
  630. }
  631. if ( i == 0 ) {
  632. // same settings, no stereo
  633. continue;
  634. }
  635. safeMode:
  636. // if we failed, set everything back to "safe mode"
  637. // and try again
  638. r_vidMode.SetInteger( 0 );
  639. r_fullscreen.SetInteger( 1 );
  640. r_displayRefresh.SetInteger( 0 );
  641. r_multiSamples.SetInteger( 0 );
  642. }
  643. }
  644. idStr extensions_string;
  645. /*
  646. ==================
  647. R_InitOpenGL
  648. This function is responsible for initializing a valid OpenGL subsystem
  649. for rendering. This is done by calling the system specific GLimp_Init,
  650. which gives us a working OGL subsystem, then setting all necessary openGL
  651. state, including images, vertex programs, and display lists.
  652. Changes to the vertex cache size or smp state require a vid_restart.
  653. If R_IsInitialized() is false, no rendering can take place, but
  654. all renderSystem functions will still operate properly, notably the material
  655. and model information functions.
  656. ==================
  657. */
  658. void R_InitOpenGL() {
  659. common->Printf( "----- R_InitOpenGL -----\n" );
  660. if ( R_IsInitialized() ) {
  661. common->FatalError( "R_InitOpenGL called while active" );
  662. }
  663. R_SetNewMode( true );
  664. // input and sound systems need to be tied to the new window
  665. Sys_InitInput();
  666. // get our config strings
  667. glConfig.vendor_string = (const char *)qglGetString( GL_VENDOR );
  668. glConfig.renderer_string = (const char *)qglGetString( GL_RENDERER );
  669. glConfig.version_string = (const char *)qglGetString( GL_VERSION );
  670. glConfig.shading_language_string = (const char *)qglGetString( GL_SHADING_LANGUAGE_VERSION );
  671. glConfig.extensions_string = (const char *)qglGetString( GL_EXTENSIONS );
  672. if ( glConfig.extensions_string == NULL ) {
  673. // As of OpenGL 3.2, glGetStringi is required to obtain the available extensions
  674. qglGetStringi = (PFNGLGETSTRINGIPROC)GLimp_ExtensionPointer( "glGetStringi" );
  675. // Build the extensions string
  676. GLint numExtensions;
  677. qglGetIntegerv( GL_NUM_EXTENSIONS, &numExtensions );
  678. extensions_string.Clear();
  679. for ( int i = 0; i < numExtensions; i++ ) {
  680. extensions_string.Append( (const char*)qglGetStringi( GL_EXTENSIONS, i ) );
  681. // the now deprecated glGetString method usaed to create a single string with each extension separated by a space
  682. if ( i < numExtensions - 1 ) {
  683. extensions_string.Append( ' ' );
  684. }
  685. }
  686. glConfig.extensions_string = extensions_string.c_str();
  687. }
  688. float glVersion = atof( glConfig.version_string );
  689. float glslVersion = atof( glConfig.shading_language_string );
  690. idLib::Printf( "OpenGL Version: %3.1f\n", glVersion );
  691. idLib::Printf( "OpenGL Vendor : %s\n", glConfig.vendor_string );
  692. idLib::Printf( "OpenGL GLSL : %3.1f\n", glslVersion );
  693. // OpenGL driver constants
  694. GLint temp;
  695. qglGetIntegerv( GL_MAX_TEXTURE_SIZE, &temp );
  696. glConfig.maxTextureSize = temp;
  697. // stubbed or broken drivers may have reported 0...
  698. if ( glConfig.maxTextureSize <= 0 ) {
  699. glConfig.maxTextureSize = 256;
  700. }
  701. r_initialized = true;
  702. // recheck all the extensions (FIXME: this might be dangerous)
  703. R_CheckPortableExtensions();
  704. renderProgManager.Init();
  705. r_initialized = true;
  706. // allocate the vertex array range or vertex objects
  707. vertexCache.Init();
  708. // allocate the frame data, which may be more if smp is enabled
  709. R_InitFrameData();
  710. // Reset our gamma
  711. R_SetColorMappings();
  712. static bool glCheck = false;
  713. if ( !glCheck && win32.osversion.dwMajorVersion == 6 ) {
  714. glCheck = true;
  715. if ( !idStr::Icmp( glConfig.vendor_string, "Microsoft" ) && idStr::FindText( glConfig.renderer_string, "OpenGL-D3D" ) != -1 ) {
  716. if ( cvarSystem->GetCVarBool( "r_fullscreen" ) ) {
  717. cmdSystem->BufferCommandText( CMD_EXEC_NOW, "vid_restart partial windowed\n" );
  718. Sys_GrabMouseCursor( false );
  719. }
  720. int ret = MessageBox( NULL, "Please install OpenGL drivers from your graphics hardware vendor to run " GAME_NAME ".\nYour OpenGL functionality is limited.",
  721. "Insufficient OpenGL capabilities", MB_OKCANCEL | MB_ICONWARNING | MB_TASKMODAL );
  722. if ( ret == IDCANCEL ) {
  723. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "quit\n" );
  724. cmdSystem->ExecuteCommandBuffer();
  725. }
  726. if ( cvarSystem->GetCVarBool( "r_fullscreen" ) ) {
  727. cmdSystem->BufferCommandText( CMD_EXEC_APPEND, "vid_restart\n" );
  728. }
  729. }
  730. }
  731. }
  732. /*
  733. ==================
  734. GL_CheckErrors
  735. ==================
  736. */
  737. void GL_CheckErrors() {
  738. int err;
  739. char s[64];
  740. int i;
  741. // check for up to 10 errors pending
  742. for ( i = 0 ; i < 10 ; i++ ) {
  743. err = qglGetError();
  744. if ( err == GL_NO_ERROR ) {
  745. return;
  746. }
  747. switch( err ) {
  748. case GL_INVALID_ENUM:
  749. strcpy( s, "GL_INVALID_ENUM" );
  750. break;
  751. case GL_INVALID_VALUE:
  752. strcpy( s, "GL_INVALID_VALUE" );
  753. break;
  754. case GL_INVALID_OPERATION:
  755. strcpy( s, "GL_INVALID_OPERATION" );
  756. break;
  757. case GL_STACK_OVERFLOW:
  758. strcpy( s, "GL_STACK_OVERFLOW" );
  759. break;
  760. case GL_STACK_UNDERFLOW:
  761. strcpy( s, "GL_STACK_UNDERFLOW" );
  762. break;
  763. case GL_OUT_OF_MEMORY:
  764. strcpy( s, "GL_OUT_OF_MEMORY" );
  765. break;
  766. default:
  767. idStr::snPrintf( s, sizeof(s), "%i", err);
  768. break;
  769. }
  770. if ( !r_ignoreGLErrors.GetBool() ) {
  771. common->Printf( "GL_CheckErrors: %s\n", s );
  772. }
  773. }
  774. }
  775. /*
  776. =====================
  777. R_ReloadSurface_f
  778. Reload the material displayed by r_showSurfaceInfo
  779. =====================
  780. */
  781. static void R_ReloadSurface_f( const idCmdArgs &args ) {
  782. modelTrace_t mt;
  783. idVec3 start, end;
  784. // start far enough away that we don't hit the player model
  785. start = tr.primaryView->renderView.vieworg + tr.primaryView->renderView.viewaxis[0] * 16;
  786. end = start + tr.primaryView->renderView.viewaxis[0] * 1000.0f;
  787. if ( !tr.primaryWorld->Trace( mt, start, end, 0.0f, false ) ) {
  788. return;
  789. }
  790. common->Printf( "Reloading %s\n", mt.material->GetName() );
  791. // reload the decl
  792. mt.material->base->Reload();
  793. // reload any images used by the decl
  794. mt.material->ReloadImages( false );
  795. }
  796. /*
  797. ==============
  798. R_ListModes_f
  799. ==============
  800. */
  801. static void R_ListModes_f( const idCmdArgs &args ) {
  802. for ( int displayNum = 0 ; ; displayNum++ ) {
  803. idList<vidMode_t> modeList;
  804. if ( !R_GetModeListForDisplay( displayNum, modeList ) ) {
  805. break;
  806. }
  807. for ( int i = 0; i < modeList.Num() ; i++ ) {
  808. common->Printf( "Monitor %i, mode %3i: %4i x %4i @ %ihz\n", displayNum+1, i, modeList[i].width, modeList[i].height, modeList[i].displayHz );
  809. }
  810. }
  811. }
  812. /*
  813. =============
  814. R_TestImage_f
  815. Display the given image centered on the screen.
  816. testimage <number>
  817. testimage <filename>
  818. =============
  819. */
  820. void R_TestImage_f( const idCmdArgs &args ) {
  821. int imageNum;
  822. if ( tr.testVideo ) {
  823. delete tr.testVideo;
  824. tr.testVideo = NULL;
  825. }
  826. tr.testImage = NULL;
  827. if ( args.Argc() != 2 ) {
  828. return;
  829. }
  830. if ( idStr::IsNumeric( args.Argv(1) ) ) {
  831. imageNum = atoi( args.Argv(1) );
  832. if ( imageNum >= 0 && imageNum < globalImages->images.Num() ) {
  833. tr.testImage = globalImages->images[imageNum];
  834. }
  835. } else {
  836. tr.testImage = globalImages->ImageFromFile( args.Argv( 1 ), TF_DEFAULT, TR_REPEAT, TD_DEFAULT );
  837. }
  838. }
  839. /*
  840. =============
  841. R_TestVideo_f
  842. Plays the cinematic file in a testImage
  843. =============
  844. */
  845. void R_TestVideo_f( const idCmdArgs &args ) {
  846. if ( tr.testVideo ) {
  847. delete tr.testVideo;
  848. tr.testVideo = NULL;
  849. }
  850. tr.testImage = NULL;
  851. if ( args.Argc() < 2 ) {
  852. return;
  853. }
  854. tr.testImage = globalImages->ImageFromFile( "_scratch", TF_DEFAULT, TR_REPEAT, TD_DEFAULT );
  855. tr.testVideo = idCinematic::Alloc();
  856. tr.testVideo->InitFromFile( args.Argv( 1 ), true );
  857. cinData_t cin;
  858. cin = tr.testVideo->ImageForTime( 0 );
  859. if ( cin.imageY == NULL ) {
  860. delete tr.testVideo;
  861. tr.testVideo = NULL;
  862. tr.testImage = NULL;
  863. return;
  864. }
  865. common->Printf( "%i x %i images\n", cin.imageWidth, cin.imageHeight );
  866. int len = tr.testVideo->AnimationLength();
  867. common->Printf( "%5.1f seconds of video\n", len * 0.001 );
  868. tr.testVideoStartTime = tr.primaryRenderView.time[1];
  869. // try to play the matching wav file
  870. idStr wavString = args.Argv( ( args.Argc() == 2 ) ? 1 : 2 );
  871. wavString.StripFileExtension();
  872. wavString = wavString + ".wav";
  873. common->SW()->PlayShaderDirectly( wavString.c_str() );
  874. }
  875. static int R_QsortSurfaceAreas( const void *a, const void *b ) {
  876. const idMaterial *ea, *eb;
  877. int ac, bc;
  878. ea = *(idMaterial **)a;
  879. if ( !ea->EverReferenced() ) {
  880. ac = 0;
  881. } else {
  882. ac = ea->GetSurfaceArea();
  883. }
  884. eb = *(idMaterial **)b;
  885. if ( !eb->EverReferenced() ) {
  886. bc = 0;
  887. } else {
  888. bc = eb->GetSurfaceArea();
  889. }
  890. if ( ac < bc ) {
  891. return -1;
  892. }
  893. if ( ac > bc ) {
  894. return 1;
  895. }
  896. return idStr::Icmp( ea->GetName(), eb->GetName() );
  897. }
  898. /*
  899. ===================
  900. R_ReportSurfaceAreas_f
  901. Prints a list of the materials sorted by surface area
  902. ===================
  903. */
  904. #pragma warning( disable: 6385 ) // This is simply to get pass a false defect for /analyze -- if you can figure out a better way, please let Shawn know...
  905. void R_ReportSurfaceAreas_f( const idCmdArgs &args ) {
  906. unsigned int i;
  907. idMaterial **list;
  908. const unsigned int count = declManager->GetNumDecls( DECL_MATERIAL );
  909. if ( count == 0 ) {
  910. return;
  911. }
  912. list = (idMaterial **)_alloca( count * sizeof( *list ) );
  913. for ( i = 0 ; i < count ; i++ ) {
  914. list[i] = (idMaterial *)declManager->DeclByIndex( DECL_MATERIAL, i, false );
  915. }
  916. qsort( list, count, sizeof( list[0] ), R_QsortSurfaceAreas );
  917. // skip over ones with 0 area
  918. for ( i = 0 ; i < count ; i++ ) {
  919. if ( list[i]->GetSurfaceArea() > 0 ) {
  920. break;
  921. }
  922. }
  923. for ( ; i < count ; i++ ) {
  924. // report size in "editor blocks"
  925. int blocks = list[i]->GetSurfaceArea() / 4096.0;
  926. common->Printf( "%7i %s\n", blocks, list[i]->GetName() );
  927. }
  928. }
  929. #pragma warning( default: 6385 )
  930. /*
  931. ==============================================================================
  932. SCREEN SHOTS
  933. ==============================================================================
  934. */
  935. /*
  936. ====================
  937. R_ReadTiledPixels
  938. NO LONGER SUPPORTED (FIXME: make standard case work)
  939. Used to allow the rendering of an image larger than the actual window by
  940. tiling it into window-sized chunks and rendering each chunk separately
  941. If ref isn't specified, the full session UpdateScreen will be done.
  942. ====================
  943. */
  944. void R_ReadTiledPixels( int width, int height, byte *buffer, renderView_t *ref = NULL ) {
  945. // include extra space for OpenGL padding to word boundaries
  946. int sysWidth = renderSystem->GetWidth();
  947. int sysHeight = renderSystem->GetHeight();
  948. byte * temp = (byte *)R_StaticAlloc( (sysWidth+3) * sysHeight * 3 );
  949. // disable scissor, so we don't need to adjust all those rects
  950. r_useScissor.SetBool( false );
  951. for ( int xo = 0 ; xo < width ; xo += sysWidth ) {
  952. for ( int yo = 0 ; yo < height ; yo += sysHeight ) {
  953. if ( ref ) {
  954. // discard anything currently on the list
  955. tr.SwapCommandBuffers( NULL, NULL, NULL, NULL );
  956. // build commands to render the scene
  957. tr.primaryWorld->RenderScene( ref );
  958. // finish off these commands
  959. const emptyCommand_t * cmd = tr.SwapCommandBuffers( NULL, NULL, NULL, NULL );
  960. // issue the commands to the GPU
  961. tr.RenderCommandBuffers( cmd );
  962. } else {
  963. const bool captureToImage = false;
  964. common->UpdateScreen( captureToImage );
  965. }
  966. int w = sysWidth;
  967. if ( xo + w > width ) {
  968. w = width - xo;
  969. }
  970. int h = sysHeight;
  971. if ( yo + h > height ) {
  972. h = height - yo;
  973. }
  974. qglReadBuffer( GL_FRONT );
  975. qglReadPixels( 0, 0, w, h, GL_RGB, GL_UNSIGNED_BYTE, temp );
  976. int row = ( w * 3 + 3 ) & ~3; // OpenGL pads to dword boundaries
  977. for ( int y = 0 ; y < h ; y++ ) {
  978. memcpy( buffer + ( ( yo + y )* width + xo ) * 3,
  979. temp + y * row, w * 3 );
  980. }
  981. }
  982. }
  983. r_useScissor.SetBool( true );
  984. R_StaticFree( temp );
  985. }
  986. /*
  987. ==================
  988. TakeScreenshot
  989. Move to tr_imagefiles.c...
  990. Downsample is the number of steps to mipmap the image before saving it
  991. If ref == NULL, common->UpdateScreen will be used
  992. ==================
  993. */
  994. void idRenderSystemLocal::TakeScreenshot( int width, int height, const char *fileName, int blends, renderView_t *ref ) {
  995. byte *buffer;
  996. int i, j, c, temp;
  997. takingScreenshot = true;
  998. const int pix = width * height;
  999. const int bufferSize = pix * 3 + 18;
  1000. buffer = (byte *)R_StaticAlloc( bufferSize );
  1001. memset( buffer, 0, bufferSize );
  1002. if ( blends <= 1 ) {
  1003. R_ReadTiledPixels( width, height, buffer + 18, ref );
  1004. } else {
  1005. unsigned short *shortBuffer = (unsigned short *)R_StaticAlloc(pix*2*3);
  1006. memset (shortBuffer, 0, pix*2*3);
  1007. // enable anti-aliasing jitter
  1008. r_jitter.SetBool( true );
  1009. for ( i = 0 ; i < blends ; i++ ) {
  1010. R_ReadTiledPixels( width, height, buffer + 18, ref );
  1011. for ( j = 0 ; j < pix*3 ; j++ ) {
  1012. shortBuffer[j] += buffer[18+j];
  1013. }
  1014. }
  1015. // divide back to bytes
  1016. for ( i = 0 ; i < pix*3 ; i++ ) {
  1017. buffer[18+i] = shortBuffer[i] / blends;
  1018. }
  1019. R_StaticFree( shortBuffer );
  1020. r_jitter.SetBool( false );
  1021. }
  1022. // fill in the header (this is vertically flipped, which qglReadPixels emits)
  1023. buffer[2] = 2; // uncompressed type
  1024. buffer[12] = width & 255;
  1025. buffer[13] = width >> 8;
  1026. buffer[14] = height & 255;
  1027. buffer[15] = height >> 8;
  1028. buffer[16] = 24; // pixel size
  1029. // swap rgb to bgr
  1030. c = 18 + width * height * 3;
  1031. for (i=18 ; i<c ; i+=3) {
  1032. temp = buffer[i];
  1033. buffer[i] = buffer[i+2];
  1034. buffer[i+2] = temp;
  1035. }
  1036. fileSystem->WriteFile( fileName, buffer, c );
  1037. R_StaticFree( buffer );
  1038. takingScreenshot = false;
  1039. }
  1040. /*
  1041. ==================
  1042. R_ScreenshotFilename
  1043. Returns a filename with digits appended
  1044. if we have saved a previous screenshot, don't scan
  1045. from the beginning, because recording demo avis can involve
  1046. thousands of shots
  1047. ==================
  1048. */
  1049. void R_ScreenshotFilename( int &lastNumber, const char *base, idStr &fileName ) {
  1050. int a,b,c,d, e;
  1051. bool restrict = cvarSystem->GetCVarBool( "fs_restrict" );
  1052. cvarSystem->SetCVarBool( "fs_restrict", false );
  1053. lastNumber++;
  1054. if ( lastNumber > 99999 ) {
  1055. lastNumber = 99999;
  1056. }
  1057. for ( ; lastNumber < 99999 ; lastNumber++ ) {
  1058. int frac = lastNumber;
  1059. a = frac / 10000;
  1060. frac -= a*10000;
  1061. b = frac / 1000;
  1062. frac -= b*1000;
  1063. c = frac / 100;
  1064. frac -= c*100;
  1065. d = frac / 10;
  1066. frac -= d*10;
  1067. e = frac;
  1068. sprintf( fileName, "%s%i%i%i%i%i.tga", base, a, b, c, d, e );
  1069. if ( lastNumber == 99999 ) {
  1070. break;
  1071. }
  1072. int len = fileSystem->ReadFile( fileName, NULL, NULL );
  1073. if ( len <= 0 ) {
  1074. break;
  1075. }
  1076. // check again...
  1077. }
  1078. cvarSystem->SetCVarBool( "fs_restrict", restrict );
  1079. }
  1080. /*
  1081. ==================
  1082. R_BlendedScreenShot
  1083. screenshot
  1084. screenshot [filename]
  1085. screenshot [width] [height]
  1086. screenshot [width] [height] [samples]
  1087. ==================
  1088. */
  1089. #define MAX_BLENDS 256 // to keep the accumulation in shorts
  1090. void R_ScreenShot_f( const idCmdArgs &args ) {
  1091. static int lastNumber = 0;
  1092. idStr checkname;
  1093. int width = renderSystem->GetWidth();
  1094. int height = renderSystem->GetHeight();
  1095. int blends = 0;
  1096. switch ( args.Argc() ) {
  1097. case 1:
  1098. width = renderSystem->GetWidth();
  1099. height = renderSystem->GetHeight();
  1100. blends = 1;
  1101. R_ScreenshotFilename( lastNumber, "screenshots/shot", checkname );
  1102. break;
  1103. case 2:
  1104. width = renderSystem->GetWidth();
  1105. height = renderSystem->GetHeight();
  1106. blends = 1;
  1107. checkname = args.Argv( 1 );
  1108. break;
  1109. case 3:
  1110. width = atoi( args.Argv( 1 ) );
  1111. height = atoi( args.Argv( 2 ) );
  1112. blends = 1;
  1113. R_ScreenshotFilename( lastNumber, "screenshots/shot", checkname );
  1114. break;
  1115. case 4:
  1116. width = atoi( args.Argv( 1 ) );
  1117. height = atoi( args.Argv( 2 ) );
  1118. blends = atoi( args.Argv( 3 ) );
  1119. if ( blends < 1 ) {
  1120. blends = 1;
  1121. }
  1122. if ( blends > MAX_BLENDS ) {
  1123. blends = MAX_BLENDS;
  1124. }
  1125. R_ScreenshotFilename( lastNumber, "screenshots/shot", checkname );
  1126. break;
  1127. default:
  1128. common->Printf( "usage: screenshot\n screenshot <filename>\n screenshot <width> <height>\n screenshot <width> <height> <blends>\n" );
  1129. return;
  1130. }
  1131. // put the console away
  1132. console->Close();
  1133. tr.TakeScreenshot( width, height, checkname, blends, NULL );
  1134. common->Printf( "Wrote %s\n", checkname.c_str() );
  1135. }
  1136. /*
  1137. ===============
  1138. R_StencilShot
  1139. Save out a screenshot showing the stencil buffer expanded by 16x range
  1140. ===============
  1141. */
  1142. void R_StencilShot() {
  1143. int i, c;
  1144. int width = tr.GetWidth();
  1145. int height = tr.GetHeight();
  1146. int pix = width * height;
  1147. c = pix * 3 + 18;
  1148. idTempArray< byte > buffer( c );
  1149. memset( buffer.Ptr(), 0, 18 );
  1150. idTempArray< byte > byteBuffer( pix );
  1151. qglReadPixels( 0, 0, width, height, GL_STENCIL_INDEX , GL_UNSIGNED_BYTE, byteBuffer.Ptr() );
  1152. for ( i = 0 ; i < pix ; i++ ) {
  1153. buffer[18+i*3] =
  1154. buffer[18+i*3+1] =
  1155. // buffer[18+i*3+2] = ( byteBuffer[i] & 15 ) * 16;
  1156. buffer[18+i*3+2] = byteBuffer[i];
  1157. }
  1158. // fill in the header (this is vertically flipped, which qglReadPixels emits)
  1159. buffer[2] = 2; // uncompressed type
  1160. buffer[12] = width & 255;
  1161. buffer[13] = width >> 8;
  1162. buffer[14] = height & 255;
  1163. buffer[15] = height >> 8;
  1164. buffer[16] = 24; // pixel size
  1165. fileSystem->WriteFile( "screenshots/stencilShot.tga", buffer.Ptr(), c, "fs_savepath" );
  1166. }
  1167. //============================================================================
  1168. static idMat3 cubeAxis[6];
  1169. /*
  1170. ==================
  1171. R_SampleCubeMap
  1172. ==================
  1173. */
  1174. void R_SampleCubeMap( const idVec3 &dir, int size, byte *buffers[6], byte result[4] ) {
  1175. float adir[3];
  1176. int axis, x, y;
  1177. adir[0] = fabs(dir[0]);
  1178. adir[1] = fabs(dir[1]);
  1179. adir[2] = fabs(dir[2]);
  1180. if ( dir[0] >= adir[1] && dir[0] >= adir[2] ) {
  1181. axis = 0;
  1182. } else if ( -dir[0] >= adir[1] && -dir[0] >= adir[2] ) {
  1183. axis = 1;
  1184. } else if ( dir[1] >= adir[0] && dir[1] >= adir[2] ) {
  1185. axis = 2;
  1186. } else if ( -dir[1] >= adir[0] && -dir[1] >= adir[2] ) {
  1187. axis = 3;
  1188. } else if ( dir[2] >= adir[1] && dir[2] >= adir[2] ) {
  1189. axis = 4;
  1190. } else {
  1191. axis = 5;
  1192. }
  1193. float fx = (dir * cubeAxis[axis][1]) / (dir * cubeAxis[axis][0]);
  1194. float fy = (dir * cubeAxis[axis][2]) / (dir * cubeAxis[axis][0]);
  1195. fx = -fx;
  1196. fy = -fy;
  1197. x = size * 0.5 * (fx + 1);
  1198. y = size * 0.5 * (fy + 1);
  1199. if ( x < 0 ) {
  1200. x = 0;
  1201. } else if ( x >= size ) {
  1202. x = size-1;
  1203. }
  1204. if ( y < 0 ) {
  1205. y = 0;
  1206. } else if ( y >= size ) {
  1207. y = size-1;
  1208. }
  1209. result[0] = buffers[axis][(y*size+x)*4+0];
  1210. result[1] = buffers[axis][(y*size+x)*4+1];
  1211. result[2] = buffers[axis][(y*size+x)*4+2];
  1212. result[3] = buffers[axis][(y*size+x)*4+3];
  1213. }
  1214. /*
  1215. ==================
  1216. R_MakeAmbientMap_f
  1217. R_MakeAmbientMap_f <basename> [size]
  1218. Saves out env/<basename>_amb_ft.tga, etc
  1219. ==================
  1220. */
  1221. void R_MakeAmbientMap_f( const idCmdArgs &args ) {
  1222. idStr fullname;
  1223. const char *baseName;
  1224. int i;
  1225. renderView_t ref;
  1226. viewDef_t primary;
  1227. int downSample;
  1228. char *extensions[6] = { "_px.tga", "_nx.tga", "_py.tga", "_ny.tga",
  1229. "_pz.tga", "_nz.tga" };
  1230. int outSize;
  1231. byte *buffers[6];
  1232. int width = 0, height = 0;
  1233. if ( args.Argc() != 2 && args.Argc() != 3 ) {
  1234. common->Printf( "USAGE: ambientshot <basename> [size]\n" );
  1235. return;
  1236. }
  1237. baseName = args.Argv( 1 );
  1238. downSample = 0;
  1239. if ( args.Argc() == 3 ) {
  1240. outSize = atoi( args.Argv( 2 ) );
  1241. } else {
  1242. outSize = 32;
  1243. }
  1244. memset( &cubeAxis, 0, sizeof( cubeAxis ) );
  1245. cubeAxis[0][0][0] = 1;
  1246. cubeAxis[0][1][2] = 1;
  1247. cubeAxis[0][2][1] = 1;
  1248. cubeAxis[1][0][0] = -1;
  1249. cubeAxis[1][1][2] = -1;
  1250. cubeAxis[1][2][1] = 1;
  1251. cubeAxis[2][0][1] = 1;
  1252. cubeAxis[2][1][0] = -1;
  1253. cubeAxis[2][2][2] = -1;
  1254. cubeAxis[3][0][1] = -1;
  1255. cubeAxis[3][1][0] = -1;
  1256. cubeAxis[3][2][2] = 1;
  1257. cubeAxis[4][0][2] = 1;
  1258. cubeAxis[4][1][0] = -1;
  1259. cubeAxis[4][2][1] = 1;
  1260. cubeAxis[5][0][2] = -1;
  1261. cubeAxis[5][1][0] = 1;
  1262. cubeAxis[5][2][1] = 1;
  1263. // read all of the images
  1264. for ( i = 0 ; i < 6 ; i++ ) {
  1265. sprintf( fullname, "env/%s%s", baseName, extensions[i] );
  1266. common->Printf( "loading %s\n", fullname.c_str() );
  1267. const bool captureToImage = false;
  1268. common->UpdateScreen( captureToImage );
  1269. R_LoadImage( fullname, &buffers[i], &width, &height, NULL, true );
  1270. if ( !buffers[i] ) {
  1271. common->Printf( "failed.\n" );
  1272. for ( i-- ; i >= 0 ; i-- ) {
  1273. Mem_Free( buffers[i] );
  1274. }
  1275. return;
  1276. }
  1277. }
  1278. // resample with hemispherical blending
  1279. int samples = 1000;
  1280. byte *outBuffer = (byte *)_alloca( outSize * outSize * 4 );
  1281. for ( int map = 0 ; map < 2 ; map++ ) {
  1282. for ( i = 0 ; i < 6 ; i++ ) {
  1283. for ( int x = 0 ; x < outSize ; x++ ) {
  1284. for ( int y = 0 ; y < outSize ; y++ ) {
  1285. idVec3 dir;
  1286. float total[3];
  1287. dir = cubeAxis[i][0] + -( -1 + 2.0*x/(outSize-1) ) * cubeAxis[i][1] + -( -1 + 2.0*y/(outSize-1) ) * cubeAxis[i][2];
  1288. dir.Normalize();
  1289. total[0] = total[1] = total[2] = 0;
  1290. //samples = 1;
  1291. float limit = map ? 0.95 : 0.25; // small for specular, almost hemisphere for ambient
  1292. for ( int s = 0 ; s < samples ; s++ ) {
  1293. // pick a random direction vector that is inside the unit sphere but not behind dir,
  1294. // which is a robust way to evenly sample a hemisphere
  1295. idVec3 test;
  1296. while( 1 ) {
  1297. for ( int j = 0 ; j < 3 ; j++ ) {
  1298. test[j] = -1 + 2 * (rand()&0x7fff)/(float)0x7fff;
  1299. }
  1300. if ( test.Length() > 1.0 ) {
  1301. continue;
  1302. }
  1303. test.Normalize();
  1304. if ( test * dir > limit ) { // don't do a complete hemisphere
  1305. break;
  1306. }
  1307. }
  1308. byte result[4];
  1309. //test = dir;
  1310. R_SampleCubeMap( test, width, buffers, result );
  1311. total[0] += result[0];
  1312. total[1] += result[1];
  1313. total[2] += result[2];
  1314. }
  1315. outBuffer[(y*outSize+x)*4+0] = total[0] / samples;
  1316. outBuffer[(y*outSize+x)*4+1] = total[1] / samples;
  1317. outBuffer[(y*outSize+x)*4+2] = total[2] / samples;
  1318. outBuffer[(y*outSize+x)*4+3] = 255;
  1319. }
  1320. }
  1321. if ( map == 0 ) {
  1322. sprintf( fullname, "env/%s_amb%s", baseName, extensions[i] );
  1323. } else {
  1324. sprintf( fullname, "env/%s_spec%s", baseName, extensions[i] );
  1325. }
  1326. common->Printf( "writing %s\n", fullname.c_str() );
  1327. const bool captureToImage = false;
  1328. common->UpdateScreen( captureToImage );
  1329. R_WriteTGA( fullname, outBuffer, outSize, outSize );
  1330. }
  1331. }
  1332. for ( i = 0 ; i < 6 ; i++ ) {
  1333. if ( buffers[i] ) {
  1334. Mem_Free( buffers[i] );
  1335. }
  1336. }
  1337. }
  1338. //============================================================================
  1339. /*
  1340. ===============
  1341. R_SetColorMappings
  1342. ===============
  1343. */
  1344. void R_SetColorMappings() {
  1345. float b = r_brightness.GetFloat();
  1346. float invg = 1.0f / r_gamma.GetFloat();
  1347. float j = 0.0f;
  1348. for ( int i = 0; i < 256; i++, j += b ) {
  1349. int inf = idMath::Ftoi( 0xffff * pow( j / 255.0f, invg ) + 0.5f );
  1350. tr.gammaTable[i] = idMath::ClampInt( 0, 0xFFFF, inf );
  1351. }
  1352. GLimp_SetGamma( tr.gammaTable, tr.gammaTable, tr.gammaTable );
  1353. }
  1354. /*
  1355. ================
  1356. GfxInfo_f
  1357. ================
  1358. */
  1359. void GfxInfo_f( const idCmdArgs &args ) {
  1360. common->Printf( "CPU: %s\n", Sys_GetProcessorString() );
  1361. const char *fsstrings[] =
  1362. {
  1363. "windowed",
  1364. "fullscreen"
  1365. };
  1366. common->Printf( "\nGL_VENDOR: %s\n", glConfig.vendor_string );
  1367. common->Printf( "GL_RENDERER: %s\n", glConfig.renderer_string );
  1368. common->Printf( "GL_VERSION: %s\n", glConfig.version_string );
  1369. common->Printf( "GL_EXTENSIONS: %s\n", glConfig.extensions_string );
  1370. if ( glConfig.wgl_extensions_string ) {
  1371. common->Printf( "WGL_EXTENSIONS: %s\n", glConfig.wgl_extensions_string );
  1372. }
  1373. common->Printf( "GL_MAX_TEXTURE_SIZE: %d\n", glConfig.maxTextureSize );
  1374. common->Printf( "GL_MAX_TEXTURE_COORDS_ARB: %d\n", glConfig.maxTextureCoords );
  1375. common->Printf( "GL_MAX_TEXTURE_IMAGE_UNITS_ARB: %d\n", glConfig.maxTextureImageUnits );
  1376. // print all the display adapters, monitors, and video modes
  1377. void DumpAllDisplayDevices();
  1378. DumpAllDisplayDevices();
  1379. common->Printf( "\nPIXELFORMAT: color(%d-bits) Z(%d-bit) stencil(%d-bits)\n", glConfig.colorBits, glConfig.depthBits, glConfig.stencilBits );
  1380. common->Printf( "MODE: %d, %d x %d %s hz:", r_vidMode.GetInteger(), renderSystem->GetWidth(), renderSystem->GetHeight(), fsstrings[r_fullscreen.GetBool()] );
  1381. if ( glConfig.displayFrequency ) {
  1382. common->Printf( "%d\n", glConfig.displayFrequency );
  1383. } else {
  1384. common->Printf( "N/A\n" );
  1385. }
  1386. common->Printf( "-------\n" );
  1387. // WGL_EXT_swap_interval
  1388. typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC) (int interval);
  1389. extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT;
  1390. if ( r_swapInterval.GetInteger() && wglSwapIntervalEXT != NULL ) {
  1391. common->Printf( "Forcing swapInterval %i\n", r_swapInterval.GetInteger() );
  1392. } else {
  1393. common->Printf( "swapInterval not forced\n" );
  1394. }
  1395. if ( glConfig.stereoPixelFormatAvailable && glConfig.isStereoPixelFormat ) {
  1396. idLib::Printf( "OpenGl quad buffer stereo pixel format active\n" );
  1397. } else if ( glConfig.stereoPixelFormatAvailable ) {
  1398. idLib::Printf( "OpenGl quad buffer stereo pixel available but not selected\n" );
  1399. } else {
  1400. idLib::Printf( "OpenGl quad buffer stereo pixel format not available\n" );
  1401. }
  1402. idLib::Printf( "Stereo mode: " );
  1403. switch ( renderSystem->GetStereo3DMode() ) {
  1404. case STEREO3D_OFF: idLib::Printf( "STEREO3D_OFF\n" ); break;
  1405. case STEREO3D_SIDE_BY_SIDE_COMPRESSED: idLib::Printf( "STEREO3D_SIDE_BY_SIDE_COMPRESSED\n" ); break;
  1406. case STEREO3D_TOP_AND_BOTTOM_COMPRESSED:idLib::Printf( "STEREO3D_TOP_AND_BOTTOM_COMPRESSED\n" ); break;
  1407. case STEREO3D_SIDE_BY_SIDE: idLib::Printf( "STEREO3D_SIDE_BY_SIDE\n" ); break;
  1408. case STEREO3D_HDMI_720: idLib::Printf( "STEREO3D_HDMI_720\n" ); break;
  1409. case STEREO3D_INTERLACED: idLib::Printf( "STEREO3D_INTERLACED\n" ); break;
  1410. case STEREO3D_QUAD_BUFFER: idLib::Printf( "STEREO3D_QUAD_BUFFER\n" ); break;
  1411. default:idLib::Printf( "Unknown (%i)\n", renderSystem->GetStereo3DMode() ); break;
  1412. }
  1413. idLib::Printf( "%i multisamples\n", glConfig.multisamples );
  1414. common->Printf( "%5.1f cm screen width (%4.1f\" diagonal)\n",
  1415. glConfig.physicalScreenWidthInCentimeters, glConfig.physicalScreenWidthInCentimeters / 2.54f
  1416. * sqrt( (float)(16*16 + 9*9) ) / 16.0f );
  1417. extern idCVar r_forceScreenWidthCentimeters;
  1418. if ( r_forceScreenWidthCentimeters.GetFloat() ) {
  1419. common->Printf( "screen size manually forced to %5.1f cm width (%4.1f\" diagonal)\n",
  1420. renderSystem->GetPhysicalScreenWidthInCentimeters(), renderSystem->GetPhysicalScreenWidthInCentimeters() / 2.54f
  1421. * sqrt( (float)(16*16 + 9*9) ) / 16.0f );
  1422. }
  1423. }
  1424. /*
  1425. =================
  1426. R_VidRestart_f
  1427. =================
  1428. */
  1429. void R_VidRestart_f( const idCmdArgs &args ) {
  1430. // if OpenGL isn't started, do nothing
  1431. if ( !R_IsInitialized() ) {
  1432. return;
  1433. }
  1434. // set the mode without re-initializing the context
  1435. R_SetNewMode( false );
  1436. #if 0
  1437. bool full = true;
  1438. bool forceWindow = false;
  1439. for ( int i = 1 ; i < args.Argc() ; i++ ) {
  1440. if ( idStr::Icmp( args.Argv( i ), "partial" ) == 0 ) {
  1441. full = false;
  1442. continue;
  1443. }
  1444. if ( idStr::Icmp( args.Argv( i ), "windowed" ) == 0 ) {
  1445. forceWindow = true;
  1446. continue;
  1447. }
  1448. }
  1449. // this could take a while, so give them the cursor back ASAP
  1450. Sys_GrabMouseCursor( false );
  1451. // dump ambient caches
  1452. renderModelManager->FreeModelVertexCaches();
  1453. // free any current world interaction surfaces and vertex caches
  1454. R_FreeDerivedData();
  1455. // make sure the defered frees are actually freed
  1456. R_ToggleSmpFrame();
  1457. R_ToggleSmpFrame();
  1458. // free the vertex caches so they will be regenerated again
  1459. vertexCache.PurgeAll();
  1460. // sound and input are tied to the window we are about to destroy
  1461. if ( full ) {
  1462. // free all of our texture numbers
  1463. Sys_ShutdownInput();
  1464. globalImages->PurgeAllImages();
  1465. // free the context and close the window
  1466. GLimp_Shutdown();
  1467. r_initialized = false;
  1468. // create the new context and vertex cache
  1469. bool latch = cvarSystem->GetCVarBool( "r_fullscreen" );
  1470. if ( forceWindow ) {
  1471. cvarSystem->SetCVarBool( "r_fullscreen", false );
  1472. }
  1473. R_InitOpenGL();
  1474. cvarSystem->SetCVarBool( "r_fullscreen", latch );
  1475. // regenerate all images
  1476. globalImages->ReloadImages( true );
  1477. } else {
  1478. glimpParms_t parms;
  1479. parms.width = glConfig.nativeScreenWidth;
  1480. parms.height = glConfig.nativeScreenHeight;
  1481. parms.fullScreen = ( forceWindow ) ? false : r_fullscreen.GetInteger();
  1482. parms.displayHz = r_displayRefresh.GetInteger();
  1483. parms.multiSamples = r_multiSamples.GetInteger();
  1484. parms.stereo = false;
  1485. GLimp_SetScreenParms( parms );
  1486. }
  1487. // make sure the regeneration doesn't use anything no longer valid
  1488. tr.viewCount++;
  1489. tr.viewDef = NULL;
  1490. // check for problems
  1491. int err = qglGetError();
  1492. if ( err != GL_NO_ERROR ) {
  1493. common->Printf( "glGetError() = 0x%x\n", err );
  1494. }
  1495. #endif
  1496. }
  1497. /*
  1498. =================
  1499. R_InitMaterials
  1500. =================
  1501. */
  1502. void R_InitMaterials() {
  1503. tr.defaultMaterial = declManager->FindMaterial( "_default", false );
  1504. if ( !tr.defaultMaterial ) {
  1505. common->FatalError( "_default material not found" );
  1506. }
  1507. tr.defaultPointLight = declManager->FindMaterial( "lights/defaultPointLight" );
  1508. tr.defaultProjectedLight = declManager->FindMaterial( "lights/defaultProjectedLight" );
  1509. tr.whiteMaterial = declManager->FindMaterial( "_white" );
  1510. tr.charSetMaterial = declManager->FindMaterial( "textures/bigchars" );
  1511. }
  1512. /*
  1513. =================
  1514. R_SizeUp_f
  1515. Keybinding command
  1516. =================
  1517. */
  1518. static void R_SizeUp_f( const idCmdArgs &args ) {
  1519. if ( r_screenFraction.GetInteger() + 10 > 100 ) {
  1520. r_screenFraction.SetInteger( 100 );
  1521. } else {
  1522. r_screenFraction.SetInteger( r_screenFraction.GetInteger() + 10 );
  1523. }
  1524. }
  1525. /*
  1526. =================
  1527. R_SizeDown_f
  1528. Keybinding command
  1529. =================
  1530. */
  1531. static void R_SizeDown_f( const idCmdArgs &args ) {
  1532. if ( r_screenFraction.GetInteger() - 10 < 10 ) {
  1533. r_screenFraction.SetInteger( 10 );
  1534. } else {
  1535. r_screenFraction.SetInteger( r_screenFraction.GetInteger() - 10 );
  1536. }
  1537. }
  1538. /*
  1539. ===============
  1540. TouchGui_f
  1541. this is called from the main thread
  1542. ===============
  1543. */
  1544. void R_TouchGui_f( const idCmdArgs &args ) {
  1545. const char *gui = args.Argv( 1 );
  1546. if ( !gui[0] ) {
  1547. common->Printf( "USAGE: touchGui <guiName>\n" );
  1548. return;
  1549. }
  1550. common->Printf( "touchGui %s\n", gui );
  1551. const bool captureToImage = false;
  1552. common->UpdateScreen( captureToImage );
  1553. uiManager->Touch( gui );
  1554. }
  1555. /*
  1556. =================
  1557. R_InitCvars
  1558. =================
  1559. */
  1560. void R_InitCvars() {
  1561. // update latched cvars here
  1562. }
  1563. /*
  1564. =================
  1565. R_InitCommands
  1566. =================
  1567. */
  1568. void R_InitCommands() {
  1569. cmdSystem->AddCommand( "sizeUp", R_SizeUp_f, CMD_FL_RENDERER, "makes the rendered view larger" );
  1570. cmdSystem->AddCommand( "sizeDown", R_SizeDown_f, CMD_FL_RENDERER, "makes the rendered view smaller" );
  1571. cmdSystem->AddCommand( "reloadGuis", R_ReloadGuis_f, CMD_FL_RENDERER, "reloads guis" );
  1572. cmdSystem->AddCommand( "listGuis", R_ListGuis_f, CMD_FL_RENDERER, "lists guis" );
  1573. cmdSystem->AddCommand( "touchGui", R_TouchGui_f, CMD_FL_RENDERER, "touches a gui" );
  1574. cmdSystem->AddCommand( "screenshot", R_ScreenShot_f, CMD_FL_RENDERER, "takes a screenshot" );
  1575. cmdSystem->AddCommand( "makeAmbientMap", R_MakeAmbientMap_f, CMD_FL_RENDERER|CMD_FL_CHEAT, "makes an ambient map" );
  1576. cmdSystem->AddCommand( "gfxInfo", GfxInfo_f, CMD_FL_RENDERER, "show graphics info" );
  1577. cmdSystem->AddCommand( "modulateLights", R_ModulateLights_f, CMD_FL_RENDERER | CMD_FL_CHEAT, "modifies shader parms on all lights" );
  1578. cmdSystem->AddCommand( "testImage", R_TestImage_f, CMD_FL_RENDERER | CMD_FL_CHEAT, "displays the given image centered on screen", idCmdSystem::ArgCompletion_ImageName );
  1579. cmdSystem->AddCommand( "testVideo", R_TestVideo_f, CMD_FL_RENDERER | CMD_FL_CHEAT, "displays the given cinematic", idCmdSystem::ArgCompletion_VideoName );
  1580. cmdSystem->AddCommand( "reportSurfaceAreas", R_ReportSurfaceAreas_f, CMD_FL_RENDERER, "lists all used materials sorted by surface area" );
  1581. cmdSystem->AddCommand( "showInteractionMemory", R_ShowInteractionMemory_f, CMD_FL_RENDERER, "shows memory used by interactions" );
  1582. cmdSystem->AddCommand( "vid_restart", R_VidRestart_f, CMD_FL_RENDERER, "restarts renderSystem" );
  1583. cmdSystem->AddCommand( "listRenderEntityDefs", R_ListRenderEntityDefs_f, CMD_FL_RENDERER, "lists the entity defs" );
  1584. cmdSystem->AddCommand( "listRenderLightDefs", R_ListRenderLightDefs_f, CMD_FL_RENDERER, "lists the light defs" );
  1585. cmdSystem->AddCommand( "listModes", R_ListModes_f, CMD_FL_RENDERER, "lists all video modes" );
  1586. cmdSystem->AddCommand( "reloadSurface", R_ReloadSurface_f, CMD_FL_RENDERER, "reloads the decl and images for selected surface" );
  1587. }
  1588. /*
  1589. ===============
  1590. idRenderSystemLocal::Clear
  1591. ===============
  1592. */
  1593. void idRenderSystemLocal::Clear() {
  1594. registered = false;
  1595. frameCount = 0;
  1596. viewCount = 0;
  1597. frameShaderTime = 0.0f;
  1598. ambientLightVector.Zero();
  1599. worlds.Clear();
  1600. primaryWorld = NULL;
  1601. memset( &primaryRenderView, 0, sizeof( primaryRenderView ) );
  1602. primaryView = NULL;
  1603. defaultMaterial = NULL;
  1604. testImage = NULL;
  1605. ambientCubeImage = NULL;
  1606. viewDef = NULL;
  1607. memset( &pc, 0, sizeof( pc ) );
  1608. memset( &identitySpace, 0, sizeof( identitySpace ) );
  1609. memset( renderCrops, 0, sizeof( renderCrops ) );
  1610. currentRenderCrop = 0;
  1611. currentColorNativeBytesOrder = 0xFFFFFFFF;
  1612. currentGLState = 0;
  1613. guiRecursionLevel = 0;
  1614. guiModel = NULL;
  1615. memset( gammaTable, 0, sizeof( gammaTable ) );
  1616. takingScreenshot = false;
  1617. if ( unitSquareTriangles != NULL ) {
  1618. Mem_Free( unitSquareTriangles );
  1619. unitSquareTriangles = NULL;
  1620. }
  1621. if ( zeroOneCubeTriangles != NULL ) {
  1622. Mem_Free( zeroOneCubeTriangles );
  1623. zeroOneCubeTriangles = NULL;
  1624. }
  1625. if ( testImageTriangles != NULL ) {
  1626. Mem_Free( testImageTriangles );
  1627. testImageTriangles = NULL;
  1628. }
  1629. frontEndJobList = NULL;
  1630. }
  1631. /*
  1632. =============
  1633. R_MakeFullScreenTris
  1634. =============
  1635. */
  1636. static srfTriangles_t * R_MakeFullScreenTris() {
  1637. // copy verts and indexes
  1638. srfTriangles_t * tri = (srfTriangles_t *)Mem_ClearedAlloc( sizeof( *tri ), TAG_RENDER_TOOLS );
  1639. tri->numIndexes = 6;
  1640. tri->numVerts = 4;
  1641. int indexSize = tri->numIndexes * sizeof( tri->indexes[0] );
  1642. int allocatedIndexBytes = ALIGN( indexSize, 16 );
  1643. tri->indexes = (triIndex_t *)Mem_Alloc( allocatedIndexBytes, TAG_RENDER_TOOLS );
  1644. int vertexSize = tri->numVerts * sizeof( tri->verts[0] );
  1645. int allocatedVertexBytes = ALIGN( vertexSize, 16 );
  1646. tri->verts = (idDrawVert *)Mem_ClearedAlloc( allocatedVertexBytes, TAG_RENDER_TOOLS );
  1647. idDrawVert * verts = tri->verts;
  1648. triIndex_t tempIndexes[6] = { 3, 0, 2, 2, 0, 1 };
  1649. memcpy( tri->indexes, tempIndexes, indexSize );
  1650. verts[0].xyz[0] = -1.0f;
  1651. verts[0].xyz[1] = 1.0f;
  1652. verts[0].SetTexCoord( 0.0f, 1.0f );
  1653. verts[1].xyz[0] = 1.0f;
  1654. verts[1].xyz[1] = 1.0f;
  1655. verts[1].SetTexCoord( 1.0f, 1.0f );
  1656. verts[2].xyz[0] = 1.0f;
  1657. verts[2].xyz[1] = -1.0f;
  1658. verts[2].SetTexCoord( 1.0f, 0.0f );
  1659. verts[3].xyz[0] = -1.0f;
  1660. verts[3].xyz[1] = -1.0f;
  1661. verts[3].SetTexCoord( 0.0f, 0.0f );
  1662. for ( int i = 0 ; i < 4 ; i++ ) {
  1663. verts[i].SetColor( 0xffffffff );
  1664. }
  1665. return tri;
  1666. }
  1667. /*
  1668. =============
  1669. R_MakeZeroOneCubeTris
  1670. =============
  1671. */
  1672. static srfTriangles_t * R_MakeZeroOneCubeTris() {
  1673. srfTriangles_t * tri = (srfTriangles_t *)Mem_ClearedAlloc( sizeof( *tri ), TAG_RENDER_TOOLS );
  1674. tri->numVerts = 8;
  1675. tri->numIndexes = 36;
  1676. const int indexSize = tri->numIndexes * sizeof( tri->indexes[0] );
  1677. const int allocatedIndexBytes = ALIGN( indexSize, 16 );
  1678. tri->indexes = (triIndex_t *)Mem_Alloc( allocatedIndexBytes, TAG_RENDER_TOOLS );
  1679. const int vertexSize = tri->numVerts * sizeof( tri->verts[0] );
  1680. const int allocatedVertexBytes = ALIGN( vertexSize, 16 );
  1681. tri->verts = (idDrawVert *)Mem_ClearedAlloc( allocatedVertexBytes, TAG_RENDER_TOOLS );
  1682. idDrawVert * verts = tri->verts;
  1683. const float low = 0.0f;
  1684. const float high = 1.0f;
  1685. idVec3 center( 0.0f );
  1686. idVec3 mx( low, 0.0f, 0.0f );
  1687. idVec3 px( high, 0.0f, 0.0f );
  1688. idVec3 my( 0.0f, low, 0.0f );
  1689. idVec3 py( 0.0f, high, 0.0f );
  1690. idVec3 mz( 0.0f, 0.0f, low );
  1691. idVec3 pz( 0.0f, 0.0f, high );
  1692. verts[0].xyz = center + mx + my + mz;
  1693. verts[1].xyz = center + px + my + mz;
  1694. verts[2].xyz = center + px + py + mz;
  1695. verts[3].xyz = center + mx + py + mz;
  1696. verts[4].xyz = center + mx + my + pz;
  1697. verts[5].xyz = center + px + my + pz;
  1698. verts[6].xyz = center + px + py + pz;
  1699. verts[7].xyz = center + mx + py + pz;
  1700. // bottom
  1701. tri->indexes[ 0*3+0] = 2;
  1702. tri->indexes[ 0*3+1] = 3;
  1703. tri->indexes[ 0*3+2] = 0;
  1704. tri->indexes[ 1*3+0] = 1;
  1705. tri->indexes[ 1*3+1] = 2;
  1706. tri->indexes[ 1*3+2] = 0;
  1707. // back
  1708. tri->indexes[ 2*3+0] = 5;
  1709. tri->indexes[ 2*3+1] = 1;
  1710. tri->indexes[ 2*3+2] = 0;
  1711. tri->indexes[ 3*3+0] = 4;
  1712. tri->indexes[ 3*3+1] = 5;
  1713. tri->indexes[ 3*3+2] = 0;
  1714. // left
  1715. tri->indexes[ 4*3+0] = 7;
  1716. tri->indexes[ 4*3+1] = 4;
  1717. tri->indexes[ 4*3+2] = 0;
  1718. tri->indexes[ 5*3+0] = 3;
  1719. tri->indexes[ 5*3+1] = 7;
  1720. tri->indexes[ 5*3+2] = 0;
  1721. // right
  1722. tri->indexes[ 6*3+0] = 1;
  1723. tri->indexes[ 6*3+1] = 5;
  1724. tri->indexes[ 6*3+2] = 6;
  1725. tri->indexes[ 7*3+0] = 2;
  1726. tri->indexes[ 7*3+1] = 1;
  1727. tri->indexes[ 7*3+2] = 6;
  1728. // front
  1729. tri->indexes[ 8*3+0] = 3;
  1730. tri->indexes[ 8*3+1] = 2;
  1731. tri->indexes[ 8*3+2] = 6;
  1732. tri->indexes[ 9*3+0] = 7;
  1733. tri->indexes[ 9*3+1] = 3;
  1734. tri->indexes[ 9*3+2] = 6;
  1735. // top
  1736. tri->indexes[10*3+0] = 4;
  1737. tri->indexes[10*3+1] = 7;
  1738. tri->indexes[10*3+2] = 6;
  1739. tri->indexes[11*3+0] = 5;
  1740. tri->indexes[11*3+1] = 4;
  1741. tri->indexes[11*3+2] = 6;
  1742. for ( int i = 0 ; i < 4 ; i++ ) {
  1743. verts[i].SetColor( 0xffffffff );
  1744. }
  1745. return tri;
  1746. }
  1747. /*
  1748. ================
  1749. R_MakeTestImageTriangles
  1750. Initializes the Test Image Triangles
  1751. ================
  1752. */
  1753. srfTriangles_t* R_MakeTestImageTriangles() {
  1754. srfTriangles_t * tri = (srfTriangles_t *)Mem_ClearedAlloc( sizeof( *tri ), TAG_RENDER_TOOLS );
  1755. tri->numIndexes = 6;
  1756. tri->numVerts = 4;
  1757. int indexSize = tri->numIndexes * sizeof( tri->indexes[0] );
  1758. int allocatedIndexBytes = ALIGN( indexSize, 16 );
  1759. tri->indexes = (triIndex_t *)Mem_Alloc( allocatedIndexBytes, TAG_RENDER_TOOLS );
  1760. int vertexSize = tri->numVerts * sizeof( tri->verts[0] );
  1761. int allocatedVertexBytes = ALIGN( vertexSize, 16 );
  1762. tri->verts = (idDrawVert *)Mem_ClearedAlloc( allocatedVertexBytes, TAG_RENDER_TOOLS );
  1763. ALIGNTYPE16 triIndex_t tempIndexes[6] = { 3, 0, 2, 2, 0, 1 };
  1764. memcpy( tri->indexes, tempIndexes, indexSize );
  1765. idDrawVert* tempVerts = tri->verts;
  1766. tempVerts[0].xyz[0] = 0.0f;
  1767. tempVerts[0].xyz[1] = 0.0f;
  1768. tempVerts[0].xyz[2] = 0;
  1769. tempVerts[0].SetTexCoord( 0.0, 0.0f );
  1770. tempVerts[1].xyz[0] = 1.0f;
  1771. tempVerts[1].xyz[1] = 0.0f;
  1772. tempVerts[1].xyz[2] = 0;
  1773. tempVerts[1].SetTexCoord( 1.0f, 0.0f );
  1774. tempVerts[2].xyz[0] = 1.0f;
  1775. tempVerts[2].xyz[1] = 1.0f;
  1776. tempVerts[2].xyz[2] = 0;
  1777. tempVerts[2].SetTexCoord( 1.0f, 1.0f );
  1778. tempVerts[3].xyz[0] = 0.0f;
  1779. tempVerts[3].xyz[1] = 1.0f;
  1780. tempVerts[3].xyz[2] = 0;
  1781. tempVerts[3].SetTexCoord( 0.0f, 1.0f );
  1782. for ( int i = 0; i < 4; i++ ) {
  1783. tempVerts[i].SetColor( 0xFFFFFFFF );
  1784. }
  1785. return tri;
  1786. }
  1787. /*
  1788. ===============
  1789. idRenderSystemLocal::Init
  1790. ===============
  1791. */
  1792. void idRenderSystemLocal::Init() {
  1793. common->Printf( "------- Initializing renderSystem --------\n" );
  1794. // clear all our internal state
  1795. viewCount = 1; // so cleared structures never match viewCount
  1796. // we used to memset tr, but now that it is a class, we can't, so
  1797. // there may be other state we need to reset
  1798. ambientLightVector[0] = 0.5f;
  1799. ambientLightVector[1] = 0.5f - 0.385f;
  1800. ambientLightVector[2] = 0.8925f;
  1801. ambientLightVector[3] = 1.0f;
  1802. memset( &backEnd, 0, sizeof( backEnd ) );
  1803. R_InitCvars();
  1804. R_InitCommands();
  1805. guiModel = new (TAG_RENDER) idGuiModel;
  1806. guiModel->Clear();
  1807. tr_guiModel = guiModel; // for DeviceContext fast path
  1808. globalImages->Init();
  1809. idCinematic::InitCinematic( );
  1810. // build brightness translation tables
  1811. R_SetColorMappings();
  1812. R_InitMaterials();
  1813. renderModelManager->Init();
  1814. // set the identity space
  1815. identitySpace.modelMatrix[0*4+0] = 1.0f;
  1816. identitySpace.modelMatrix[1*4+1] = 1.0f;
  1817. identitySpace.modelMatrix[2*4+2] = 1.0f;
  1818. // make sure the tr.unitSquareTriangles data is current in the vertex / index cache
  1819. if ( unitSquareTriangles == NULL ) {
  1820. unitSquareTriangles = R_MakeFullScreenTris();
  1821. }
  1822. // make sure the tr.zeroOneCubeTriangles data is current in the vertex / index cache
  1823. if ( zeroOneCubeTriangles == NULL ) {
  1824. zeroOneCubeTriangles = R_MakeZeroOneCubeTris();
  1825. }
  1826. // make sure the tr.testImageTriangles data is current in the vertex / index cache
  1827. if ( testImageTriangles == NULL ) {
  1828. testImageTriangles = R_MakeTestImageTriangles();
  1829. }
  1830. frontEndJobList = parallelJobManager->AllocJobList( JOBLIST_RENDERER_FRONTEND, JOBLIST_PRIORITY_MEDIUM, 2048, 0, NULL );
  1831. // make sure the command buffers are ready to accept the first screen update
  1832. SwapCommandBuffers( NULL, NULL, NULL, NULL );
  1833. common->Printf( "renderSystem initialized.\n" );
  1834. common->Printf( "--------------------------------------\n" );
  1835. }
  1836. /*
  1837. ===============
  1838. idRenderSystemLocal::Shutdown
  1839. ===============
  1840. */
  1841. void idRenderSystemLocal::Shutdown() {
  1842. common->Printf( "idRenderSystem::Shutdown()\n" );
  1843. fonts.DeleteContents();
  1844. if ( R_IsInitialized() ) {
  1845. globalImages->PurgeAllImages();
  1846. }
  1847. renderModelManager->Shutdown();
  1848. idCinematic::ShutdownCinematic( );
  1849. globalImages->Shutdown();
  1850. // free frame memory
  1851. R_ShutdownFrameData();
  1852. UnbindBufferObjects();
  1853. // free the vertex cache, which should have nothing allocated now
  1854. vertexCache.Shutdown();
  1855. RB_ShutdownDebugTools();
  1856. delete guiModel;
  1857. parallelJobManager->FreeJobList( frontEndJobList );
  1858. Clear();
  1859. ShutdownOpenGL();
  1860. }
  1861. /*
  1862. ========================
  1863. idRenderSystemLocal::ResetGuiModels
  1864. ========================
  1865. */
  1866. void idRenderSystemLocal::ResetGuiModels() {
  1867. delete guiModel;
  1868. guiModel = new (TAG_RENDER) idGuiModel;
  1869. guiModel->Clear();
  1870. guiModel->BeginFrame();
  1871. tr_guiModel = guiModel; // for DeviceContext fast path
  1872. }
  1873. /*
  1874. ========================
  1875. idRenderSystemLocal::BeginLevelLoad
  1876. ========================
  1877. */
  1878. void idRenderSystemLocal::BeginLevelLoad() {
  1879. globalImages->BeginLevelLoad();
  1880. renderModelManager->BeginLevelLoad();
  1881. // Re-Initialize the Default Materials if needed.
  1882. R_InitMaterials();
  1883. }
  1884. /*
  1885. ========================
  1886. idRenderSystemLocal::LoadLevelImages
  1887. ========================
  1888. */
  1889. void idRenderSystemLocal::LoadLevelImages() {
  1890. globalImages->LoadLevelImages( false );
  1891. }
  1892. /*
  1893. ========================
  1894. idRenderSystemLocal::Preload
  1895. ========================
  1896. */
  1897. void idRenderSystemLocal::Preload( const idPreloadManifest &manifest, const char *mapName ) {
  1898. globalImages->Preload( manifest, true );
  1899. uiManager->Preload( mapName );
  1900. renderModelManager->Preload( manifest );
  1901. }
  1902. /*
  1903. ========================
  1904. idRenderSystemLocal::EndLevelLoad
  1905. ========================
  1906. */
  1907. void idRenderSystemLocal::EndLevelLoad() {
  1908. renderModelManager->EndLevelLoad();
  1909. globalImages->EndLevelLoad();
  1910. }
  1911. /*
  1912. ========================
  1913. idRenderSystemLocal::BeginAutomaticBackgroundSwaps
  1914. ========================
  1915. */
  1916. void idRenderSystemLocal::BeginAutomaticBackgroundSwaps( autoRenderIconType_t icon ) {
  1917. }
  1918. /*
  1919. ========================
  1920. idRenderSystemLocal::EndAutomaticBackgroundSwaps
  1921. ========================
  1922. */
  1923. void idRenderSystemLocal::EndAutomaticBackgroundSwaps() {
  1924. }
  1925. /*
  1926. ========================
  1927. idRenderSystemLocal::AreAutomaticBackgroundSwapsRunning
  1928. ========================
  1929. */
  1930. bool idRenderSystemLocal::AreAutomaticBackgroundSwapsRunning( autoRenderIconType_t * icon ) const {
  1931. return false;
  1932. }
  1933. /*
  1934. ============
  1935. idRenderSystemLocal::RegisterFont
  1936. ============
  1937. */
  1938. idFont * idRenderSystemLocal::RegisterFont( const char * fontName ) {
  1939. idStrStatic< MAX_OSPATH > baseFontName = fontName;
  1940. baseFontName.Replace( "fonts/", "" );
  1941. for ( int i = 0; i < fonts.Num(); i++ ) {
  1942. if ( idStr::Icmp( fonts[i]->GetName(), baseFontName ) == 0 ) {
  1943. fonts[i]->Touch();
  1944. return fonts[i];
  1945. }
  1946. }
  1947. idFont * newFont = new (TAG_FONT) idFont( baseFontName );
  1948. fonts.Append( newFont );
  1949. return newFont;
  1950. }
  1951. /*
  1952. ========================
  1953. idRenderSystemLocal::ResetFonts
  1954. ========================
  1955. */
  1956. void idRenderSystemLocal::ResetFonts() {
  1957. fonts.DeleteContents( true );
  1958. }
  1959. /*
  1960. ========================
  1961. idRenderSystemLocal::InitOpenGL
  1962. ========================
  1963. */
  1964. void idRenderSystemLocal::InitOpenGL() {
  1965. // if OpenGL isn't started, start it now
  1966. if ( !R_IsInitialized() ) {
  1967. R_InitOpenGL();
  1968. // Reloading images here causes the rendertargets to get deleted. Figure out how to handle this properly on 360
  1969. globalImages->ReloadImages( true );
  1970. int err = qglGetError();
  1971. if ( err != GL_NO_ERROR ) {
  1972. common->Printf( "glGetError() = 0x%x\n", err );
  1973. }
  1974. }
  1975. }
  1976. /*
  1977. ========================
  1978. idRenderSystemLocal::ShutdownOpenGL
  1979. ========================
  1980. */
  1981. void idRenderSystemLocal::ShutdownOpenGL() {
  1982. // free the context and close the window
  1983. R_ShutdownFrameData();
  1984. GLimp_Shutdown();
  1985. r_initialized = false;
  1986. }
  1987. /*
  1988. ========================
  1989. idRenderSystemLocal::IsOpenGLRunning
  1990. ========================
  1991. */
  1992. bool idRenderSystemLocal::IsOpenGLRunning() const {
  1993. return R_IsInitialized();
  1994. }
  1995. /*
  1996. ========================
  1997. idRenderSystemLocal::IsFullScreen
  1998. ========================
  1999. */
  2000. bool idRenderSystemLocal::IsFullScreen() const {
  2001. return glConfig.isFullscreen != 0;
  2002. }
  2003. /*
  2004. ========================
  2005. idRenderSystemLocal::GetWidth
  2006. ========================
  2007. */
  2008. int idRenderSystemLocal::GetWidth() const {
  2009. if ( glConfig.stereo3Dmode == STEREO3D_SIDE_BY_SIDE || glConfig.stereo3Dmode == STEREO3D_SIDE_BY_SIDE_COMPRESSED ) {
  2010. return glConfig.nativeScreenWidth >> 1;
  2011. }
  2012. return glConfig.nativeScreenWidth;
  2013. }
  2014. /*
  2015. ========================
  2016. idRenderSystemLocal::GetHeight
  2017. ========================
  2018. */
  2019. int idRenderSystemLocal::GetHeight() const {
  2020. if ( glConfig.stereo3Dmode == STEREO3D_HDMI_720 ) {
  2021. return 720;
  2022. }
  2023. extern idCVar stereoRender_warp;
  2024. if ( glConfig.stereo3Dmode == STEREO3D_SIDE_BY_SIDE && stereoRender_warp.GetBool() ) {
  2025. // for the Rift, render a square aspect view that will be symetric for the optics
  2026. return glConfig.nativeScreenWidth >> 1;
  2027. }
  2028. if ( glConfig.stereo3Dmode == STEREO3D_INTERLACED || glConfig.stereo3Dmode == STEREO3D_TOP_AND_BOTTOM_COMPRESSED ) {
  2029. return glConfig.nativeScreenHeight >> 1;
  2030. }
  2031. return glConfig.nativeScreenHeight;
  2032. }
  2033. /*
  2034. ========================
  2035. idRenderSystemLocal::GetStereo3DMode
  2036. ========================
  2037. */
  2038. stereo3DMode_t idRenderSystemLocal::GetStereo3DMode() const {
  2039. return glConfig.stereo3Dmode;
  2040. }
  2041. /*
  2042. ========================
  2043. idRenderSystemLocal::IsStereoScopicRenderingSupported
  2044. ========================
  2045. */
  2046. bool idRenderSystemLocal::IsStereoScopicRenderingSupported() const {
  2047. return true;
  2048. }
  2049. /*
  2050. ========================
  2051. idRenderSystemLocal::HasQuadBufferSupport
  2052. ========================
  2053. */
  2054. bool idRenderSystemLocal::HasQuadBufferSupport() const {
  2055. return glConfig.stereoPixelFormatAvailable;
  2056. }
  2057. /*
  2058. ========================
  2059. idRenderSystemLocal::GetStereoScopicRenderingMode
  2060. ========================
  2061. */
  2062. stereo3DMode_t idRenderSystemLocal::GetStereoScopicRenderingMode() const {
  2063. return ( !IsStereoScopicRenderingSupported() ) ? STEREO3D_OFF : (stereo3DMode_t)stereoRender_enable.GetInteger();
  2064. }
  2065. /*
  2066. ========================
  2067. idRenderSystemLocal::IsStereoScopicRenderingSupported
  2068. ========================
  2069. */
  2070. void idRenderSystemLocal::EnableStereoScopicRendering( const stereo3DMode_t mode ) const {
  2071. stereoRender_enable.SetInteger( mode );
  2072. }
  2073. /*
  2074. ========================
  2075. idRenderSystemLocal::GetPixelAspect
  2076. ========================
  2077. */
  2078. float idRenderSystemLocal::GetPixelAspect() const {
  2079. switch( glConfig.stereo3Dmode ) {
  2080. case STEREO3D_SIDE_BY_SIDE_COMPRESSED:
  2081. return glConfig.pixelAspect * 2.0f;
  2082. case STEREO3D_TOP_AND_BOTTOM_COMPRESSED:
  2083. case STEREO3D_INTERLACED:
  2084. return glConfig.pixelAspect * 0.5f;
  2085. default:
  2086. return glConfig.pixelAspect;
  2087. }
  2088. }
  2089. /*
  2090. ========================
  2091. idRenderSystemLocal::GetPhysicalScreenWidthInCentimeters
  2092. This is used to calculate stereoscopic screen offset for a given interocular distance.
  2093. ========================
  2094. */
  2095. idCVar r_forceScreenWidthCentimeters( "r_forceScreenWidthCentimeters", "0", CVAR_RENDERER | CVAR_ARCHIVE, "Override screen width returned by hardware" );
  2096. float idRenderSystemLocal::GetPhysicalScreenWidthInCentimeters() const {
  2097. if ( r_forceScreenWidthCentimeters.GetFloat() > 0 ) {
  2098. return r_forceScreenWidthCentimeters.GetFloat();
  2099. }
  2100. return glConfig.physicalScreenWidthInCentimeters;
  2101. }