SoftwareGLContext.cpp 124 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349
  1. /*
  2. * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
  3. * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include <AK/Assertions.h>
  8. #include <AK/Debug.h>
  9. #include <AK/Format.h>
  10. #include <AK/QuickSort.h>
  11. #include <AK/TemporaryChange.h>
  12. #include <AK/Variant.h>
  13. #include <AK/Vector.h>
  14. #include <LibGL/SoftwareGLContext.h>
  15. #include <LibGfx/Bitmap.h>
  16. #include <LibGfx/Painter.h>
  17. #include <LibGfx/Vector4.h>
  18. #include <LibSoftGPU/Device.h>
  19. using AK::dbgln;
  20. namespace GL {
  21. static constexpr size_t MODELVIEW_MATRIX_STACK_LIMIT = 64;
  22. static constexpr size_t PROJECTION_MATRIX_STACK_LIMIT = 8;
  23. static constexpr size_t TEXTURE_MATRIX_STACK_LIMIT = 8;
  24. #define APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(name, ...) \
  25. if (should_append_to_listing()) { \
  26. append_to_listing<&SoftwareGLContext::name>(__VA_ARGS__); \
  27. if (!should_execute_after_appending_to_listing()) \
  28. return; \
  29. }
  30. #define APPEND_TO_CALL_LIST_WITH_ARG_AND_RETURN_IF_NEEDED(name, arg) \
  31. if (should_append_to_listing()) { \
  32. auto ptr = store_in_listing(arg); \
  33. append_to_listing<&SoftwareGLContext::name>(*ptr); \
  34. if (!should_execute_after_appending_to_listing()) \
  35. return; \
  36. }
  37. #define RETURN_WITH_ERROR_IF(condition, error) \
  38. if (condition) { \
  39. if (m_error == GL_NO_ERROR) \
  40. m_error = error; \
  41. return; \
  42. }
  43. #define RETURN_VALUE_WITH_ERROR_IF(condition, error, return_value) \
  44. if (condition) { \
  45. if (m_error == GL_NO_ERROR) \
  46. m_error = error; \
  47. return return_value; \
  48. }
  49. SoftwareGLContext::SoftwareGLContext(Gfx::Bitmap& frontbuffer)
  50. : m_viewport(frontbuffer.rect())
  51. , m_frontbuffer(frontbuffer)
  52. , m_rasterizer(frontbuffer.size())
  53. , m_device_info(m_rasterizer.info())
  54. {
  55. m_texture_units.resize(m_device_info.num_texture_units);
  56. m_active_texture_unit = &m_texture_units[0];
  57. // Query the number lights from the device and set set up their state
  58. // locally in the GL
  59. m_light_states.resize(m_device_info.num_lights);
  60. // Set-up light0's state, as it has a different default state
  61. // to the other lights, as per the OpenGL 1.5 spec
  62. auto& light0 = m_light_states.at(0);
  63. light0.diffuse_intensity = { 1.0f, 1.0f, 1.0f, 1.0f };
  64. light0.specular_intensity = { 1.0f, 1.0f, 1.0f, 1.0f };
  65. m_light_state_is_dirty = true;
  66. }
  67. Optional<ContextParameter> SoftwareGLContext::get_context_parameter(GLenum name)
  68. {
  69. switch (name) {
  70. case GL_ALPHA_BITS:
  71. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  72. case GL_ALPHA_TEST:
  73. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_alpha_test_enabled } };
  74. case GL_BLEND:
  75. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_blend_enabled } };
  76. case GL_BLEND_DST_ALPHA:
  77. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_destination_factor) } };
  78. case GL_BLEND_SRC_ALPHA:
  79. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_source_factor) } };
  80. case GL_BLUE_BITS:
  81. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  82. case GL_COLOR_MATERIAL:
  83. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_color_material_enabled } };
  84. case GL_COLOR_MATERIAL_FACE:
  85. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_color_material_face) } };
  86. case GL_COLOR_MATERIAL_MODE:
  87. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_color_material_mode) } };
  88. case GL_CULL_FACE:
  89. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_cull_faces } };
  90. case GL_DEPTH_BITS:
  91. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  92. case GL_DEPTH_TEST:
  93. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_depth_test_enabled } };
  94. case GL_DITHER:
  95. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_dither_enabled } };
  96. case GL_DOUBLEBUFFER:
  97. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = true } };
  98. case GL_FOG: {
  99. auto fog_enabled = m_rasterizer.options().fog_enabled;
  100. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = fog_enabled } };
  101. }
  102. case GL_GREEN_BITS:
  103. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  104. case GL_LIGHTING:
  105. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_lighting_enabled } };
  106. case GL_MAX_LIGHTS:
  107. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_device_info.num_lights) } };
  108. case GL_MAX_MODELVIEW_STACK_DEPTH:
  109. return ContextParameter { .type = GL_INT, .value = { .integer_value = MODELVIEW_MATRIX_STACK_LIMIT } };
  110. case GL_MAX_PROJECTION_STACK_DEPTH:
  111. return ContextParameter { .type = GL_INT, .value = { .integer_value = PROJECTION_MATRIX_STACK_LIMIT } };
  112. case GL_MAX_TEXTURE_SIZE:
  113. return ContextParameter { .type = GL_INT, .value = { .integer_value = 4096 } };
  114. case GL_MAX_TEXTURE_STACK_DEPTH:
  115. return ContextParameter { .type = GL_INT, .value = { .integer_value = TEXTURE_MATRIX_STACK_LIMIT } };
  116. case GL_MAX_TEXTURE_UNITS:
  117. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_texture_units.size()) } };
  118. case GL_NORMALIZE:
  119. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_normalize } };
  120. case GL_PACK_ALIGNMENT:
  121. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_pack_alignment } };
  122. case GL_PACK_IMAGE_HEIGHT:
  123. return ContextParameter { .type = GL_BOOL, .value = { .integer_value = 0 } };
  124. case GL_PACK_LSB_FIRST:
  125. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = false } };
  126. case GL_PACK_ROW_LENGTH:
  127. return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
  128. case GL_PACK_SKIP_PIXELS:
  129. return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
  130. case GL_PACK_SKIP_ROWS:
  131. return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
  132. case GL_PACK_SWAP_BYTES:
  133. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = false } };
  134. case GL_RED_BITS:
  135. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  136. case GL_SCISSOR_BOX: {
  137. auto scissor_box = m_rasterizer.options().scissor_box;
  138. return ContextParameter {
  139. .type = GL_INT,
  140. .count = 4,
  141. .value = {
  142. .integer_list = {
  143. scissor_box.x(),
  144. scissor_box.y(),
  145. scissor_box.width(),
  146. scissor_box.height(),
  147. } }
  148. };
  149. } break;
  150. case GL_SCISSOR_TEST: {
  151. auto scissor_enabled = m_rasterizer.options().scissor_enabled;
  152. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = scissor_enabled } };
  153. }
  154. case GL_STENCIL_BITS:
  155. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  156. case GL_STENCIL_TEST:
  157. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_stencil_test_enabled } };
  158. case GL_TEXTURE_1D:
  159. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_1d_enabled() } };
  160. case GL_TEXTURE_2D:
  161. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_2d_enabled() } };
  162. case GL_TEXTURE_3D:
  163. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_3d_enabled() } };
  164. case GL_TEXTURE_CUBE_MAP:
  165. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_cube_map_enabled() } };
  166. case GL_TEXTURE_GEN_Q:
  167. case GL_TEXTURE_GEN_R:
  168. case GL_TEXTURE_GEN_S:
  169. case GL_TEXTURE_GEN_T: {
  170. auto generation_enabled = texture_coordinate_generation(name).enabled;
  171. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = generation_enabled } };
  172. }
  173. case GL_UNPACK_ALIGNMENT:
  174. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpack_alignment } };
  175. case GL_UNPACK_IMAGE_HEIGHT:
  176. return ContextParameter { .type = GL_BOOL, .value = { .integer_value = 0 } };
  177. case GL_UNPACK_LSB_FIRST:
  178. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = false } };
  179. case GL_UNPACK_ROW_LENGTH:
  180. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpack_row_length } };
  181. case GL_UNPACK_SKIP_PIXELS:
  182. return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
  183. case GL_UNPACK_SKIP_ROWS:
  184. return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
  185. case GL_UNPACK_SWAP_BYTES:
  186. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = false } };
  187. case GL_VIEWPORT:
  188. return ContextParameter {
  189. .type = GL_INT,
  190. .count = 4,
  191. .value = {
  192. .integer_list = {
  193. m_viewport.x(),
  194. m_viewport.y(),
  195. m_viewport.width(),
  196. m_viewport.height(),
  197. } }
  198. };
  199. default:
  200. dbgln_if(GL_DEBUG, "get_context_parameter({:#x}): unknown context parameter", name);
  201. return {};
  202. }
  203. }
  204. void SoftwareGLContext::gl_begin(GLenum mode)
  205. {
  206. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_begin, mode);
  207. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  208. RETURN_WITH_ERROR_IF(mode < GL_TRIANGLES || mode > GL_POLYGON, GL_INVALID_ENUM);
  209. m_current_draw_mode = mode;
  210. m_in_draw_state = true; // Certain commands will now generate an error
  211. }
  212. void SoftwareGLContext::gl_clear(GLbitfield mask)
  213. {
  214. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_clear, mask);
  215. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  216. RETURN_WITH_ERROR_IF(mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT), GL_INVALID_ENUM);
  217. if (mask & GL_COLOR_BUFFER_BIT)
  218. m_rasterizer.clear_color(m_clear_color);
  219. if (mask & GL_DEPTH_BUFFER_BIT)
  220. m_rasterizer.clear_depth(static_cast<float>(m_clear_depth));
  221. // FIXME: implement GL_STENCIL_BUFFER_BIT
  222. if (mask & GL_STENCIL_BUFFER_BIT)
  223. dbgln_if(GL_DEBUG, "gl_clear(): GL_STENCIL_BUFFER_BIT is unimplemented");
  224. }
  225. void SoftwareGLContext::gl_clear_color(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
  226. {
  227. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_clear_color, red, green, blue, alpha);
  228. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  229. m_clear_color = { red, green, blue, alpha };
  230. }
  231. void SoftwareGLContext::gl_clear_depth(GLdouble depth)
  232. {
  233. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_clear_depth, depth);
  234. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  235. m_clear_depth = depth;
  236. }
  237. void SoftwareGLContext::gl_clear_stencil(GLint s)
  238. {
  239. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_clear_stencil, s);
  240. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  241. // FIXME: "s is masked with 2^m - 1 , where m is the number of bits in the stencil buffer"
  242. m_clear_stencil = s;
  243. }
  244. void SoftwareGLContext::gl_color(GLdouble r, GLdouble g, GLdouble b, GLdouble a)
  245. {
  246. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_color, r, g, b, a);
  247. m_current_vertex_color = {
  248. static_cast<float>(r),
  249. static_cast<float>(g),
  250. static_cast<float>(b),
  251. static_cast<float>(a),
  252. };
  253. }
  254. void SoftwareGLContext::gl_end()
  255. {
  256. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_end);
  257. // Make sure we had a `glBegin` before this call...
  258. RETURN_WITH_ERROR_IF(!m_in_draw_state, GL_INVALID_OPERATION);
  259. m_in_draw_state = false;
  260. // FIXME: Add support for the remaining primitive types.
  261. if (m_current_draw_mode != GL_TRIANGLES
  262. && m_current_draw_mode != GL_TRIANGLE_FAN
  263. && m_current_draw_mode != GL_TRIANGLE_STRIP
  264. && m_current_draw_mode != GL_QUADS
  265. && m_current_draw_mode != GL_QUAD_STRIP
  266. && m_current_draw_mode != GL_POLYGON) {
  267. m_vertex_list.clear_with_capacity();
  268. dbgln_if(GL_DEBUG, "gl_end: draw mode {:#x} unsupported", m_current_draw_mode);
  269. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  270. }
  271. Vector<size_t, 32> enabled_texture_units;
  272. for (size_t i = 0; i < m_texture_units.size(); ++i) {
  273. if (m_texture_units[i].texture_2d_enabled())
  274. enabled_texture_units.append(i);
  275. }
  276. sync_device_config();
  277. SoftGPU::PrimitiveType primitive_type;
  278. switch (m_current_draw_mode) {
  279. case GL_TRIANGLES:
  280. primitive_type = SoftGPU::PrimitiveType::Triangles;
  281. break;
  282. case GL_TRIANGLE_STRIP:
  283. case GL_QUAD_STRIP:
  284. primitive_type = SoftGPU::PrimitiveType::TriangleStrip;
  285. break;
  286. case GL_TRIANGLE_FAN:
  287. case GL_POLYGON:
  288. primitive_type = SoftGPU::PrimitiveType::TriangleFan;
  289. break;
  290. case GL_QUADS:
  291. primitive_type = SoftGPU::PrimitiveType::Quads;
  292. break;
  293. default:
  294. VERIFY_NOT_REACHED();
  295. }
  296. // Set up normals transform by taking the upper left 3x3 elements from the model view matrix
  297. // See section 2.11.3 of the OpenGL 1.5 spec
  298. auto const& mv_elements = m_model_view_matrix.elements();
  299. auto const model_view_transposed = FloatMatrix3x3(
  300. mv_elements[0][0], mv_elements[1][0], mv_elements[2][0],
  301. mv_elements[0][1], mv_elements[1][1], mv_elements[2][1],
  302. mv_elements[0][2], mv_elements[1][2], mv_elements[2][2]);
  303. auto const& normal_transform = model_view_transposed.inverse();
  304. m_rasterizer.draw_primitives(primitive_type, m_model_view_matrix, normal_transform, m_projection_matrix, m_texture_matrix, m_vertex_list, enabled_texture_units);
  305. m_vertex_list.clear_with_capacity();
  306. }
  307. void SoftwareGLContext::gl_frustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val)
  308. {
  309. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_frustum, left, right, bottom, top, near_val, far_val);
  310. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  311. // Let's do some math!
  312. // FIXME: Are we losing too much precision by doing this?
  313. float a = static_cast<float>((right + left) / (right - left));
  314. float b = static_cast<float>((top + bottom) / (top - bottom));
  315. float c = static_cast<float>(-((far_val + near_val) / (far_val - near_val)));
  316. float d = static_cast<float>(-((2 * (far_val * near_val)) / (far_val - near_val)));
  317. FloatMatrix4x4 frustum {
  318. ((2 * (float)near_val) / ((float)right - (float)left)), 0, a, 0,
  319. 0, ((2 * (float)near_val) / ((float)top - (float)bottom)), b, 0,
  320. 0, 0, c, d,
  321. 0, 0, -1, 0
  322. };
  323. if (m_current_matrix_mode == GL_PROJECTION)
  324. m_projection_matrix = m_projection_matrix * frustum;
  325. else if (m_current_matrix_mode == GL_MODELVIEW)
  326. m_projection_matrix = m_model_view_matrix * frustum;
  327. else if (m_current_matrix_mode == GL_TEXTURE)
  328. m_texture_matrix = m_texture_matrix * frustum;
  329. else
  330. VERIFY_NOT_REACHED();
  331. }
  332. void SoftwareGLContext::gl_ortho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val)
  333. {
  334. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_ortho, left, right, bottom, top, near_val, far_val);
  335. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  336. RETURN_WITH_ERROR_IF(left == right || bottom == top || near_val == far_val, GL_INVALID_VALUE);
  337. auto rl = right - left;
  338. auto tb = top - bottom;
  339. auto fn = far_val - near_val;
  340. auto tx = -(right + left) / rl;
  341. auto ty = -(top + bottom) / tb;
  342. auto tz = -(far_val + near_val) / fn;
  343. FloatMatrix4x4 projection {
  344. static_cast<float>(2 / rl), 0, 0, static_cast<float>(tx),
  345. 0, static_cast<float>(2 / tb), 0, static_cast<float>(ty),
  346. 0, 0, static_cast<float>(-2 / fn), static_cast<float>(tz),
  347. 0, 0, 0, 1
  348. };
  349. if (m_current_matrix_mode == GL_PROJECTION)
  350. m_projection_matrix = m_projection_matrix * projection;
  351. else if (m_current_matrix_mode == GL_MODELVIEW)
  352. m_projection_matrix = m_model_view_matrix * projection;
  353. else if (m_current_matrix_mode == GL_TEXTURE)
  354. m_texture_matrix = m_texture_matrix * projection;
  355. else
  356. VERIFY_NOT_REACHED();
  357. }
  358. GLenum SoftwareGLContext::gl_get_error()
  359. {
  360. if (m_in_draw_state)
  361. return GL_INVALID_OPERATION;
  362. auto last_error = m_error;
  363. m_error = GL_NO_ERROR;
  364. return last_error;
  365. }
  366. GLubyte* SoftwareGLContext::gl_get_string(GLenum name)
  367. {
  368. RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, nullptr);
  369. switch (name) {
  370. case GL_VENDOR:
  371. return reinterpret_cast<GLubyte*>(const_cast<char*>(m_device_info.vendor_name.characters()));
  372. case GL_RENDERER:
  373. return reinterpret_cast<GLubyte*>(const_cast<char*>(m_device_info.device_name.characters()));
  374. case GL_VERSION:
  375. return reinterpret_cast<GLubyte*>(const_cast<char*>("1.5"));
  376. case GL_EXTENSIONS:
  377. return reinterpret_cast<GLubyte*>(const_cast<char*>(""));
  378. case GL_SHADING_LANGUAGE_VERSION:
  379. return reinterpret_cast<GLubyte*>(const_cast<char*>("0.0"));
  380. default:
  381. dbgln_if(GL_DEBUG, "gl_get_string({:#x}): unknown name", name);
  382. break;
  383. }
  384. RETURN_VALUE_WITH_ERROR_IF(true, GL_INVALID_ENUM, nullptr);
  385. }
  386. void SoftwareGLContext::gl_load_identity()
  387. {
  388. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_load_identity);
  389. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  390. if (m_current_matrix_mode == GL_PROJECTION)
  391. m_projection_matrix = FloatMatrix4x4::identity();
  392. else if (m_current_matrix_mode == GL_MODELVIEW)
  393. m_model_view_matrix = FloatMatrix4x4::identity();
  394. else if (m_current_matrix_mode == GL_TEXTURE)
  395. m_texture_matrix = FloatMatrix4x4::identity();
  396. else
  397. VERIFY_NOT_REACHED();
  398. }
  399. void SoftwareGLContext::gl_load_matrix(const FloatMatrix4x4& matrix)
  400. {
  401. APPEND_TO_CALL_LIST_WITH_ARG_AND_RETURN_IF_NEEDED(gl_load_matrix, matrix);
  402. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  403. if (m_current_matrix_mode == GL_PROJECTION)
  404. m_projection_matrix = matrix;
  405. else if (m_current_matrix_mode == GL_MODELVIEW)
  406. m_model_view_matrix = matrix;
  407. else if (m_current_matrix_mode == GL_TEXTURE)
  408. m_texture_matrix = matrix;
  409. else
  410. VERIFY_NOT_REACHED();
  411. }
  412. void SoftwareGLContext::gl_matrix_mode(GLenum mode)
  413. {
  414. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_matrix_mode, mode);
  415. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  416. RETURN_WITH_ERROR_IF(mode < GL_MODELVIEW || mode > GL_TEXTURE, GL_INVALID_ENUM);
  417. m_current_matrix_mode = mode;
  418. }
  419. void SoftwareGLContext::gl_push_matrix()
  420. {
  421. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_push_matrix);
  422. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  423. switch (m_current_matrix_mode) {
  424. case GL_PROJECTION:
  425. RETURN_WITH_ERROR_IF(m_projection_matrix_stack.size() >= PROJECTION_MATRIX_STACK_LIMIT, GL_STACK_OVERFLOW);
  426. m_projection_matrix_stack.append(m_projection_matrix);
  427. break;
  428. case GL_MODELVIEW:
  429. RETURN_WITH_ERROR_IF(m_model_view_matrix_stack.size() >= MODELVIEW_MATRIX_STACK_LIMIT, GL_STACK_OVERFLOW);
  430. m_model_view_matrix_stack.append(m_model_view_matrix);
  431. break;
  432. case GL_TEXTURE:
  433. RETURN_WITH_ERROR_IF(m_texture_matrix_stack.size() >= TEXTURE_MATRIX_STACK_LIMIT, GL_STACK_OVERFLOW);
  434. m_texture_matrix_stack.append(m_texture_matrix);
  435. break;
  436. default:
  437. VERIFY_NOT_REACHED();
  438. }
  439. }
  440. void SoftwareGLContext::gl_pop_matrix()
  441. {
  442. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_pop_matrix);
  443. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  444. switch (m_current_matrix_mode) {
  445. case GL_PROJECTION:
  446. RETURN_WITH_ERROR_IF(m_projection_matrix_stack.size() == 0, GL_STACK_UNDERFLOW);
  447. m_projection_matrix = m_projection_matrix_stack.take_last();
  448. break;
  449. case GL_MODELVIEW:
  450. RETURN_WITH_ERROR_IF(m_model_view_matrix_stack.size() == 0, GL_STACK_UNDERFLOW);
  451. m_model_view_matrix = m_model_view_matrix_stack.take_last();
  452. break;
  453. case GL_TEXTURE:
  454. RETURN_WITH_ERROR_IF(m_texture_matrix_stack.size() == 0, GL_STACK_UNDERFLOW);
  455. m_texture_matrix = m_texture_matrix_stack.take_last();
  456. break;
  457. default:
  458. VERIFY_NOT_REACHED();
  459. }
  460. }
  461. void SoftwareGLContext::gl_mult_matrix(FloatMatrix4x4 const& matrix)
  462. {
  463. APPEND_TO_CALL_LIST_WITH_ARG_AND_RETURN_IF_NEEDED(gl_mult_matrix, matrix);
  464. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  465. if (m_current_matrix_mode == GL_MODELVIEW)
  466. m_model_view_matrix = m_model_view_matrix * matrix;
  467. else if (m_current_matrix_mode == GL_PROJECTION)
  468. m_projection_matrix = m_projection_matrix * matrix;
  469. else if (m_current_matrix_mode == GL_TEXTURE)
  470. m_texture_matrix = m_texture_matrix * matrix;
  471. else
  472. VERIFY_NOT_REACHED();
  473. }
  474. void SoftwareGLContext::gl_rotate(GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
  475. {
  476. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_rotate, angle, x, y, z);
  477. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  478. FloatVector3 axis = { (float)x, (float)y, (float)z };
  479. axis.normalize();
  480. auto rotation_mat = Gfx::rotation_matrix(axis, static_cast<float>(angle * M_PI * 2 / 360));
  481. if (m_current_matrix_mode == GL_MODELVIEW)
  482. m_model_view_matrix = m_model_view_matrix * rotation_mat;
  483. else if (m_current_matrix_mode == GL_PROJECTION)
  484. m_projection_matrix = m_projection_matrix * rotation_mat;
  485. else if (m_current_matrix_mode == GL_TEXTURE)
  486. m_texture_matrix = m_texture_matrix * rotation_mat;
  487. else
  488. VERIFY_NOT_REACHED();
  489. }
  490. void SoftwareGLContext::gl_scale(GLdouble x, GLdouble y, GLdouble z)
  491. {
  492. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_scale, x, y, z);
  493. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  494. auto scale_matrix = Gfx::scale_matrix(FloatVector3 { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z) });
  495. if (m_current_matrix_mode == GL_MODELVIEW)
  496. m_model_view_matrix = m_model_view_matrix * scale_matrix;
  497. else if (m_current_matrix_mode == GL_PROJECTION)
  498. m_projection_matrix = m_projection_matrix * scale_matrix;
  499. else if (m_current_matrix_mode == GL_TEXTURE)
  500. m_texture_matrix = m_texture_matrix * scale_matrix;
  501. else
  502. VERIFY_NOT_REACHED();
  503. }
  504. void SoftwareGLContext::gl_translate(GLdouble x, GLdouble y, GLdouble z)
  505. {
  506. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_translate, x, y, z);
  507. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  508. auto translation_matrix = Gfx::translation_matrix(FloatVector3 { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z) });
  509. if (m_current_matrix_mode == GL_MODELVIEW)
  510. m_model_view_matrix = m_model_view_matrix * translation_matrix;
  511. else if (m_current_matrix_mode == GL_PROJECTION)
  512. m_projection_matrix = m_projection_matrix * translation_matrix;
  513. else if (m_current_matrix_mode == GL_TEXTURE)
  514. m_texture_matrix = m_texture_matrix * translation_matrix;
  515. else
  516. VERIFY_NOT_REACHED();
  517. }
  518. void SoftwareGLContext::gl_vertex(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
  519. {
  520. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_vertex, x, y, z, w);
  521. SoftGPU::Vertex vertex;
  522. vertex.position = { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(w) };
  523. vertex.color = m_current_vertex_color;
  524. vertex.tex_coord = m_current_vertex_tex_coord;
  525. vertex.normal = m_current_vertex_normal;
  526. m_vertex_list.append(vertex);
  527. }
  528. // FIXME: We need to add `r` and `q` to our GLVertex?!
  529. void SoftwareGLContext::gl_tex_coord(GLfloat s, GLfloat t, GLfloat r, GLfloat q)
  530. {
  531. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_tex_coord, s, t, r, q);
  532. m_current_vertex_tex_coord = { s, t, r, q };
  533. }
  534. void SoftwareGLContext::gl_viewport(GLint x, GLint y, GLsizei width, GLsizei height)
  535. {
  536. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_viewport, x, y, width, height);
  537. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  538. RETURN_WITH_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
  539. m_viewport = { x, y, width, height };
  540. auto rasterizer_options = m_rasterizer.options();
  541. rasterizer_options.viewport = m_viewport;
  542. m_rasterizer.set_options(rasterizer_options);
  543. }
  544. void SoftwareGLContext::gl_enable(GLenum capability)
  545. {
  546. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_enable, capability);
  547. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  548. auto rasterizer_options = m_rasterizer.options();
  549. bool update_rasterizer_options = false;
  550. switch (capability) {
  551. case GL_COLOR_MATERIAL:
  552. m_color_material_enabled = true;
  553. break;
  554. case GL_CULL_FACE:
  555. m_cull_faces = true;
  556. rasterizer_options.enable_culling = true;
  557. update_rasterizer_options = true;
  558. break;
  559. case GL_DEPTH_TEST:
  560. m_depth_test_enabled = true;
  561. rasterizer_options.enable_depth_test = true;
  562. update_rasterizer_options = true;
  563. break;
  564. case GL_BLEND:
  565. m_blend_enabled = true;
  566. rasterizer_options.enable_blending = true;
  567. update_rasterizer_options = true;
  568. break;
  569. case GL_ALPHA_TEST:
  570. m_alpha_test_enabled = true;
  571. rasterizer_options.enable_alpha_test = true;
  572. update_rasterizer_options = true;
  573. break;
  574. case GL_DITHER:
  575. m_dither_enabled = true;
  576. break;
  577. case GL_FOG:
  578. rasterizer_options.fog_enabled = true;
  579. update_rasterizer_options = true;
  580. break;
  581. case GL_LIGHTING:
  582. m_lighting_enabled = true;
  583. rasterizer_options.lighting_enabled = true;
  584. update_rasterizer_options = true;
  585. break;
  586. case GL_NORMALIZE:
  587. m_normalize = true;
  588. rasterizer_options.normalization_enabled = true;
  589. update_rasterizer_options = true;
  590. break;
  591. case GL_SCISSOR_TEST:
  592. rasterizer_options.scissor_enabled = true;
  593. update_rasterizer_options = true;
  594. break;
  595. case GL_STENCIL_TEST:
  596. m_stencil_test_enabled = true;
  597. break;
  598. case GL_TEXTURE_1D:
  599. m_active_texture_unit->set_texture_1d_enabled(true);
  600. m_sampler_config_is_dirty = true;
  601. break;
  602. case GL_TEXTURE_2D:
  603. m_active_texture_unit->set_texture_2d_enabled(true);
  604. m_sampler_config_is_dirty = true;
  605. break;
  606. case GL_TEXTURE_3D:
  607. m_active_texture_unit->set_texture_3d_enabled(true);
  608. m_sampler_config_is_dirty = true;
  609. break;
  610. case GL_TEXTURE_CUBE_MAP:
  611. m_active_texture_unit->set_texture_cube_map_enabled(true);
  612. m_sampler_config_is_dirty = true;
  613. break;
  614. case GL_LIGHT0:
  615. case GL_LIGHT1:
  616. case GL_LIGHT2:
  617. case GL_LIGHT3:
  618. case GL_LIGHT4:
  619. case GL_LIGHT5:
  620. case GL_LIGHT6:
  621. case GL_LIGHT7:
  622. m_light_states.at(capability - GL_LIGHT0).is_enabled = true;
  623. m_light_state_is_dirty = true;
  624. break;
  625. case GL_TEXTURE_GEN_Q:
  626. case GL_TEXTURE_GEN_R:
  627. case GL_TEXTURE_GEN_S:
  628. case GL_TEXTURE_GEN_T:
  629. texture_coordinate_generation(capability).enabled = true;
  630. m_texcoord_generation_dirty = true;
  631. break;
  632. default:
  633. dbgln_if(GL_DEBUG, "gl_enable({:#x}): unknown parameter", capability);
  634. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  635. }
  636. if (update_rasterizer_options)
  637. m_rasterizer.set_options(rasterizer_options);
  638. }
  639. void SoftwareGLContext::gl_disable(GLenum capability)
  640. {
  641. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_disable, capability);
  642. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  643. auto rasterizer_options = m_rasterizer.options();
  644. bool update_rasterizer_options = false;
  645. switch (capability) {
  646. case GL_COLOR_MATERIAL:
  647. m_color_material_enabled = false;
  648. break;
  649. case GL_CULL_FACE:
  650. m_cull_faces = false;
  651. rasterizer_options.enable_culling = false;
  652. update_rasterizer_options = true;
  653. break;
  654. case GL_DEPTH_TEST:
  655. m_depth_test_enabled = false;
  656. rasterizer_options.enable_depth_test = false;
  657. update_rasterizer_options = true;
  658. break;
  659. case GL_BLEND:
  660. m_blend_enabled = false;
  661. rasterizer_options.enable_blending = false;
  662. update_rasterizer_options = true;
  663. break;
  664. case GL_ALPHA_TEST:
  665. m_alpha_test_enabled = false;
  666. rasterizer_options.enable_alpha_test = false;
  667. update_rasterizer_options = true;
  668. break;
  669. case GL_DITHER:
  670. m_dither_enabled = false;
  671. break;
  672. case GL_FOG:
  673. rasterizer_options.fog_enabled = false;
  674. update_rasterizer_options = true;
  675. break;
  676. case GL_LIGHTING:
  677. m_lighting_enabled = false;
  678. rasterizer_options.lighting_enabled = false;
  679. update_rasterizer_options = true;
  680. break;
  681. case GL_LIGHT0:
  682. case GL_LIGHT1:
  683. case GL_LIGHT2:
  684. case GL_LIGHT3:
  685. case GL_LIGHT4:
  686. case GL_LIGHT5:
  687. case GL_LIGHT6:
  688. case GL_LIGHT7:
  689. m_light_states.at(capability - GL_LIGHT0).is_enabled = false;
  690. m_light_state_is_dirty = true;
  691. break;
  692. case GL_NORMALIZE:
  693. m_normalize = false;
  694. rasterizer_options.normalization_enabled = false;
  695. update_rasterizer_options = true;
  696. break;
  697. case GL_SCISSOR_TEST:
  698. rasterizer_options.scissor_enabled = false;
  699. update_rasterizer_options = true;
  700. break;
  701. case GL_STENCIL_TEST:
  702. m_stencil_test_enabled = false;
  703. break;
  704. case GL_TEXTURE_1D:
  705. m_active_texture_unit->set_texture_1d_enabled(false);
  706. m_sampler_config_is_dirty = true;
  707. break;
  708. case GL_TEXTURE_2D:
  709. m_active_texture_unit->set_texture_2d_enabled(false);
  710. m_sampler_config_is_dirty = true;
  711. break;
  712. case GL_TEXTURE_3D:
  713. m_active_texture_unit->set_texture_3d_enabled(false);
  714. m_sampler_config_is_dirty = true;
  715. break;
  716. case GL_TEXTURE_CUBE_MAP:
  717. m_active_texture_unit->set_texture_cube_map_enabled(false);
  718. m_sampler_config_is_dirty = true;
  719. break;
  720. case GL_TEXTURE_GEN_Q:
  721. case GL_TEXTURE_GEN_R:
  722. case GL_TEXTURE_GEN_S:
  723. case GL_TEXTURE_GEN_T:
  724. texture_coordinate_generation(capability).enabled = false;
  725. m_texcoord_generation_dirty = true;
  726. break;
  727. default:
  728. dbgln_if(GL_DEBUG, "gl_disable({:#x}): unknown parameter", capability);
  729. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  730. }
  731. if (update_rasterizer_options)
  732. m_rasterizer.set_options(rasterizer_options);
  733. }
  734. GLboolean SoftwareGLContext::gl_is_enabled(GLenum capability)
  735. {
  736. RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, 0);
  737. auto optional_parameter = get_context_parameter(capability);
  738. RETURN_VALUE_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM, 0);
  739. auto parameter = optional_parameter.release_value();
  740. RETURN_VALUE_WITH_ERROR_IF(!parameter.is_capability, GL_INVALID_ENUM, 0);
  741. return parameter.value.boolean_value;
  742. }
  743. void SoftwareGLContext::gl_gen_textures(GLsizei n, GLuint* textures)
  744. {
  745. RETURN_WITH_ERROR_IF(n < 0, GL_INVALID_VALUE);
  746. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  747. m_name_allocator.allocate(n, textures);
  748. // Initialize all texture names with a nullptr
  749. for (auto i = 0; i < n; i++) {
  750. GLuint name = textures[i];
  751. m_allocated_textures.set(name, nullptr);
  752. }
  753. }
  754. void SoftwareGLContext::gl_delete_textures(GLsizei n, const GLuint* textures)
  755. {
  756. RETURN_WITH_ERROR_IF(n < 0, GL_INVALID_VALUE);
  757. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  758. for (auto i = 0; i < n; i++) {
  759. GLuint name = textures[i];
  760. if (name == 0)
  761. continue;
  762. m_name_allocator.free(name);
  763. auto texture_object = m_allocated_textures.find(name);
  764. if (texture_object == m_allocated_textures.end() || texture_object->value.is_null())
  765. continue;
  766. // Check all texture units
  767. for (auto& texture_unit : m_texture_units) {
  768. if (texture_object->value == texture_unit.bound_texture())
  769. texture_unit.bind_texture_to_target(GL_TEXTURE_2D, nullptr);
  770. }
  771. m_allocated_textures.remove(name);
  772. }
  773. }
  774. void SoftwareGLContext::gl_tex_image_2d(GLenum target, GLint level, GLint internal_format, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* data)
  775. {
  776. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  777. // We only support GL_TEXTURE_2D for now
  778. RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM);
  779. // Check if there is actually a texture bound
  780. RETURN_WITH_ERROR_IF(target == GL_TEXTURE_2D && m_active_texture_unit->currently_bound_target() != GL_TEXTURE_2D, GL_INVALID_OPERATION);
  781. // Internal format can also be a number between 1 and 4. Symbolic formats were only added with EXT_texture, promoted to core in OpenGL 1.1
  782. if (internal_format == 1)
  783. internal_format = GL_ALPHA;
  784. else if (internal_format == 2)
  785. internal_format = GL_LUMINANCE_ALPHA;
  786. else if (internal_format == 3)
  787. internal_format = GL_RGB;
  788. else if (internal_format == 4)
  789. internal_format = GL_RGBA;
  790. // We only support symbolic constants for now
  791. RETURN_WITH_ERROR_IF(!(internal_format == GL_RGB || internal_format == GL_RGBA || internal_format == GL_LUMINANCE8 || internal_format == GL_LUMINANCE8_ALPHA8), GL_INVALID_ENUM);
  792. RETURN_WITH_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT_5_6_5), GL_INVALID_VALUE);
  793. RETURN_WITH_ERROR_IF(level < 0 || level > Texture2D::LOG2_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
  794. RETURN_WITH_ERROR_IF(width < 0 || height < 0 || width > (2 + Texture2D::MAX_TEXTURE_SIZE) || height > (2 + Texture2D::MAX_TEXTURE_SIZE), GL_INVALID_VALUE);
  795. // Check if width and height are a power of 2
  796. RETURN_WITH_ERROR_IF((width & (width - 1)) != 0, GL_INVALID_VALUE);
  797. RETURN_WITH_ERROR_IF((height & (height - 1)) != 0, GL_INVALID_VALUE);
  798. RETURN_WITH_ERROR_IF(border != 0, GL_INVALID_VALUE);
  799. if (level == 0) {
  800. // FIXME: OpenGL has the concept of texture and mipmap completeness. A texture has to fulfill certain criteria to be considered complete.
  801. // Trying to render while an incomplete texture is bound will result in an error.
  802. // Here we simply create a complete device image when mipmap level 0 is attached to the texture object. This has the unfortunate side effect
  803. // that constructing GL textures in any but the default mipmap order, going from level 0 upwards will cause mip levels to stay uninitialized.
  804. // To be spec compliant we should create the device image once the texture has become complete and is used for rendering the first time.
  805. // All images that were attached before the device image was created need to be stored somewhere to be used to initialize the device image once complete.
  806. SoftGPU::ImageFormat device_format;
  807. switch (internal_format) {
  808. case GL_RGB:
  809. device_format = SoftGPU::ImageFormat::RGB888;
  810. break;
  811. case GL_RGBA:
  812. device_format = SoftGPU::ImageFormat::RGBA8888;
  813. break;
  814. case GL_LUMINANCE8:
  815. device_format = SoftGPU::ImageFormat::L8;
  816. break;
  817. case GL_LUMINANCE8_ALPHA8:
  818. device_format = SoftGPU::ImageFormat::L8A8;
  819. break;
  820. default:
  821. VERIFY_NOT_REACHED();
  822. }
  823. m_active_texture_unit->bound_texture_2d()->set_device_image(m_rasterizer.create_image(device_format, width, height, 1, 999, 1));
  824. m_sampler_config_is_dirty = true;
  825. }
  826. m_active_texture_unit->bound_texture_2d()->upload_texture_data(level, internal_format, width, height, format, type, data, m_unpack_row_length, m_unpack_alignment);
  827. }
  828. void SoftwareGLContext::gl_tex_sub_image_2d(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* data)
  829. {
  830. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  831. // We only support GL_TEXTURE_2D for now
  832. RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM);
  833. // Check if there is actually a texture bound
  834. RETURN_WITH_ERROR_IF(target == GL_TEXTURE_2D && m_active_texture_unit->currently_bound_target() != GL_TEXTURE_2D, GL_INVALID_OPERATION);
  835. // We only support symbolic constants for now
  836. RETURN_WITH_ERROR_IF(!(format == GL_RGBA || format == GL_RGB), GL_INVALID_VALUE);
  837. RETURN_WITH_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT_5_6_5), GL_INVALID_VALUE);
  838. RETURN_WITH_ERROR_IF(level < 0 || level > Texture2D::LOG2_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
  839. RETURN_WITH_ERROR_IF(width < 0 || height < 0 || width > (2 + Texture2D::MAX_TEXTURE_SIZE) || height > (2 + Texture2D::MAX_TEXTURE_SIZE), GL_INVALID_VALUE);
  840. auto texture = m_active_texture_unit->bound_texture_2d();
  841. RETURN_WITH_ERROR_IF(xoffset < 0 || yoffset < 0 || xoffset + width > texture->width_at_lod(level) || yoffset + height > texture->height_at_lod(level), GL_INVALID_VALUE);
  842. texture->replace_sub_texture_data(level, xoffset, yoffset, width, height, format, type, data, m_unpack_row_length, m_unpack_alignment);
  843. }
  844. void SoftwareGLContext::gl_tex_parameter(GLenum target, GLenum pname, GLfloat param)
  845. {
  846. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_tex_parameter, target, pname, param);
  847. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  848. // FIXME: We currently only support GL_TETXURE_2D targets. 1D, 3D and CUBE should also be supported (https://docs.gl/gl2/glTexParameter)
  849. RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM);
  850. // FIXME: implement the remaining parameters. (https://docs.gl/gl2/glTexParameter)
  851. RETURN_WITH_ERROR_IF(!(pname == GL_TEXTURE_MIN_FILTER
  852. || pname == GL_TEXTURE_MAG_FILTER
  853. || pname == GL_TEXTURE_WRAP_S
  854. || pname == GL_TEXTURE_WRAP_T),
  855. GL_INVALID_ENUM);
  856. if (target == GL_TEXTURE_2D) {
  857. auto texture2d = m_active_texture_unit->bound_texture_2d();
  858. if (texture2d.is_null())
  859. return;
  860. switch (pname) {
  861. case GL_TEXTURE_MIN_FILTER:
  862. RETURN_WITH_ERROR_IF(!(param == GL_NEAREST
  863. || param == GL_LINEAR
  864. || param == GL_NEAREST_MIPMAP_NEAREST
  865. || param == GL_LINEAR_MIPMAP_NEAREST
  866. || param == GL_NEAREST_MIPMAP_LINEAR
  867. || param == GL_LINEAR_MIPMAP_LINEAR),
  868. GL_INVALID_ENUM);
  869. texture2d->sampler().set_min_filter(param);
  870. break;
  871. case GL_TEXTURE_MAG_FILTER:
  872. RETURN_WITH_ERROR_IF(!(param == GL_NEAREST
  873. || param == GL_LINEAR),
  874. GL_INVALID_ENUM);
  875. texture2d->sampler().set_mag_filter(param);
  876. break;
  877. case GL_TEXTURE_WRAP_S:
  878. RETURN_WITH_ERROR_IF(!(param == GL_CLAMP
  879. || param == GL_CLAMP_TO_BORDER
  880. || param == GL_CLAMP_TO_EDGE
  881. || param == GL_MIRRORED_REPEAT
  882. || param == GL_REPEAT),
  883. GL_INVALID_ENUM);
  884. texture2d->sampler().set_wrap_s_mode(param);
  885. break;
  886. case GL_TEXTURE_WRAP_T:
  887. RETURN_WITH_ERROR_IF(!(param == GL_CLAMP
  888. || param == GL_CLAMP_TO_BORDER
  889. || param == GL_CLAMP_TO_EDGE
  890. || param == GL_MIRRORED_REPEAT
  891. || param == GL_REPEAT),
  892. GL_INVALID_ENUM);
  893. texture2d->sampler().set_wrap_t_mode(param);
  894. break;
  895. default:
  896. VERIFY_NOT_REACHED();
  897. }
  898. }
  899. m_sampler_config_is_dirty = true;
  900. }
  901. void SoftwareGLContext::gl_front_face(GLenum face)
  902. {
  903. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_front_face, face);
  904. RETURN_WITH_ERROR_IF(face < GL_CW || face > GL_CCW, GL_INVALID_ENUM);
  905. m_front_face = face;
  906. auto rasterizer_options = m_rasterizer.options();
  907. rasterizer_options.front_face = (face == GL_CW) ? SoftGPU::WindingOrder::Clockwise : SoftGPU::WindingOrder::CounterClockwise;
  908. m_rasterizer.set_options(rasterizer_options);
  909. }
  910. void SoftwareGLContext::gl_cull_face(GLenum cull_mode)
  911. {
  912. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_cull_face, cull_mode);
  913. RETURN_WITH_ERROR_IF(cull_mode < GL_FRONT || cull_mode > GL_FRONT_AND_BACK, GL_INVALID_ENUM);
  914. m_culled_sides = cull_mode;
  915. auto rasterizer_options = m_rasterizer.options();
  916. rasterizer_options.cull_back = cull_mode == GL_BACK || cull_mode == GL_FRONT_AND_BACK;
  917. rasterizer_options.cull_front = cull_mode == GL_FRONT || cull_mode == GL_FRONT_AND_BACK;
  918. m_rasterizer.set_options(rasterizer_options);
  919. }
  920. GLuint SoftwareGLContext::gl_gen_lists(GLsizei range)
  921. {
  922. RETURN_VALUE_WITH_ERROR_IF(range <= 0, GL_INVALID_VALUE, 0);
  923. RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, 0);
  924. auto initial_entry = m_listings.size();
  925. m_listings.resize(range + initial_entry);
  926. return initial_entry + 1;
  927. }
  928. void SoftwareGLContext::invoke_list(size_t list_index)
  929. {
  930. auto& listing = m_listings[list_index - 1];
  931. for (auto& entry : listing.entries) {
  932. entry.function.visit([&](auto& function) {
  933. entry.arguments.visit([&](auto& arguments) {
  934. auto apply = [&]<typename... Args>(Args && ... args)
  935. {
  936. if constexpr (requires { (this->*function)(forward<Args>(args)...); })
  937. (this->*function)(forward<Args>(args)...);
  938. };
  939. arguments.apply_as_args(apply);
  940. });
  941. });
  942. }
  943. }
  944. void SoftwareGLContext::gl_call_list(GLuint list)
  945. {
  946. if (m_gl_call_depth > max_allowed_gl_call_depth)
  947. return;
  948. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_call_list, list);
  949. if (m_listings.size() < list)
  950. return;
  951. TemporaryChange change { m_gl_call_depth, m_gl_call_depth + 1 };
  952. invoke_list(list);
  953. }
  954. void SoftwareGLContext::gl_call_lists(GLsizei n, GLenum type, void const* lists)
  955. {
  956. if (m_gl_call_depth > max_allowed_gl_call_depth)
  957. return;
  958. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_call_lists, n, type, lists);
  959. RETURN_WITH_ERROR_IF(n < 0, GL_INVALID_VALUE);
  960. RETURN_WITH_ERROR_IF(!(type == GL_BYTE
  961. || type == GL_UNSIGNED_BYTE
  962. || type == GL_SHORT
  963. || type == GL_UNSIGNED_SHORT
  964. || type == GL_INT
  965. || type == GL_UNSIGNED_INT
  966. || type == GL_FLOAT
  967. || type == GL_2_BYTES
  968. || type == GL_3_BYTES
  969. || type == GL_4_BYTES),
  970. GL_INVALID_ENUM);
  971. TemporaryChange change { m_gl_call_depth, m_gl_call_depth + 1 };
  972. auto invoke_all_lists = [&]<typename T>(T const* lists) {
  973. for (int i = 0; i < n; ++i) {
  974. auto list = static_cast<size_t>(lists[i]);
  975. invoke_list(m_list_base + list);
  976. }
  977. };
  978. switch (type) {
  979. case GL_BYTE:
  980. invoke_all_lists(static_cast<GLbyte const*>(lists));
  981. break;
  982. case GL_UNSIGNED_BYTE:
  983. invoke_all_lists(static_cast<GLubyte const*>(lists));
  984. break;
  985. case GL_SHORT:
  986. invoke_all_lists(static_cast<GLshort const*>(lists));
  987. break;
  988. case GL_UNSIGNED_SHORT:
  989. invoke_all_lists(static_cast<GLushort const*>(lists));
  990. break;
  991. case GL_INT:
  992. invoke_all_lists(static_cast<GLint const*>(lists));
  993. break;
  994. case GL_UNSIGNED_INT:
  995. invoke_all_lists(static_cast<GLuint const*>(lists));
  996. break;
  997. case GL_FLOAT:
  998. invoke_all_lists(static_cast<GLfloat const*>(lists));
  999. break;
  1000. case GL_2_BYTES:
  1001. case GL_3_BYTES:
  1002. case GL_4_BYTES:
  1003. dbgln("SoftwareGLContext FIXME: unimplemented glCallLists() with type {}", type);
  1004. break;
  1005. default:
  1006. VERIFY_NOT_REACHED();
  1007. }
  1008. }
  1009. void SoftwareGLContext::gl_delete_lists(GLuint list, GLsizei range)
  1010. {
  1011. if (m_listings.size() < list || m_listings.size() <= list + range)
  1012. return;
  1013. for (auto& entry : m_listings.span().slice(list - 1, range))
  1014. entry.entries.clear_with_capacity();
  1015. }
  1016. void SoftwareGLContext::gl_list_base(GLuint base)
  1017. {
  1018. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_list_base, base);
  1019. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1020. m_list_base = base;
  1021. }
  1022. void SoftwareGLContext::gl_end_list()
  1023. {
  1024. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1025. RETURN_WITH_ERROR_IF(!m_current_listing_index.has_value(), GL_INVALID_OPERATION);
  1026. m_listings[m_current_listing_index->index] = move(m_current_listing_index->listing);
  1027. m_current_listing_index.clear();
  1028. }
  1029. void SoftwareGLContext::gl_new_list(GLuint list, GLenum mode)
  1030. {
  1031. RETURN_WITH_ERROR_IF(list == 0, GL_INVALID_VALUE);
  1032. RETURN_WITH_ERROR_IF(mode != GL_COMPILE && mode != GL_COMPILE_AND_EXECUTE, GL_INVALID_ENUM);
  1033. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1034. RETURN_WITH_ERROR_IF(m_current_listing_index.has_value(), GL_INVALID_OPERATION);
  1035. if (m_listings.size() < list)
  1036. return;
  1037. m_current_listing_index = CurrentListing { {}, static_cast<size_t>(list - 1), mode };
  1038. }
  1039. GLboolean SoftwareGLContext::gl_is_list(GLuint list)
  1040. {
  1041. RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, GL_FALSE);
  1042. return list < m_listings.size() ? GL_TRUE : GL_FALSE;
  1043. }
  1044. void SoftwareGLContext::gl_flush()
  1045. {
  1046. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1047. // No-op since SoftwareGLContext is completely synchronous at the moment
  1048. }
  1049. void SoftwareGLContext::gl_finish()
  1050. {
  1051. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1052. // No-op since SoftwareGLContext is completely synchronous at the moment
  1053. }
  1054. void SoftwareGLContext::gl_blend_func(GLenum src_factor, GLenum dst_factor)
  1055. {
  1056. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_blend_func, src_factor, dst_factor);
  1057. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1058. // FIXME: The list of allowed enums differs between API versions
  1059. // This was taken from the 2.0 spec on https://docs.gl/gl2/glBlendFunc
  1060. RETURN_WITH_ERROR_IF(!(src_factor == GL_ZERO
  1061. || src_factor == GL_ONE
  1062. || src_factor == GL_SRC_COLOR
  1063. || src_factor == GL_ONE_MINUS_SRC_COLOR
  1064. || src_factor == GL_DST_COLOR
  1065. || src_factor == GL_ONE_MINUS_DST_COLOR
  1066. || src_factor == GL_SRC_ALPHA
  1067. || src_factor == GL_ONE_MINUS_SRC_ALPHA
  1068. || src_factor == GL_DST_ALPHA
  1069. || src_factor == GL_ONE_MINUS_DST_ALPHA
  1070. || src_factor == GL_CONSTANT_COLOR
  1071. || src_factor == GL_ONE_MINUS_CONSTANT_COLOR
  1072. || src_factor == GL_CONSTANT_ALPHA
  1073. || src_factor == GL_ONE_MINUS_CONSTANT_ALPHA
  1074. || src_factor == GL_SRC_ALPHA_SATURATE),
  1075. GL_INVALID_ENUM);
  1076. RETURN_WITH_ERROR_IF(!(dst_factor == GL_ZERO
  1077. || dst_factor == GL_ONE
  1078. || dst_factor == GL_SRC_COLOR
  1079. || dst_factor == GL_ONE_MINUS_SRC_COLOR
  1080. || dst_factor == GL_DST_COLOR
  1081. || dst_factor == GL_ONE_MINUS_DST_COLOR
  1082. || dst_factor == GL_SRC_ALPHA
  1083. || dst_factor == GL_ONE_MINUS_SRC_ALPHA
  1084. || dst_factor == GL_DST_ALPHA
  1085. || dst_factor == GL_ONE_MINUS_DST_ALPHA
  1086. || dst_factor == GL_CONSTANT_COLOR
  1087. || dst_factor == GL_ONE_MINUS_CONSTANT_COLOR
  1088. || dst_factor == GL_CONSTANT_ALPHA
  1089. || dst_factor == GL_ONE_MINUS_CONSTANT_ALPHA),
  1090. GL_INVALID_ENUM);
  1091. m_blend_source_factor = src_factor;
  1092. m_blend_destination_factor = dst_factor;
  1093. auto map_gl_blend_factor_to_device = [](GLenum factor) constexpr
  1094. {
  1095. switch (factor) {
  1096. case GL_ZERO:
  1097. return SoftGPU::BlendFactor::Zero;
  1098. case GL_ONE:
  1099. return SoftGPU::BlendFactor::One;
  1100. case GL_SRC_ALPHA:
  1101. return SoftGPU::BlendFactor::SrcAlpha;
  1102. case GL_ONE_MINUS_SRC_ALPHA:
  1103. return SoftGPU::BlendFactor::OneMinusSrcAlpha;
  1104. case GL_SRC_COLOR:
  1105. return SoftGPU::BlendFactor::SrcColor;
  1106. case GL_ONE_MINUS_SRC_COLOR:
  1107. return SoftGPU::BlendFactor::OneMinusSrcColor;
  1108. case GL_DST_ALPHA:
  1109. return SoftGPU::BlendFactor::DstAlpha;
  1110. case GL_ONE_MINUS_DST_ALPHA:
  1111. return SoftGPU::BlendFactor::OneMinusDstAlpha;
  1112. case GL_DST_COLOR:
  1113. return SoftGPU::BlendFactor::DstColor;
  1114. case GL_ONE_MINUS_DST_COLOR:
  1115. return SoftGPU::BlendFactor::OneMinusDstColor;
  1116. case GL_SRC_ALPHA_SATURATE:
  1117. return SoftGPU::BlendFactor::SrcAlphaSaturate;
  1118. default:
  1119. VERIFY_NOT_REACHED();
  1120. }
  1121. };
  1122. auto options = m_rasterizer.options();
  1123. options.blend_source_factor = map_gl_blend_factor_to_device(m_blend_source_factor);
  1124. options.blend_destination_factor = map_gl_blend_factor_to_device(m_blend_destination_factor);
  1125. m_rasterizer.set_options(options);
  1126. }
  1127. void SoftwareGLContext::gl_shade_model(GLenum mode)
  1128. {
  1129. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_shade_model, mode);
  1130. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1131. RETURN_WITH_ERROR_IF(mode != GL_FLAT && mode != GL_SMOOTH, GL_INVALID_ENUM);
  1132. auto options = m_rasterizer.options();
  1133. options.shade_smooth = (mode == GL_SMOOTH);
  1134. m_rasterizer.set_options(options);
  1135. }
  1136. void SoftwareGLContext::gl_alpha_func(GLenum func, GLclampf ref)
  1137. {
  1138. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_alpha_func, func, ref);
  1139. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1140. RETURN_WITH_ERROR_IF(func < GL_NEVER || func > GL_ALWAYS, GL_INVALID_ENUM);
  1141. m_alpha_test_func = func;
  1142. m_alpha_test_ref_value = ref;
  1143. auto options = m_rasterizer.options();
  1144. switch (func) {
  1145. case GL_NEVER:
  1146. options.alpha_test_func = SoftGPU::AlphaTestFunction::Never;
  1147. break;
  1148. case GL_ALWAYS:
  1149. options.alpha_test_func = SoftGPU::AlphaTestFunction::Always;
  1150. break;
  1151. case GL_LESS:
  1152. options.alpha_test_func = SoftGPU::AlphaTestFunction::Less;
  1153. break;
  1154. case GL_LEQUAL:
  1155. options.alpha_test_func = SoftGPU::AlphaTestFunction::LessOrEqual;
  1156. break;
  1157. case GL_EQUAL:
  1158. options.alpha_test_func = SoftGPU::AlphaTestFunction::Equal;
  1159. break;
  1160. case GL_NOTEQUAL:
  1161. options.alpha_test_func = SoftGPU::AlphaTestFunction::NotEqual;
  1162. break;
  1163. case GL_GEQUAL:
  1164. options.alpha_test_func = SoftGPU::AlphaTestFunction::GreaterOrEqual;
  1165. break;
  1166. case GL_GREATER:
  1167. options.alpha_test_func = SoftGPU::AlphaTestFunction::Greater;
  1168. break;
  1169. default:
  1170. VERIFY_NOT_REACHED();
  1171. }
  1172. options.alpha_test_ref_value = m_alpha_test_ref_value;
  1173. m_rasterizer.set_options(options);
  1174. }
  1175. void SoftwareGLContext::gl_hint(GLenum target, GLenum mode)
  1176. {
  1177. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_hint, target, mode);
  1178. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1179. RETURN_WITH_ERROR_IF(target != GL_PERSPECTIVE_CORRECTION_HINT
  1180. && target != GL_POINT_SMOOTH_HINT
  1181. && target != GL_LINE_SMOOTH_HINT
  1182. && target != GL_POLYGON_SMOOTH_HINT
  1183. && target != GL_FOG_HINT
  1184. && target != GL_GENERATE_MIPMAP_HINT
  1185. && target != GL_TEXTURE_COMPRESSION_HINT,
  1186. GL_INVALID_ENUM);
  1187. RETURN_WITH_ERROR_IF(mode != GL_DONT_CARE
  1188. && mode != GL_FASTEST
  1189. && mode != GL_NICEST,
  1190. GL_INVALID_ENUM);
  1191. // According to the spec implementors are free to ignore glHint. So we do.
  1192. }
  1193. void SoftwareGLContext::gl_read_buffer(GLenum mode)
  1194. {
  1195. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_read_buffer, mode);
  1196. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1197. // FIXME: Also allow aux buffers GL_AUX0 through GL_AUX3 here
  1198. // plus any aux buffer between 0 and GL_AUX_BUFFERS
  1199. RETURN_WITH_ERROR_IF(mode != GL_FRONT_LEFT
  1200. && mode != GL_FRONT_RIGHT
  1201. && mode != GL_BACK_LEFT
  1202. && mode != GL_BACK_RIGHT
  1203. && mode != GL_FRONT
  1204. && mode != GL_BACK
  1205. && mode != GL_LEFT
  1206. && mode != GL_RIGHT,
  1207. GL_INVALID_ENUM);
  1208. // FIXME: We do not currently have aux buffers, so make it an invalid
  1209. // operation to select anything but front or back buffers. Also we do
  1210. // not allow selecting the stereoscopic RIGHT buffers since we do not
  1211. // have them configured.
  1212. RETURN_WITH_ERROR_IF(mode != GL_FRONT_LEFT
  1213. && mode != GL_FRONT
  1214. && mode != GL_BACK_LEFT
  1215. && mode != GL_BACK
  1216. && mode != GL_FRONT
  1217. && mode != GL_BACK
  1218. && mode != GL_LEFT,
  1219. GL_INVALID_OPERATION);
  1220. m_current_read_buffer = mode;
  1221. }
  1222. void SoftwareGLContext::gl_draw_buffer(GLenum buffer)
  1223. {
  1224. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_draw_buffer, buffer);
  1225. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1226. // FIXME: Also allow aux buffers GL_AUX0 through GL_AUX3 here
  1227. // plus any aux buffer between 0 and GL_AUX_BUFFERS
  1228. RETURN_WITH_ERROR_IF(buffer != GL_NONE
  1229. && buffer != GL_FRONT_LEFT
  1230. && buffer != GL_FRONT_RIGHT
  1231. && buffer != GL_BACK_LEFT
  1232. && buffer != GL_BACK_RIGHT
  1233. && buffer != GL_FRONT
  1234. && buffer != GL_BACK
  1235. && buffer != GL_LEFT
  1236. && buffer != GL_RIGHT,
  1237. GL_INVALID_ENUM);
  1238. // FIXME: We do not currently have aux buffers, so make it an invalid
  1239. // operation to select anything but front or back buffers. Also we do
  1240. // not allow selecting the stereoscopic RIGHT buffers since we do not
  1241. // have them configured.
  1242. RETURN_WITH_ERROR_IF(buffer != GL_NONE
  1243. && buffer != GL_FRONT_LEFT
  1244. && buffer != GL_FRONT
  1245. && buffer != GL_BACK_LEFT
  1246. && buffer != GL_BACK
  1247. && buffer != GL_FRONT
  1248. && buffer != GL_BACK
  1249. && buffer != GL_LEFT,
  1250. GL_INVALID_OPERATION);
  1251. m_current_draw_buffer = buffer;
  1252. auto rasterizer_options = m_rasterizer.options();
  1253. // FIXME: We only have a single draw buffer in SoftGPU at the moment,
  1254. // so we simply disable color writes if GL_NONE is selected
  1255. rasterizer_options.enable_color_write = m_current_draw_buffer != GL_NONE;
  1256. m_rasterizer.set_options(rasterizer_options);
  1257. }
  1258. void SoftwareGLContext::gl_read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
  1259. {
  1260. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1261. RETURN_WITH_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
  1262. RETURN_WITH_ERROR_IF(format != GL_COLOR_INDEX
  1263. && format != GL_STENCIL_INDEX
  1264. && format != GL_DEPTH_COMPONENT
  1265. && format != GL_RED
  1266. && format != GL_GREEN
  1267. && format != GL_BLUE
  1268. && format != GL_ALPHA
  1269. && format != GL_RGB
  1270. && format != GL_RGBA
  1271. && format != GL_LUMINANCE
  1272. && format != GL_LUMINANCE_ALPHA,
  1273. GL_INVALID_ENUM);
  1274. RETURN_WITH_ERROR_IF(type != GL_UNSIGNED_BYTE
  1275. && type != GL_BYTE
  1276. && type != GL_BITMAP
  1277. && type != GL_UNSIGNED_SHORT
  1278. && type != GL_SHORT
  1279. && type != GL_BLUE
  1280. && type != GL_UNSIGNED_INT
  1281. && type != GL_INT
  1282. && type != GL_FLOAT,
  1283. GL_INVALID_ENUM);
  1284. // FIXME: We only support RGBA buffers for now.
  1285. // Once we add support for indexed color modes do the correct check here
  1286. RETURN_WITH_ERROR_IF(format == GL_COLOR_INDEX, GL_INVALID_OPERATION);
  1287. // FIXME: We do not have stencil buffers yet
  1288. // Once we add support for stencil buffers do the correct check here
  1289. RETURN_WITH_ERROR_IF(format == GL_STENCIL_INDEX, GL_INVALID_OPERATION);
  1290. if (format == GL_DEPTH_COMPONENT) {
  1291. // FIXME: This check needs to be a bit more sophisticated. Currently the buffers
  1292. // are hardcoded. Once we add proper structures for them we need to correct this check
  1293. // Error because only back buffer has a depth buffer
  1294. RETURN_WITH_ERROR_IF(m_current_read_buffer == GL_FRONT
  1295. || m_current_read_buffer == GL_FRONT_LEFT
  1296. || m_current_read_buffer == GL_FRONT_RIGHT,
  1297. GL_INVALID_OPERATION);
  1298. }
  1299. // Some helper functions for converting float values to integer types
  1300. auto float_to_i8 = [](float f) -> GLchar {
  1301. return static_cast<GLchar>((0x7f * min(max(f, 0.0f), 1.0f) - 1) / 2);
  1302. };
  1303. auto float_to_i16 = [](float f) -> GLshort {
  1304. return static_cast<GLshort>((0x7fff * min(max(f, 0.0f), 1.0f) - 1) / 2);
  1305. };
  1306. auto float_to_i32 = [](float f) -> GLint {
  1307. return static_cast<GLint>((0x7fffffff * min(max(f, 0.0f), 1.0f) - 1) / 2);
  1308. };
  1309. auto float_to_u8 = [](float f) -> GLubyte {
  1310. return static_cast<GLubyte>(0xff * min(max(f, 0.0f), 1.0f));
  1311. };
  1312. auto float_to_u16 = [](float f) -> GLushort {
  1313. return static_cast<GLushort>(0xffff * min(max(f, 0.0f), 1.0f));
  1314. };
  1315. auto float_to_u32 = [](float f) -> GLuint {
  1316. return static_cast<GLuint>(0xffffffff * min(max(f, 0.0f), 1.0f));
  1317. };
  1318. u8 component_size = 0;
  1319. switch (type) {
  1320. case GL_BYTE:
  1321. case GL_UNSIGNED_BYTE:
  1322. component_size = 1;
  1323. break;
  1324. case GL_SHORT:
  1325. case GL_UNSIGNED_SHORT:
  1326. component_size = 2;
  1327. break;
  1328. case GL_INT:
  1329. case GL_UNSIGNED_INT:
  1330. case GL_FLOAT:
  1331. component_size = 4;
  1332. break;
  1333. }
  1334. if (format == GL_DEPTH_COMPONENT) {
  1335. auto const row_stride = (width * component_size + m_pack_alignment - 1) / m_pack_alignment * m_pack_alignment;
  1336. // Read from depth buffer
  1337. for (GLsizei i = 0; i < height; ++i) {
  1338. for (GLsizei j = 0; j < width; ++j) {
  1339. float depth = m_rasterizer.get_depthbuffer_value(x + j, y + i);
  1340. auto char_ptr = reinterpret_cast<char*>(pixels) + i * row_stride + j * component_size;
  1341. switch (type) {
  1342. case GL_BYTE:
  1343. *reinterpret_cast<GLchar*>(char_ptr) = float_to_i8(depth);
  1344. break;
  1345. case GL_SHORT:
  1346. *reinterpret_cast<GLshort*>(char_ptr) = float_to_i16(depth);
  1347. break;
  1348. case GL_INT:
  1349. *reinterpret_cast<GLint*>(char_ptr) = float_to_i32(depth);
  1350. break;
  1351. case GL_UNSIGNED_BYTE:
  1352. *reinterpret_cast<GLubyte*>(char_ptr) = float_to_u8(depth);
  1353. break;
  1354. case GL_UNSIGNED_SHORT:
  1355. *reinterpret_cast<GLushort*>(char_ptr) = float_to_u16(depth);
  1356. break;
  1357. case GL_UNSIGNED_INT:
  1358. *reinterpret_cast<GLuint*>(char_ptr) = float_to_u32(depth);
  1359. break;
  1360. case GL_FLOAT:
  1361. *reinterpret_cast<GLfloat*>(char_ptr) = min(max(depth, 0.0f), 1.0f);
  1362. break;
  1363. }
  1364. }
  1365. }
  1366. return;
  1367. }
  1368. bool write_red = false;
  1369. bool write_green = false;
  1370. bool write_blue = false;
  1371. bool write_alpha = false;
  1372. size_t component_count = 0;
  1373. size_t red_offset = 0;
  1374. size_t green_offset = 0;
  1375. size_t blue_offset = 0;
  1376. size_t alpha_offset = 0;
  1377. char* red_ptr = nullptr;
  1378. char* green_ptr = nullptr;
  1379. char* blue_ptr = nullptr;
  1380. char* alpha_ptr = nullptr;
  1381. switch (format) {
  1382. case GL_RGB:
  1383. write_red = true;
  1384. write_green = true;
  1385. write_blue = true;
  1386. component_count = 3;
  1387. red_offset = 2;
  1388. green_offset = 1;
  1389. blue_offset = 0;
  1390. break;
  1391. case GL_RGBA:
  1392. write_red = true;
  1393. write_green = true;
  1394. write_blue = true;
  1395. write_alpha = true;
  1396. component_count = 4;
  1397. red_offset = 3;
  1398. green_offset = 2;
  1399. blue_offset = 1;
  1400. alpha_offset = 0;
  1401. break;
  1402. case GL_RED:
  1403. write_red = true;
  1404. component_count = 1;
  1405. red_offset = 0;
  1406. break;
  1407. case GL_GREEN:
  1408. write_green = true;
  1409. component_count = 1;
  1410. green_offset = 0;
  1411. break;
  1412. case GL_BLUE:
  1413. write_blue = true;
  1414. component_count = 1;
  1415. blue_offset = 0;
  1416. break;
  1417. case GL_ALPHA:
  1418. write_alpha = true;
  1419. component_count = 1;
  1420. alpha_offset = 0;
  1421. break;
  1422. }
  1423. auto const pixel_bytes = component_size * component_count;
  1424. auto const row_alignment_bytes = (m_pack_alignment - ((width * pixel_bytes) % m_pack_alignment)) % m_pack_alignment;
  1425. char* out_ptr = reinterpret_cast<char*>(pixels);
  1426. for (int i = 0; i < (int)height; ++i) {
  1427. for (int j = 0; j < (int)width; ++j) {
  1428. Gfx::RGBA32 color {};
  1429. if (m_current_read_buffer == GL_FRONT || m_current_read_buffer == GL_LEFT || m_current_read_buffer == GL_FRONT_LEFT) {
  1430. if (y + i >= m_frontbuffer->width() || x + j >= m_frontbuffer->height())
  1431. color = 0;
  1432. else
  1433. color = m_frontbuffer->scanline(y + i)[x + j];
  1434. } else {
  1435. color = m_rasterizer.get_backbuffer_pixel(x + j, y + i);
  1436. }
  1437. float red = ((color >> 24) & 0xff) / 255.0f;
  1438. float green = ((color >> 16) & 0xff) / 255.0f;
  1439. float blue = ((color >> 8) & 0xff) / 255.0f;
  1440. float alpha = (color & 0xff) / 255.0f;
  1441. // FIXME: Set up write pointers based on selected endianness (glPixelStore)
  1442. red_ptr = out_ptr + (component_size * red_offset);
  1443. green_ptr = out_ptr + (component_size * green_offset);
  1444. blue_ptr = out_ptr + (component_size * blue_offset);
  1445. alpha_ptr = out_ptr + (component_size * alpha_offset);
  1446. switch (type) {
  1447. case GL_BYTE:
  1448. if (write_red)
  1449. *reinterpret_cast<GLchar*>(red_ptr) = float_to_i8(red);
  1450. if (write_green)
  1451. *reinterpret_cast<GLchar*>(green_ptr) = float_to_i8(green);
  1452. if (write_blue)
  1453. *reinterpret_cast<GLchar*>(blue_ptr) = float_to_i8(blue);
  1454. if (write_alpha)
  1455. *reinterpret_cast<GLchar*>(alpha_ptr) = float_to_i8(alpha);
  1456. break;
  1457. case GL_UNSIGNED_BYTE:
  1458. if (write_red)
  1459. *reinterpret_cast<GLubyte*>(red_ptr) = float_to_u8(red);
  1460. if (write_green)
  1461. *reinterpret_cast<GLubyte*>(green_ptr) = float_to_u8(green);
  1462. if (write_blue)
  1463. *reinterpret_cast<GLubyte*>(blue_ptr) = float_to_u8(blue);
  1464. if (write_alpha)
  1465. *reinterpret_cast<GLubyte*>(alpha_ptr) = float_to_u8(alpha);
  1466. break;
  1467. case GL_SHORT:
  1468. if (write_red)
  1469. *reinterpret_cast<GLshort*>(red_ptr) = float_to_i16(red);
  1470. if (write_green)
  1471. *reinterpret_cast<GLshort*>(green_ptr) = float_to_i16(green);
  1472. if (write_blue)
  1473. *reinterpret_cast<GLshort*>(blue_ptr) = float_to_i16(blue);
  1474. if (write_alpha)
  1475. *reinterpret_cast<GLshort*>(alpha_ptr) = float_to_i16(alpha);
  1476. break;
  1477. case GL_UNSIGNED_SHORT:
  1478. if (write_red)
  1479. *reinterpret_cast<GLushort*>(red_ptr) = float_to_u16(red);
  1480. if (write_green)
  1481. *reinterpret_cast<GLushort*>(green_ptr) = float_to_u16(green);
  1482. if (write_blue)
  1483. *reinterpret_cast<GLushort*>(blue_ptr) = float_to_u16(blue);
  1484. if (write_alpha)
  1485. *reinterpret_cast<GLushort*>(alpha_ptr) = float_to_u16(alpha);
  1486. break;
  1487. case GL_INT:
  1488. if (write_red)
  1489. *reinterpret_cast<GLint*>(red_ptr) = float_to_i32(red);
  1490. if (write_green)
  1491. *reinterpret_cast<GLint*>(green_ptr) = float_to_i32(green);
  1492. if (write_blue)
  1493. *reinterpret_cast<GLint*>(blue_ptr) = float_to_i32(blue);
  1494. if (write_alpha)
  1495. *reinterpret_cast<GLint*>(alpha_ptr) = float_to_i32(alpha);
  1496. break;
  1497. case GL_UNSIGNED_INT:
  1498. if (write_red)
  1499. *reinterpret_cast<GLuint*>(red_ptr) = float_to_u32(red);
  1500. if (write_green)
  1501. *reinterpret_cast<GLuint*>(green_ptr) = float_to_u32(green);
  1502. if (write_blue)
  1503. *reinterpret_cast<GLuint*>(blue_ptr) = float_to_u32(blue);
  1504. if (write_alpha)
  1505. *reinterpret_cast<GLuint*>(alpha_ptr) = float_to_u32(alpha);
  1506. break;
  1507. case GL_FLOAT:
  1508. if (write_red)
  1509. *reinterpret_cast<GLfloat*>(red_ptr) = min(max(red, 0.0f), 1.0f);
  1510. if (write_green)
  1511. *reinterpret_cast<GLfloat*>(green_ptr) = min(max(green, 0.0f), 1.0f);
  1512. if (write_blue)
  1513. *reinterpret_cast<GLfloat*>(blue_ptr) = min(max(blue, 0.0f), 1.0f);
  1514. if (write_alpha)
  1515. *reinterpret_cast<GLfloat*>(alpha_ptr) = min(max(alpha, 0.0f), 1.0f);
  1516. break;
  1517. }
  1518. out_ptr += pixel_bytes;
  1519. }
  1520. out_ptr += row_alignment_bytes;
  1521. }
  1522. }
  1523. void SoftwareGLContext::gl_bind_texture(GLenum target, GLuint texture)
  1524. {
  1525. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1526. // FIXME: We only support GL_TEXTURE_2D for now
  1527. RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM);
  1528. if (texture == 0) {
  1529. switch (target) {
  1530. case GL_TEXTURE_2D:
  1531. m_active_texture_unit->bind_texture_to_target(target, nullptr);
  1532. m_sampler_config_is_dirty = true;
  1533. return;
  1534. default:
  1535. VERIFY_NOT_REACHED();
  1536. return;
  1537. }
  1538. }
  1539. auto it = m_allocated_textures.find(texture);
  1540. RefPtr<Texture> texture_object;
  1541. // OpenGL 1.x supports binding texture names that were not previously generated by glGenTextures.
  1542. // If there is not an allocated texture, meaning it was not previously generated by glGenTextures,
  1543. // we can keep texture_object null to both allocate and bind the texture with the passed in texture name.
  1544. // FIXME: Later OpenGL versions such as 4.x enforce that texture names being bound were previously generated
  1545. // by glGenTextures.
  1546. if (it != m_allocated_textures.end())
  1547. texture_object = it->value;
  1548. // Binding a texture to a different target than it was first bound is an invalid operation
  1549. // FIXME: We only support GL_TEXTURE_2D for now
  1550. RETURN_WITH_ERROR_IF(target == GL_TEXTURE_2D && !texture_object.is_null() && !texture_object->is_texture_2d(), GL_INVALID_OPERATION);
  1551. if (!texture_object) {
  1552. // This is the first time the texture is bound. Allocate an actual texture object
  1553. switch (target) {
  1554. case GL_TEXTURE_2D:
  1555. texture_object = adopt_ref(*new Texture2D());
  1556. break;
  1557. default:
  1558. VERIFY_NOT_REACHED();
  1559. }
  1560. m_allocated_textures.set(texture, texture_object);
  1561. }
  1562. switch (target) {
  1563. case GL_TEXTURE_2D:
  1564. m_active_texture_unit->bind_texture_to_target(target, texture_object);
  1565. break;
  1566. }
  1567. m_sampler_config_is_dirty = true;
  1568. }
  1569. GLboolean SoftwareGLContext::gl_is_texture(GLuint texture)
  1570. {
  1571. RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, GL_FALSE);
  1572. if (texture == 0)
  1573. return GL_FALSE;
  1574. auto it = m_allocated_textures.find(texture);
  1575. if (it == m_allocated_textures.end())
  1576. return GL_FALSE;
  1577. return it->value.is_null() ? GL_FALSE : GL_TRUE;
  1578. }
  1579. void SoftwareGLContext::gl_active_texture(GLenum texture)
  1580. {
  1581. RETURN_WITH_ERROR_IF(texture < GL_TEXTURE0 || texture > GL_TEXTURE31, GL_INVALID_ENUM);
  1582. m_active_texture_unit = &m_texture_units.at(texture - GL_TEXTURE0);
  1583. }
  1584. void SoftwareGLContext::gl_get_booleanv(GLenum pname, GLboolean* data)
  1585. {
  1586. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1587. auto optional_parameter = get_context_parameter(pname);
  1588. RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
  1589. auto parameter = optional_parameter.release_value();
  1590. switch (parameter.type) {
  1591. case GL_BOOL:
  1592. *data = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
  1593. break;
  1594. case GL_DOUBLE:
  1595. *data = (parameter.value.double_value == 0.0) ? GL_FALSE : GL_TRUE;
  1596. break;
  1597. case GL_INT:
  1598. *data = (parameter.value.integer_value == 0) ? GL_FALSE : GL_TRUE;
  1599. break;
  1600. default:
  1601. VERIFY_NOT_REACHED();
  1602. }
  1603. }
  1604. void SoftwareGLContext::gl_get_doublev(GLenum pname, GLdouble* params)
  1605. {
  1606. get_floating_point(pname, params);
  1607. }
  1608. void SoftwareGLContext::gl_get_floatv(GLenum pname, GLfloat* params)
  1609. {
  1610. get_floating_point(pname, params);
  1611. }
  1612. template<typename T>
  1613. void SoftwareGLContext::get_floating_point(GLenum pname, T* params)
  1614. {
  1615. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1616. // Handle special matrix cases first
  1617. auto flatten_and_assign_matrix = [&params](const FloatMatrix4x4& matrix) {
  1618. auto elements = matrix.elements();
  1619. for (size_t i = 0; i < 4; ++i)
  1620. for (size_t j = 0; j < 4; ++j)
  1621. params[i * 4 + j] = static_cast<T>(elements[i][j]);
  1622. };
  1623. switch (pname) {
  1624. case GL_MODELVIEW_MATRIX:
  1625. if (m_current_matrix_mode == GL_MODELVIEW)
  1626. flatten_and_assign_matrix(m_model_view_matrix);
  1627. else if (m_model_view_matrix_stack.is_empty())
  1628. flatten_and_assign_matrix(FloatMatrix4x4::identity());
  1629. else
  1630. flatten_and_assign_matrix(m_model_view_matrix_stack.last());
  1631. return;
  1632. case GL_PROJECTION_MATRIX:
  1633. if (m_current_matrix_mode == GL_PROJECTION)
  1634. flatten_and_assign_matrix(m_projection_matrix);
  1635. else if (m_projection_matrix_stack.is_empty())
  1636. flatten_and_assign_matrix(FloatMatrix4x4::identity());
  1637. else
  1638. flatten_and_assign_matrix(m_projection_matrix_stack.last());
  1639. return;
  1640. }
  1641. // Regular parameters
  1642. auto optional_parameter = get_context_parameter(pname);
  1643. RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
  1644. auto parameter = optional_parameter.release_value();
  1645. switch (parameter.type) {
  1646. case GL_BOOL:
  1647. *params = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
  1648. break;
  1649. case GL_DOUBLE:
  1650. for (size_t i = 0; i < parameter.count; ++i) {
  1651. params[i] = parameter.value.double_list[i];
  1652. }
  1653. break;
  1654. case GL_INT:
  1655. for (size_t i = 0; i < parameter.count; ++i) {
  1656. params[i] = parameter.value.integer_list[i];
  1657. }
  1658. break;
  1659. default:
  1660. VERIFY_NOT_REACHED();
  1661. }
  1662. }
  1663. void SoftwareGLContext::gl_get_integerv(GLenum pname, GLint* data)
  1664. {
  1665. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1666. auto optional_parameter = get_context_parameter(pname);
  1667. RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
  1668. auto parameter = optional_parameter.release_value();
  1669. switch (parameter.type) {
  1670. case GL_BOOL:
  1671. *data = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
  1672. break;
  1673. case GL_DOUBLE: {
  1674. double const int_range = static_cast<double>(NumericLimits<GLint>::max()) - NumericLimits<GLint>::min();
  1675. for (size_t i = 0; i < parameter.count; ++i) {
  1676. double const result_factor = (clamp(parameter.value.double_list[i], -1.0, 1.0) + 1.0) / 2.0;
  1677. data[i] = static_cast<GLint>(NumericLimits<GLint>::min() + result_factor * int_range);
  1678. }
  1679. break;
  1680. }
  1681. case GL_INT:
  1682. for (size_t i = 0; i < parameter.count; ++i) {
  1683. data[i] = parameter.value.integer_list[i];
  1684. }
  1685. break;
  1686. default:
  1687. VERIFY_NOT_REACHED();
  1688. }
  1689. }
  1690. void SoftwareGLContext::gl_depth_mask(GLboolean flag)
  1691. {
  1692. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_depth_mask, flag);
  1693. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1694. auto options = m_rasterizer.options();
  1695. options.enable_depth_write = (flag != GL_FALSE);
  1696. m_rasterizer.set_options(options);
  1697. }
  1698. void SoftwareGLContext::gl_enable_client_state(GLenum cap)
  1699. {
  1700. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1701. switch (cap) {
  1702. case GL_VERTEX_ARRAY:
  1703. m_client_side_vertex_array_enabled = true;
  1704. break;
  1705. case GL_COLOR_ARRAY:
  1706. m_client_side_color_array_enabled = true;
  1707. break;
  1708. case GL_TEXTURE_COORD_ARRAY:
  1709. m_client_side_texture_coord_array_enabled = true;
  1710. break;
  1711. default:
  1712. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  1713. }
  1714. }
  1715. void SoftwareGLContext::gl_disable_client_state(GLenum cap)
  1716. {
  1717. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1718. switch (cap) {
  1719. case GL_VERTEX_ARRAY:
  1720. m_client_side_vertex_array_enabled = false;
  1721. break;
  1722. case GL_COLOR_ARRAY:
  1723. m_client_side_color_array_enabled = false;
  1724. break;
  1725. case GL_TEXTURE_COORD_ARRAY:
  1726. m_client_side_texture_coord_array_enabled = false;
  1727. break;
  1728. default:
  1729. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  1730. }
  1731. }
  1732. void SoftwareGLContext::gl_vertex_pointer(GLint size, GLenum type, GLsizei stride, const void* pointer)
  1733. {
  1734. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1735. RETURN_WITH_ERROR_IF(!(size == 2 || size == 3 || size == 4), GL_INVALID_VALUE);
  1736. RETURN_WITH_ERROR_IF(!(type == GL_SHORT || type == GL_INT || type == GL_FLOAT || type == GL_DOUBLE), GL_INVALID_ENUM);
  1737. RETURN_WITH_ERROR_IF(stride < 0, GL_INVALID_VALUE);
  1738. m_client_vertex_pointer.size = size;
  1739. m_client_vertex_pointer.type = type;
  1740. m_client_vertex_pointer.stride = stride;
  1741. m_client_vertex_pointer.pointer = pointer;
  1742. }
  1743. void SoftwareGLContext::gl_color_pointer(GLint size, GLenum type, GLsizei stride, const void* pointer)
  1744. {
  1745. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1746. RETURN_WITH_ERROR_IF(!(size == 3 || size == 4), GL_INVALID_VALUE);
  1747. RETURN_WITH_ERROR_IF(!(type == GL_BYTE
  1748. || type == GL_UNSIGNED_BYTE
  1749. || type == GL_SHORT
  1750. || type == GL_UNSIGNED_SHORT
  1751. || type == GL_INT
  1752. || type == GL_UNSIGNED_INT
  1753. || type == GL_FLOAT
  1754. || type == GL_DOUBLE),
  1755. GL_INVALID_ENUM);
  1756. RETURN_WITH_ERROR_IF(stride < 0, GL_INVALID_VALUE);
  1757. m_client_color_pointer.size = size;
  1758. m_client_color_pointer.type = type;
  1759. m_client_color_pointer.stride = stride;
  1760. m_client_color_pointer.pointer = pointer;
  1761. }
  1762. void SoftwareGLContext::gl_tex_coord_pointer(GLint size, GLenum type, GLsizei stride, const void* pointer)
  1763. {
  1764. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1765. RETURN_WITH_ERROR_IF(!(size == 1 || size == 2 || size == 3 || size == 4), GL_INVALID_VALUE);
  1766. RETURN_WITH_ERROR_IF(!(type == GL_SHORT || type == GL_INT || type == GL_FLOAT || type == GL_DOUBLE), GL_INVALID_ENUM);
  1767. RETURN_WITH_ERROR_IF(stride < 0, GL_INVALID_VALUE);
  1768. m_client_tex_coord_pointer.size = size;
  1769. m_client_tex_coord_pointer.type = type;
  1770. m_client_tex_coord_pointer.stride = stride;
  1771. m_client_tex_coord_pointer.pointer = pointer;
  1772. }
  1773. void SoftwareGLContext::gl_tex_env(GLenum target, GLenum pname, GLfloat param)
  1774. {
  1775. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_tex_env, target, pname, param);
  1776. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1777. // FIXME: We currently only support a subset of possible target values. Implement the rest!
  1778. RETURN_WITH_ERROR_IF(target != GL_TEXTURE_ENV, GL_INVALID_ENUM);
  1779. // FIXME: We currently only support a subset of possible pname values. Implement the rest!
  1780. RETURN_WITH_ERROR_IF(pname != GL_TEXTURE_ENV_MODE, GL_INVALID_ENUM);
  1781. auto param_enum = static_cast<GLenum>(param);
  1782. switch (param_enum) {
  1783. case GL_MODULATE:
  1784. case GL_REPLACE:
  1785. case GL_DECAL:
  1786. m_active_texture_unit->set_env_mode(param_enum);
  1787. break;
  1788. default:
  1789. // FIXME: We currently only support a subset of possible param values. Implement the rest!
  1790. dbgln_if(GL_DEBUG, "gl_tex_env({:#x}, {:#x}, {}): param unimplemented", target, pname, param);
  1791. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  1792. }
  1793. }
  1794. void SoftwareGLContext::gl_draw_arrays(GLenum mode, GLint first, GLsizei count)
  1795. {
  1796. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_draw_arrays, mode, first, count);
  1797. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1798. // FIXME: Some modes are still missing (GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES)
  1799. RETURN_WITH_ERROR_IF(!(mode == GL_TRIANGLE_STRIP
  1800. || mode == GL_TRIANGLE_FAN
  1801. || mode == GL_TRIANGLES
  1802. || mode == GL_QUADS
  1803. || mode == GL_QUAD_STRIP
  1804. || mode == GL_POLYGON),
  1805. GL_INVALID_ENUM);
  1806. RETURN_WITH_ERROR_IF(count < 0, GL_INVALID_VALUE);
  1807. // At least the vertex array needs to be enabled
  1808. if (!m_client_side_vertex_array_enabled)
  1809. return;
  1810. auto last = first + count;
  1811. gl_begin(mode);
  1812. for (int i = first; i < last; i++) {
  1813. if (m_client_side_texture_coord_array_enabled) {
  1814. float tex_coords[4] { 0, 0, 0, 0 };
  1815. read_from_vertex_attribute_pointer(m_client_tex_coord_pointer, i, tex_coords, false);
  1816. gl_tex_coord(tex_coords[0], tex_coords[1], tex_coords[2], tex_coords[3]);
  1817. }
  1818. if (m_client_side_color_array_enabled) {
  1819. float color[4] { 0, 0, 0, 1 };
  1820. read_from_vertex_attribute_pointer(m_client_color_pointer, i, color, true);
  1821. glColor4fv(color);
  1822. }
  1823. float vertex[4] { 0, 0, 0, 1 };
  1824. read_from_vertex_attribute_pointer(m_client_vertex_pointer, i, vertex, false);
  1825. glVertex4fv(vertex);
  1826. }
  1827. gl_end();
  1828. }
  1829. void SoftwareGLContext::gl_draw_elements(GLenum mode, GLsizei count, GLenum type, const void* indices)
  1830. {
  1831. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_draw_elements, mode, count, type, indices);
  1832. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1833. // FIXME: Some modes are still missing (GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES)
  1834. RETURN_WITH_ERROR_IF(!(mode == GL_TRIANGLE_STRIP
  1835. || mode == GL_TRIANGLE_FAN
  1836. || mode == GL_TRIANGLES
  1837. || mode == GL_QUADS
  1838. || mode == GL_QUAD_STRIP
  1839. || mode == GL_POLYGON),
  1840. GL_INVALID_ENUM);
  1841. RETURN_WITH_ERROR_IF(!(type == GL_UNSIGNED_BYTE
  1842. || type == GL_UNSIGNED_SHORT
  1843. || type == GL_UNSIGNED_INT),
  1844. GL_INVALID_ENUM);
  1845. RETURN_WITH_ERROR_IF(count < 0, GL_INVALID_VALUE);
  1846. // At least the vertex array needs to be enabled
  1847. if (!m_client_side_vertex_array_enabled)
  1848. return;
  1849. gl_begin(mode);
  1850. for (int index = 0; index < count; index++) {
  1851. int i = 0;
  1852. switch (type) {
  1853. case GL_UNSIGNED_BYTE:
  1854. i = reinterpret_cast<const GLubyte*>(indices)[index];
  1855. break;
  1856. case GL_UNSIGNED_SHORT:
  1857. i = reinterpret_cast<const GLushort*>(indices)[index];
  1858. break;
  1859. case GL_UNSIGNED_INT:
  1860. i = reinterpret_cast<const GLuint*>(indices)[index];
  1861. break;
  1862. }
  1863. if (m_client_side_texture_coord_array_enabled) {
  1864. float tex_coords[4] { 0, 0, 0, 0 };
  1865. read_from_vertex_attribute_pointer(m_client_tex_coord_pointer, i, tex_coords, false);
  1866. gl_tex_coord(tex_coords[0], tex_coords[1], tex_coords[2], tex_coords[3]);
  1867. }
  1868. if (m_client_side_color_array_enabled) {
  1869. float color[4] { 0, 0, 0, 1 };
  1870. read_from_vertex_attribute_pointer(m_client_color_pointer, i, color, true);
  1871. glColor4fv(color);
  1872. }
  1873. float vertex[4] { 0, 0, 0, 1 };
  1874. read_from_vertex_attribute_pointer(m_client_vertex_pointer, i, vertex, false);
  1875. glVertex4fv(vertex);
  1876. }
  1877. gl_end();
  1878. }
  1879. void SoftwareGLContext::gl_draw_pixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data)
  1880. {
  1881. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_draw_pixels, width, height, format, type, data);
  1882. RETURN_WITH_ERROR_IF(format < GL_COLOR_INDEX || format > GL_BGRA, GL_INVALID_ENUM);
  1883. RETURN_WITH_ERROR_IF((type < GL_BYTE || type > GL_FLOAT)
  1884. && (type < GL_UNSIGNED_BYTE_3_3_2 || type > GL_UNSIGNED_INT_10_10_10_2)
  1885. && (type < GL_UNSIGNED_BYTE_2_3_3_REV || type > GL_UNSIGNED_INT_2_10_10_10_REV),
  1886. GL_INVALID_ENUM);
  1887. RETURN_WITH_ERROR_IF(type == GL_BITMAP && !(format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX), GL_INVALID_ENUM);
  1888. RETURN_WITH_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
  1889. // FIXME: GL_INVALID_OPERATION is generated if format is GL_STENCIL_INDEX and there is no stencil buffer
  1890. // FIXME: GL_INVALID_OPERATION is generated if format is GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_RGB, GL_RGBA,
  1891. // GL_BGR, GL_BGRA, GL_LUMINANCE, or GL_LUMINANCE_ALPHA, and the GL is in color index mode
  1892. RETURN_WITH_ERROR_IF(format != GL_RGB
  1893. && (type == GL_UNSIGNED_BYTE_3_3_2
  1894. || type == GL_UNSIGNED_BYTE_2_3_3_REV
  1895. || type == GL_UNSIGNED_SHORT_5_6_5
  1896. || type == GL_UNSIGNED_SHORT_5_6_5_REV),
  1897. GL_INVALID_OPERATION);
  1898. RETURN_WITH_ERROR_IF(!(format == GL_RGBA || format == GL_BGRA)
  1899. && (type == GL_UNSIGNED_SHORT_4_4_4_4
  1900. || type == GL_UNSIGNED_SHORT_4_4_4_4_REV
  1901. || type == GL_UNSIGNED_SHORT_5_5_5_1
  1902. || type == GL_UNSIGNED_SHORT_1_5_5_5_REV
  1903. || type == GL_UNSIGNED_INT_8_8_8_8
  1904. || type == GL_UNSIGNED_INT_8_8_8_8_REV
  1905. || type == GL_UNSIGNED_INT_10_10_10_2
  1906. || type == GL_UNSIGNED_INT_2_10_10_10_REV),
  1907. GL_INVALID_OPERATION);
  1908. // FIXME: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER
  1909. // target and the buffer object's data store is currently mapped.
  1910. // FIXME: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER
  1911. // target and the data would be unpacked from the buffer object such that the memory reads required would
  1912. // exceed the data store size.
  1913. // FIXME: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER
  1914. // target and data is not evenly divisible into the number of bytes needed to store in memory a datum
  1915. // indicated by type.
  1916. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1917. // FIXME: we only support RGBA + UNSIGNED_BYTE and DEPTH_COMPONENT + UNSIGNED_SHORT, implement all combinations!
  1918. if (!((format == GL_RGBA && type == GL_UNSIGNED_BYTE) || (format == GL_DEPTH_COMPONENT && type == GL_UNSIGNED_SHORT))) {
  1919. dbgln_if(GL_DEBUG, "gl_draw_pixels(): support for format {:#x} and/or type {:#x} not implemented", format, type);
  1920. return;
  1921. }
  1922. // FIXME: implement support for pixel parameters such as GL_UNPACK_ALIGNMENT
  1923. if (format == GL_RGBA) {
  1924. auto bitmap_or_error = Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, { width, height });
  1925. RETURN_WITH_ERROR_IF(bitmap_or_error.is_error(), GL_OUT_OF_MEMORY);
  1926. auto bitmap = bitmap_or_error.release_value();
  1927. auto pixel_data = static_cast<u32 const*>(data);
  1928. for (int y = 0; y < height; ++y)
  1929. for (int x = 0; x < width; ++x)
  1930. bitmap->set_pixel(x, y, Color::from_rgba(*(pixel_data++)));
  1931. m_rasterizer.blit_to_color_buffer_at_raster_position(bitmap);
  1932. } else if (format == GL_DEPTH_COMPONENT) {
  1933. Vector<float> depth_values;
  1934. depth_values.ensure_capacity(width * height);
  1935. auto depth_data = static_cast<u16 const*>(data);
  1936. for (int y = 0; y < height; ++y) {
  1937. for (int x = 0; x < width; ++x) {
  1938. auto u16_value = *(depth_data++);
  1939. auto float_value = static_cast<float>(u16_value) / NumericLimits<u16>::max();
  1940. depth_values.append(float_value);
  1941. }
  1942. }
  1943. m_rasterizer.blit_to_depth_buffer_at_raster_position(depth_values, width, height);
  1944. } else {
  1945. VERIFY_NOT_REACHED();
  1946. }
  1947. }
  1948. void SoftwareGLContext::gl_depth_range(GLdouble min, GLdouble max)
  1949. {
  1950. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_depth_range, min, max);
  1951. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1952. auto options = m_rasterizer.options();
  1953. options.depth_min = clamp(min, 0.f, 1.f);
  1954. options.depth_max = clamp(max, 0.f, 1.f);
  1955. m_rasterizer.set_options(options);
  1956. }
  1957. void SoftwareGLContext::gl_depth_func(GLenum func)
  1958. {
  1959. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_depth_func, func);
  1960. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1961. RETURN_WITH_ERROR_IF(!(func == GL_NEVER
  1962. || func == GL_LESS
  1963. || func == GL_EQUAL
  1964. || func == GL_LEQUAL
  1965. || func == GL_GREATER
  1966. || func == GL_NOTEQUAL
  1967. || func == GL_GEQUAL
  1968. || func == GL_ALWAYS),
  1969. GL_INVALID_ENUM);
  1970. auto options = m_rasterizer.options();
  1971. switch (func) {
  1972. case GL_NEVER:
  1973. options.depth_func = SoftGPU::DepthTestFunction::Never;
  1974. break;
  1975. case GL_ALWAYS:
  1976. options.depth_func = SoftGPU::DepthTestFunction::Always;
  1977. break;
  1978. case GL_LESS:
  1979. options.depth_func = SoftGPU::DepthTestFunction::Less;
  1980. break;
  1981. case GL_LEQUAL:
  1982. options.depth_func = SoftGPU::DepthTestFunction::LessOrEqual;
  1983. break;
  1984. case GL_EQUAL:
  1985. options.depth_func = SoftGPU::DepthTestFunction::Equal;
  1986. break;
  1987. case GL_NOTEQUAL:
  1988. options.depth_func = SoftGPU::DepthTestFunction::NotEqual;
  1989. break;
  1990. case GL_GEQUAL:
  1991. options.depth_func = SoftGPU::DepthTestFunction::GreaterOrEqual;
  1992. break;
  1993. case GL_GREATER:
  1994. options.depth_func = SoftGPU::DepthTestFunction::Greater;
  1995. break;
  1996. default:
  1997. VERIFY_NOT_REACHED();
  1998. }
  1999. m_rasterizer.set_options(options);
  2000. }
  2001. // General helper function to read arbitrary vertex attribute data into a float array
  2002. void SoftwareGLContext::read_from_vertex_attribute_pointer(VertexAttribPointer const& attrib, int index, float* elements, bool normalize)
  2003. {
  2004. auto byte_ptr = reinterpret_cast<const char*>(attrib.pointer);
  2005. size_t stride = attrib.stride;
  2006. switch (attrib.type) {
  2007. case GL_BYTE: {
  2008. if (stride == 0)
  2009. stride = sizeof(GLbyte) * attrib.size;
  2010. for (int i = 0; i < attrib.size; i++) {
  2011. elements[i] = *(reinterpret_cast<const GLbyte*>(byte_ptr + stride * index) + i);
  2012. if (normalize)
  2013. elements[i] /= 0x80;
  2014. }
  2015. break;
  2016. }
  2017. case GL_UNSIGNED_BYTE: {
  2018. if (stride == 0)
  2019. stride = sizeof(GLubyte) * attrib.size;
  2020. for (int i = 0; i < attrib.size; i++) {
  2021. elements[i] = *(reinterpret_cast<const GLubyte*>(byte_ptr + stride * index) + i);
  2022. if (normalize)
  2023. elements[i] /= 0xff;
  2024. }
  2025. break;
  2026. }
  2027. case GL_SHORT: {
  2028. if (stride == 0)
  2029. stride = sizeof(GLshort) * attrib.size;
  2030. for (int i = 0; i < attrib.size; i++) {
  2031. elements[i] = *(reinterpret_cast<const GLshort*>(byte_ptr + stride * index) + i);
  2032. if (normalize)
  2033. elements[i] /= 0x8000;
  2034. }
  2035. break;
  2036. }
  2037. case GL_UNSIGNED_SHORT: {
  2038. if (stride == 0)
  2039. stride = sizeof(GLushort) * attrib.size;
  2040. for (int i = 0; i < attrib.size; i++) {
  2041. elements[i] = *(reinterpret_cast<const GLushort*>(byte_ptr + stride * index) + i);
  2042. if (normalize)
  2043. elements[i] /= 0xffff;
  2044. }
  2045. break;
  2046. }
  2047. case GL_INT: {
  2048. if (stride == 0)
  2049. stride = sizeof(GLint) * attrib.size;
  2050. for (int i = 0; i < attrib.size; i++) {
  2051. elements[i] = *(reinterpret_cast<const GLint*>(byte_ptr + stride * index) + i);
  2052. if (normalize)
  2053. elements[i] /= 0x80000000;
  2054. }
  2055. break;
  2056. }
  2057. case GL_UNSIGNED_INT: {
  2058. if (stride == 0)
  2059. stride = sizeof(GLuint) * attrib.size;
  2060. for (int i = 0; i < attrib.size; i++) {
  2061. elements[i] = *(reinterpret_cast<const GLuint*>(byte_ptr + stride * index) + i);
  2062. if (normalize)
  2063. elements[i] /= 0xffffffff;
  2064. }
  2065. break;
  2066. }
  2067. case GL_FLOAT: {
  2068. if (stride == 0)
  2069. stride = sizeof(GLfloat) * attrib.size;
  2070. for (int i = 0; i < attrib.size; i++) {
  2071. elements[i] = *(reinterpret_cast<const GLfloat*>(byte_ptr + stride * index) + i);
  2072. }
  2073. break;
  2074. }
  2075. case GL_DOUBLE: {
  2076. if (stride == 0)
  2077. stride = sizeof(GLdouble) * attrib.size;
  2078. for (int i = 0; i < attrib.size; i++) {
  2079. elements[i] = static_cast<float>(*(reinterpret_cast<const GLdouble*>(byte_ptr + stride * index) + i));
  2080. }
  2081. break;
  2082. }
  2083. }
  2084. }
  2085. void SoftwareGLContext::gl_color_mask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
  2086. {
  2087. auto options = m_rasterizer.options();
  2088. auto mask = options.color_mask;
  2089. if (!red)
  2090. mask &= ~0x000000ff;
  2091. else
  2092. mask |= 0x000000ff;
  2093. if (!green)
  2094. mask &= ~0x0000ff00;
  2095. else
  2096. mask |= 0x0000ff00;
  2097. if (!blue)
  2098. mask &= ~0x00ff0000;
  2099. else
  2100. mask |= 0x00ff0000;
  2101. if (!alpha)
  2102. mask &= ~0xff000000;
  2103. else
  2104. mask |= 0xff000000;
  2105. options.color_mask = mask;
  2106. m_rasterizer.set_options(options);
  2107. }
  2108. void SoftwareGLContext::gl_polygon_mode(GLenum face, GLenum mode)
  2109. {
  2110. RETURN_WITH_ERROR_IF(!(face == GL_BACK || face == GL_FRONT || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM);
  2111. RETURN_WITH_ERROR_IF(!(mode == GL_POINT || mode == GL_LINE || mode == GL_FILL), GL_INVALID_ENUM);
  2112. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2113. auto options = m_rasterizer.options();
  2114. // FIXME: This must support different polygon modes for front- and backside
  2115. switch (mode) {
  2116. case GL_POINT:
  2117. options.polygon_mode = SoftGPU::PolygonMode::Point;
  2118. break;
  2119. case GL_LINE:
  2120. options.polygon_mode = SoftGPU::PolygonMode::Line;
  2121. break;
  2122. case GL_FILL:
  2123. options.polygon_mode = SoftGPU::PolygonMode::Fill;
  2124. break;
  2125. }
  2126. m_rasterizer.set_options(options);
  2127. }
  2128. void SoftwareGLContext::gl_polygon_offset(GLfloat factor, GLfloat units)
  2129. {
  2130. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_polygon_offset, factor, units);
  2131. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2132. auto rasterizer_options = m_rasterizer.options();
  2133. rasterizer_options.depth_offset_factor = factor;
  2134. rasterizer_options.depth_offset_constant = units;
  2135. m_rasterizer.set_options(rasterizer_options);
  2136. }
  2137. void SoftwareGLContext::gl_fogfv(GLenum pname, GLfloat* params)
  2138. {
  2139. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_fogfv, pname, params);
  2140. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2141. auto options = m_rasterizer.options();
  2142. switch (pname) {
  2143. case GL_FOG_COLOR:
  2144. options.fog_color = { params[0], params[1], params[2], params[3] };
  2145. break;
  2146. default:
  2147. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  2148. }
  2149. m_rasterizer.set_options(options);
  2150. }
  2151. void SoftwareGLContext::gl_fogf(GLenum pname, GLfloat param)
  2152. {
  2153. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_fogf, pname, param);
  2154. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2155. RETURN_WITH_ERROR_IF(param < 0.0f, GL_INVALID_VALUE);
  2156. auto options = m_rasterizer.options();
  2157. switch (pname) {
  2158. case GL_FOG_DENSITY:
  2159. options.fog_density = param;
  2160. break;
  2161. case GL_FOG_END:
  2162. options.fog_end = param;
  2163. break;
  2164. case GL_FOG_START:
  2165. options.fog_start = param;
  2166. break;
  2167. default:
  2168. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  2169. }
  2170. m_rasterizer.set_options(options);
  2171. }
  2172. void SoftwareGLContext::gl_fogi(GLenum pname, GLint param)
  2173. {
  2174. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_fogi, pname, param);
  2175. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2176. RETURN_WITH_ERROR_IF(param != GL_LINEAR && param != GL_EXP && param != GL_EXP2, GL_INVALID_ENUM);
  2177. auto options = m_rasterizer.options();
  2178. switch (pname) {
  2179. case GL_FOG_MODE:
  2180. switch (param) {
  2181. case GL_LINEAR:
  2182. options.fog_mode = SoftGPU::FogMode::Linear;
  2183. break;
  2184. case GL_EXP:
  2185. options.fog_mode = SoftGPU::FogMode::Exp;
  2186. break;
  2187. case GL_EXP2:
  2188. options.fog_mode = SoftGPU::FogMode::Exp2;
  2189. break;
  2190. }
  2191. break;
  2192. default:
  2193. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  2194. }
  2195. m_rasterizer.set_options(options);
  2196. }
  2197. void SoftwareGLContext::gl_pixel_storei(GLenum pname, GLint param)
  2198. {
  2199. // FIXME: Implement missing parameters
  2200. switch (pname) {
  2201. case GL_PACK_ALIGNMENT:
  2202. RETURN_WITH_ERROR_IF(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE);
  2203. m_pack_alignment = param;
  2204. break;
  2205. case GL_UNPACK_ROW_LENGTH:
  2206. RETURN_WITH_ERROR_IF(param < 0, GL_INVALID_VALUE);
  2207. m_unpack_row_length = static_cast<size_t>(param);
  2208. break;
  2209. case GL_UNPACK_ALIGNMENT:
  2210. RETURN_WITH_ERROR_IF(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE);
  2211. m_unpack_alignment = param;
  2212. break;
  2213. default:
  2214. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  2215. break;
  2216. }
  2217. }
  2218. void SoftwareGLContext::gl_scissor(GLint x, GLint y, GLsizei width, GLsizei height)
  2219. {
  2220. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_scissor, x, y, width, height);
  2221. RETURN_WITH_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
  2222. auto options = m_rasterizer.options();
  2223. options.scissor_box = { x, y, width, height };
  2224. m_rasterizer.set_options(options);
  2225. }
  2226. void SoftwareGLContext::gl_stencil_func_separate(GLenum face, GLenum func, GLint ref, GLuint mask)
  2227. {
  2228. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_stencil_func_separate, face, func, ref, mask);
  2229. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2230. RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM);
  2231. RETURN_WITH_ERROR_IF(!(func == GL_NEVER
  2232. || func == GL_LESS
  2233. || func == GL_LEQUAL
  2234. || func == GL_GREATER
  2235. || func == GL_GEQUAL
  2236. || func == GL_EQUAL
  2237. || func == GL_NOTEQUAL
  2238. || func == GL_ALWAYS),
  2239. GL_INVALID_ENUM);
  2240. // FIXME: "ref is clamped to the range 02^n - 1 , where n is the number of bitplanes in the stencil buffer"
  2241. StencilFunctionOptions new_options = { func, ref, mask };
  2242. if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
  2243. m_stencil_frontfacing_func = new_options;
  2244. if (face == GL_BACK || face == GL_FRONT_AND_BACK)
  2245. m_stencil_backfacing_func = new_options;
  2246. }
  2247. void SoftwareGLContext::gl_stencil_op_separate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)
  2248. {
  2249. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_stencil_op_separate, face, sfail, dpfail, dppass);
  2250. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2251. RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM);
  2252. RETURN_WITH_ERROR_IF(!(sfail == GL_KEEP
  2253. || sfail == GL_ZERO
  2254. || sfail == GL_REPLACE
  2255. || sfail == GL_INCR
  2256. || sfail == GL_INCR_WRAP
  2257. || sfail == GL_DECR
  2258. || sfail == GL_DECR_WRAP
  2259. || sfail == GL_INVERT),
  2260. GL_INVALID_ENUM);
  2261. RETURN_WITH_ERROR_IF(!(dpfail == GL_KEEP
  2262. || dpfail == GL_ZERO
  2263. || dpfail == GL_REPLACE
  2264. || dpfail == GL_INCR
  2265. || dpfail == GL_INCR_WRAP
  2266. || dpfail == GL_DECR
  2267. || dpfail == GL_DECR_WRAP
  2268. || dpfail == GL_INVERT),
  2269. GL_INVALID_ENUM);
  2270. RETURN_WITH_ERROR_IF(!(dppass == GL_KEEP
  2271. || dppass == GL_ZERO
  2272. || dppass == GL_REPLACE
  2273. || dppass == GL_INCR
  2274. || dppass == GL_INCR_WRAP
  2275. || dppass == GL_DECR
  2276. || dppass == GL_DECR_WRAP
  2277. || dppass == GL_INVERT),
  2278. GL_INVALID_ENUM);
  2279. StencilOperationOptions new_options = { sfail, dpfail, dppass };
  2280. if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
  2281. m_stencil_frontfacing_op = new_options;
  2282. if (face == GL_BACK || face == GL_FRONT_AND_BACK)
  2283. m_stencil_backfacing_op = new_options;
  2284. }
  2285. void SoftwareGLContext::gl_normal(GLfloat nx, GLfloat ny, GLfloat nz)
  2286. {
  2287. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_normal, nx, ny, nz);
  2288. m_current_vertex_normal = { nx, ny, nz };
  2289. }
  2290. void SoftwareGLContext::gl_normal_pointer(GLenum type, GLsizei stride, void const* pointer)
  2291. {
  2292. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2293. RETURN_WITH_ERROR_IF(type != GL_BYTE
  2294. && type != GL_SHORT
  2295. && type != GL_INT
  2296. && type != GL_FLOAT
  2297. && type != GL_DOUBLE,
  2298. GL_INVALID_ENUM);
  2299. RETURN_WITH_ERROR_IF(stride < 0, GL_INVALID_VALUE);
  2300. dbgln_if(GL_DEBUG, "gl_normal_pointer({:#x}, {}, {:p}): unimplemented", type, stride, pointer);
  2301. }
  2302. void SoftwareGLContext::gl_raster_pos(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  2303. {
  2304. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_raster_pos, x, y, z, w);
  2305. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2306. m_rasterizer.set_raster_position({ x, y, z, w }, m_model_view_matrix, m_projection_matrix);
  2307. }
  2308. void SoftwareGLContext::gl_line_width(GLfloat width)
  2309. {
  2310. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_line_width, width);
  2311. RETURN_WITH_ERROR_IF(width <= 0, GL_INVALID_VALUE);
  2312. m_line_width = width;
  2313. }
  2314. void SoftwareGLContext::gl_push_attrib(GLbitfield mask)
  2315. {
  2316. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_push_attrib, mask);
  2317. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2318. // FIXME: implement
  2319. dbgln_if(GL_DEBUG, "SoftwareGLContext FIXME: implement gl_push_attrib({})", mask);
  2320. }
  2321. void SoftwareGLContext::gl_pop_attrib()
  2322. {
  2323. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_pop_attrib);
  2324. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2325. // FIXME: implement
  2326. dbgln_if(GL_DEBUG, "SoftwareGLContext FIXME: implement gl_pop_attrib()");
  2327. }
  2328. void SoftwareGLContext::gl_light_model(GLenum pname, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  2329. {
  2330. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_light_model, pname, x, y, z, w);
  2331. RETURN_WITH_ERROR_IF(!(pname == GL_LIGHT_MODEL_AMBIENT
  2332. || pname == GL_LIGHT_MODEL_TWO_SIDE),
  2333. GL_INVALID_ENUM);
  2334. auto lighting_params = m_rasterizer.light_model();
  2335. bool update_lighting_model = false;
  2336. switch (pname) {
  2337. case GL_LIGHT_MODEL_AMBIENT:
  2338. lighting_params.scene_ambient_color = { x, y, z, w };
  2339. update_lighting_model = true;
  2340. break;
  2341. case GL_LIGHT_MODEL_TWO_SIDE:
  2342. VERIFY(y == 0.0f && z == 0.0f && w == 0.0f);
  2343. lighting_params.two_sided_lighting = x;
  2344. update_lighting_model = true;
  2345. break;
  2346. default:
  2347. VERIFY_NOT_REACHED();
  2348. }
  2349. if (update_lighting_model)
  2350. m_rasterizer.set_light_model_params(lighting_params);
  2351. }
  2352. void SoftwareGLContext::gl_bitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, GLubyte const* bitmap)
  2353. {
  2354. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_bitmap, width, height, xorig, yorig, xmove, ymove, bitmap);
  2355. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2356. if (bitmap != nullptr) {
  2357. // FIXME: implement
  2358. dbgln_if(GL_DEBUG, "gl_bitmap({}, {}, {}, {}, {}, {}, {}): unimplemented", width, height, xorig, yorig, xmove, ymove, bitmap);
  2359. }
  2360. auto raster_position = m_rasterizer.raster_position();
  2361. raster_position.window_coordinates += { xmove, ymove, 0.f, 0.f };
  2362. m_rasterizer.set_raster_position(raster_position);
  2363. }
  2364. void SoftwareGLContext::gl_copy_tex_image_2d(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
  2365. {
  2366. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_copy_tex_image_2d, target, level, internalformat, x, y, width, height, border);
  2367. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2368. // FIXME: implement
  2369. dbgln_if(GL_DEBUG, "SoftwareGLContext FIXME: implement gl_copy_tex_image_2d({:#x}, {}, {:#x}, {}, {}, {}, {}, {})",
  2370. target, level, internalformat, x, y, width, height, border);
  2371. }
  2372. void SoftwareGLContext::gl_get_tex_parameter_integerv(GLenum target, GLint level, GLenum pname, GLint* params)
  2373. {
  2374. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2375. // FIXME: support targets other than GL_TEXTURE_2D
  2376. RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM);
  2377. // FIXME: support other parameter names
  2378. RETURN_WITH_ERROR_IF(pname < GL_TEXTURE_WIDTH || pname > GL_TEXTURE_HEIGHT, GL_INVALID_ENUM);
  2379. RETURN_WITH_ERROR_IF(level < 0 || level > Texture2D::LOG2_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
  2380. // FIXME: GL_INVALID_VALUE is generated if target is GL_TEXTURE_BUFFER and level is not zero
  2381. // FIXME: GL_INVALID_OPERATION is generated if GL_TEXTURE_COMPRESSED_IMAGE_SIZE is queried on texture images with an uncompressed internal format or on proxy targets
  2382. switch (pname) {
  2383. case GL_TEXTURE_HEIGHT:
  2384. *params = m_active_texture_unit->bound_texture_2d()->height_at_lod(level);
  2385. break;
  2386. case GL_TEXTURE_WIDTH:
  2387. *params = m_active_texture_unit->bound_texture_2d()->width_at_lod(level);
  2388. break;
  2389. }
  2390. }
  2391. void SoftwareGLContext::gl_rect(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2)
  2392. {
  2393. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_rect, x1, y1, x2, y2);
  2394. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2395. gl_begin(GL_POLYGON);
  2396. gl_vertex(x1, y1, 0.0, 0.0);
  2397. gl_vertex(x2, y1, 0.0, 0.0);
  2398. gl_vertex(x2, y2, 0.0, 0.0);
  2399. gl_vertex(x1, y2, 0.0, 0.0);
  2400. gl_end();
  2401. }
  2402. void SoftwareGLContext::gl_tex_gen(GLenum coord, GLenum pname, GLint param)
  2403. {
  2404. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_tex_gen, coord, pname, param);
  2405. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2406. RETURN_WITH_ERROR_IF(coord < GL_S || coord > GL_Q, GL_INVALID_ENUM);
  2407. RETURN_WITH_ERROR_IF(pname != GL_TEXTURE_GEN_MODE, GL_INVALID_ENUM);
  2408. RETURN_WITH_ERROR_IF(param != GL_EYE_LINEAR
  2409. && param != GL_OBJECT_LINEAR
  2410. && param != GL_SPHERE_MAP
  2411. && param != GL_NORMAL_MAP
  2412. && param != GL_REFLECTION_MAP,
  2413. GL_INVALID_ENUM);
  2414. RETURN_WITH_ERROR_IF((coord == GL_R || coord == GL_Q) && param == GL_SPHERE_MAP, GL_INVALID_ENUM);
  2415. RETURN_WITH_ERROR_IF(coord == GL_Q && (param == GL_REFLECTION_MAP || param == GL_NORMAL_MAP), GL_INVALID_ENUM);
  2416. GLenum const capability = GL_TEXTURE_GEN_S + (coord - GL_S);
  2417. texture_coordinate_generation(capability).generation_mode = param;
  2418. m_texcoord_generation_dirty = true;
  2419. }
  2420. void SoftwareGLContext::gl_tex_gen_floatv(GLenum coord, GLenum pname, GLfloat const* params)
  2421. {
  2422. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_tex_gen_floatv, coord, pname, params);
  2423. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2424. RETURN_WITH_ERROR_IF(coord < GL_S || coord > GL_Q, GL_INVALID_ENUM);
  2425. RETURN_WITH_ERROR_IF(pname != GL_TEXTURE_GEN_MODE
  2426. && pname != GL_OBJECT_PLANE
  2427. && pname != GL_EYE_PLANE,
  2428. GL_INVALID_ENUM);
  2429. GLenum const capability = GL_TEXTURE_GEN_S + (coord - GL_S);
  2430. switch (pname) {
  2431. case GL_TEXTURE_GEN_MODE: {
  2432. auto param = static_cast<GLenum>(params[0]);
  2433. RETURN_WITH_ERROR_IF(param != GL_EYE_LINEAR
  2434. && param != GL_OBJECT_LINEAR
  2435. && param != GL_SPHERE_MAP
  2436. && param != GL_NORMAL_MAP
  2437. && param != GL_REFLECTION_MAP,
  2438. GL_INVALID_ENUM);
  2439. RETURN_WITH_ERROR_IF((coord == GL_R || coord == GL_Q) && param == GL_SPHERE_MAP, GL_INVALID_ENUM);
  2440. RETURN_WITH_ERROR_IF(coord == GL_Q && (param == GL_REFLECTION_MAP || param == GL_NORMAL_MAP), GL_INVALID_ENUM);
  2441. texture_coordinate_generation(capability).generation_mode = param;
  2442. break;
  2443. }
  2444. case GL_OBJECT_PLANE:
  2445. texture_coordinate_generation(capability).object_plane_coefficients = { params[0], params[1], params[2], params[3] };
  2446. break;
  2447. case GL_EYE_PLANE: {
  2448. auto const& inverse_model_view = m_model_view_matrix.inverse();
  2449. auto input_coefficients = FloatVector4 { params[0], params[1], params[2], params[3] };
  2450. // Note: we are allowed to store transformed coefficients here, according to the documentation on
  2451. // `glGetTexGen`:
  2452. //
  2453. // "The returned values are those maintained in eye coordinates. They are not equal to the values
  2454. // specified using glTexGen, unless the modelview matrix was identity when glTexGen was called."
  2455. texture_coordinate_generation(capability).eye_plane_coefficients = inverse_model_view * input_coefficients;
  2456. break;
  2457. }
  2458. default:
  2459. VERIFY_NOT_REACHED();
  2460. }
  2461. m_texcoord_generation_dirty = true;
  2462. }
  2463. void SoftwareGLContext::present()
  2464. {
  2465. m_rasterizer.blit_to(*m_frontbuffer);
  2466. }
  2467. void SoftwareGLContext::sync_device_config()
  2468. {
  2469. sync_device_sampler_config();
  2470. sync_device_texcoord_config();
  2471. sync_light_state();
  2472. }
  2473. void SoftwareGLContext::sync_device_sampler_config()
  2474. {
  2475. if (!m_sampler_config_is_dirty)
  2476. return;
  2477. m_sampler_config_is_dirty = false;
  2478. for (unsigned i = 0; i < m_texture_units.size(); ++i) {
  2479. SoftGPU::SamplerConfig config;
  2480. if (!m_texture_units[i].texture_2d_enabled())
  2481. continue;
  2482. auto texture = m_texture_units[i].bound_texture_2d();
  2483. config.bound_image = texture.is_null() ? nullptr : texture->device_image();
  2484. auto const& sampler = texture->sampler();
  2485. switch (sampler.min_filter()) {
  2486. case GL_NEAREST:
  2487. config.texture_min_filter = SoftGPU::TextureFilter::Nearest;
  2488. config.mipmap_filter = SoftGPU::MipMapFilter::None;
  2489. break;
  2490. case GL_LINEAR:
  2491. config.texture_min_filter = SoftGPU::TextureFilter::Linear;
  2492. config.mipmap_filter = SoftGPU::MipMapFilter::None;
  2493. break;
  2494. case GL_NEAREST_MIPMAP_NEAREST:
  2495. config.texture_min_filter = SoftGPU::TextureFilter::Nearest;
  2496. config.mipmap_filter = SoftGPU::MipMapFilter::Nearest;
  2497. break;
  2498. case GL_LINEAR_MIPMAP_NEAREST:
  2499. config.texture_min_filter = SoftGPU::TextureFilter::Nearest;
  2500. config.mipmap_filter = SoftGPU::MipMapFilter::Linear;
  2501. break;
  2502. case GL_NEAREST_MIPMAP_LINEAR:
  2503. config.texture_min_filter = SoftGPU::TextureFilter::Linear;
  2504. config.mipmap_filter = SoftGPU::MipMapFilter::Nearest;
  2505. break;
  2506. case GL_LINEAR_MIPMAP_LINEAR:
  2507. config.texture_min_filter = SoftGPU::TextureFilter::Linear;
  2508. config.mipmap_filter = SoftGPU::MipMapFilter::Linear;
  2509. break;
  2510. default:
  2511. VERIFY_NOT_REACHED();
  2512. }
  2513. switch (sampler.mag_filter()) {
  2514. case GL_NEAREST:
  2515. config.texture_mag_filter = SoftGPU::TextureFilter::Nearest;
  2516. break;
  2517. case GL_LINEAR:
  2518. config.texture_mag_filter = SoftGPU::TextureFilter::Linear;
  2519. break;
  2520. default:
  2521. VERIFY_NOT_REACHED();
  2522. }
  2523. switch (sampler.wrap_s_mode()) {
  2524. case GL_CLAMP:
  2525. config.texture_wrap_u = SoftGPU::TextureWrapMode::Clamp;
  2526. break;
  2527. case GL_CLAMP_TO_BORDER:
  2528. config.texture_wrap_u = SoftGPU::TextureWrapMode::ClampToBorder;
  2529. break;
  2530. case GL_CLAMP_TO_EDGE:
  2531. config.texture_wrap_u = SoftGPU::TextureWrapMode::ClampToEdge;
  2532. break;
  2533. case GL_REPEAT:
  2534. config.texture_wrap_u = SoftGPU::TextureWrapMode::Repeat;
  2535. break;
  2536. case GL_MIRRORED_REPEAT:
  2537. config.texture_wrap_u = SoftGPU::TextureWrapMode::MirroredRepeat;
  2538. break;
  2539. default:
  2540. VERIFY_NOT_REACHED();
  2541. }
  2542. switch (sampler.wrap_t_mode()) {
  2543. case GL_CLAMP:
  2544. config.texture_wrap_v = SoftGPU::TextureWrapMode::Clamp;
  2545. break;
  2546. case GL_CLAMP_TO_BORDER:
  2547. config.texture_wrap_v = SoftGPU::TextureWrapMode::ClampToBorder;
  2548. break;
  2549. case GL_CLAMP_TO_EDGE:
  2550. config.texture_wrap_v = SoftGPU::TextureWrapMode::ClampToEdge;
  2551. break;
  2552. case GL_REPEAT:
  2553. config.texture_wrap_v = SoftGPU::TextureWrapMode::Repeat;
  2554. break;
  2555. case GL_MIRRORED_REPEAT:
  2556. config.texture_wrap_v = SoftGPU::TextureWrapMode::MirroredRepeat;
  2557. break;
  2558. default:
  2559. VERIFY_NOT_REACHED();
  2560. }
  2561. switch (m_texture_units[i].env_mode()) {
  2562. case GL_MODULATE:
  2563. config.fixed_function_texture_env_mode = SoftGPU::TextureEnvMode::Modulate;
  2564. break;
  2565. case GL_REPLACE:
  2566. config.fixed_function_texture_env_mode = SoftGPU::TextureEnvMode::Replace;
  2567. break;
  2568. case GL_DECAL:
  2569. config.fixed_function_texture_env_mode = SoftGPU::TextureEnvMode::Decal;
  2570. break;
  2571. default:
  2572. VERIFY_NOT_REACHED();
  2573. }
  2574. m_rasterizer.set_sampler_config(i, config);
  2575. }
  2576. }
  2577. void SoftwareGLContext::sync_light_state()
  2578. {
  2579. if (!m_light_state_is_dirty)
  2580. return;
  2581. m_light_state_is_dirty = false;
  2582. auto options = m_rasterizer.options();
  2583. options.color_material_enabled = m_color_material_enabled;
  2584. switch (m_color_material_face) {
  2585. case GL_BACK:
  2586. options.color_material_face = SoftGPU::ColorMaterialFace::Back;
  2587. break;
  2588. case GL_FRONT:
  2589. options.color_material_face = SoftGPU::ColorMaterialFace::Front;
  2590. break;
  2591. case GL_FRONT_AND_BACK:
  2592. options.color_material_face = SoftGPU::ColorMaterialFace::FrontAndBack;
  2593. break;
  2594. default:
  2595. VERIFY_NOT_REACHED();
  2596. }
  2597. switch (m_color_material_mode) {
  2598. case GL_AMBIENT:
  2599. options.color_material_mode = SoftGPU::ColorMaterialMode::Ambient;
  2600. break;
  2601. case GL_AMBIENT_AND_DIFFUSE:
  2602. options.color_material_mode = SoftGPU::ColorMaterialMode::Ambient;
  2603. options.color_material_mode = SoftGPU::ColorMaterialMode::Diffuse;
  2604. break;
  2605. case GL_DIFFUSE:
  2606. options.color_material_mode = SoftGPU::ColorMaterialMode::Diffuse;
  2607. break;
  2608. case GL_EMISSION:
  2609. options.color_material_mode = SoftGPU::ColorMaterialMode::Emissive;
  2610. break;
  2611. case GL_SPECULAR:
  2612. options.color_material_mode = SoftGPU::ColorMaterialMode::Specular;
  2613. break;
  2614. default:
  2615. VERIFY_NOT_REACHED();
  2616. }
  2617. m_rasterizer.set_options(options);
  2618. for (auto light_id = 0u; light_id < SoftGPU::NUM_LIGHTS; light_id++) {
  2619. SoftGPU::Light light;
  2620. auto const& current_light_state = m_light_states.at(light_id);
  2621. light.is_enabled = current_light_state.is_enabled;
  2622. light.ambient_intensity = current_light_state.ambient_intensity;
  2623. light.diffuse_intensity = current_light_state.diffuse_intensity;
  2624. light.specular_intensity = current_light_state.specular_intensity;
  2625. light.position = current_light_state.position;
  2626. light.spotlight_direction = current_light_state.spotlight_direction;
  2627. light.spotlight_exponent = current_light_state.spotlight_exponent;
  2628. light.spotlight_cutoff_angle = current_light_state.spotlight_cutoff_angle;
  2629. light.constant_attenuation = current_light_state.constant_attenuation;
  2630. light.linear_attenuation = current_light_state.linear_attenuation;
  2631. light.quadratic_attenuation = current_light_state.quadratic_attenuation;
  2632. m_rasterizer.set_light_state(light_id, light);
  2633. }
  2634. for (auto material_id = 0u; material_id < 2u; material_id++) {
  2635. SoftGPU::Material material;
  2636. auto const& current_material_state = m_material_states.at(material_id);
  2637. material.ambient = current_material_state.ambient;
  2638. material.diffuse = current_material_state.diffuse;
  2639. material.specular = current_material_state.specular;
  2640. material.emissive = current_material_state.emissive;
  2641. material.shininess = current_material_state.shininess;
  2642. material.specular_exponent = current_material_state.specular_exponent;
  2643. material.ambient_color_index = current_material_state.ambient_color_index;
  2644. material.diffuse_color_index = current_material_state.diffuse_color_index;
  2645. material.specular_color_index = current_material_state.specular_color_index;
  2646. m_rasterizer.set_material_state(material_id, material);
  2647. }
  2648. }
  2649. void SoftwareGLContext::sync_device_texcoord_config()
  2650. {
  2651. if (!m_texcoord_generation_dirty)
  2652. return;
  2653. m_texcoord_generation_dirty = false;
  2654. auto options = m_rasterizer.options();
  2655. u8 enabled_coordinates = SoftGPU::TexCoordGenerationCoordinate::None;
  2656. for (GLenum capability = GL_TEXTURE_GEN_S; capability <= GL_TEXTURE_GEN_Q; ++capability) {
  2657. auto const context_coordinate_config = texture_coordinate_generation(capability);
  2658. if (!context_coordinate_config.enabled)
  2659. continue;
  2660. SoftGPU::TexCoordGenerationConfig* texcoord_generation_config;
  2661. switch (capability) {
  2662. case GL_TEXTURE_GEN_S:
  2663. enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::S;
  2664. texcoord_generation_config = &options.texcoord_generation_config[0];
  2665. break;
  2666. case GL_TEXTURE_GEN_T:
  2667. enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::T;
  2668. texcoord_generation_config = &options.texcoord_generation_config[1];
  2669. break;
  2670. case GL_TEXTURE_GEN_R:
  2671. enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::R;
  2672. texcoord_generation_config = &options.texcoord_generation_config[2];
  2673. break;
  2674. case GL_TEXTURE_GEN_Q:
  2675. enabled_coordinates |= SoftGPU::TexCoordGenerationCoordinate::Q;
  2676. texcoord_generation_config = &options.texcoord_generation_config[3];
  2677. break;
  2678. default:
  2679. VERIFY_NOT_REACHED();
  2680. }
  2681. switch (context_coordinate_config.generation_mode) {
  2682. case GL_OBJECT_LINEAR:
  2683. texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::ObjectLinear;
  2684. texcoord_generation_config->coefficients = context_coordinate_config.object_plane_coefficients;
  2685. break;
  2686. case GL_EYE_LINEAR:
  2687. texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::EyeLinear;
  2688. texcoord_generation_config->coefficients = context_coordinate_config.eye_plane_coefficients;
  2689. break;
  2690. case GL_SPHERE_MAP:
  2691. texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::SphereMap;
  2692. break;
  2693. case GL_REFLECTION_MAP:
  2694. texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::ReflectionMap;
  2695. break;
  2696. case GL_NORMAL_MAP:
  2697. texcoord_generation_config->mode = SoftGPU::TexCoordGenerationMode::NormalMap;
  2698. break;
  2699. }
  2700. }
  2701. options.texcoord_generation_enabled_coordinates = enabled_coordinates;
  2702. m_rasterizer.set_options(options);
  2703. }
  2704. void SoftwareGLContext::gl_lightf(GLenum light, GLenum pname, GLfloat param)
  2705. {
  2706. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_lightf, light, pname, param);
  2707. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2708. RETURN_WITH_ERROR_IF(light < GL_LIGHT0 || light >= (GL_LIGHT0 + m_rasterizer.info().num_lights), GL_INVALID_ENUM);
  2709. RETURN_WITH_ERROR_IF(!(pname == GL_CONSTANT_ATTENUATION || pname == GL_LINEAR_ATTENUATION || pname == GL_QUADRATIC_ATTENUATION || pname != GL_SPOT_EXPONENT || pname != GL_SPOT_CUTOFF), GL_INVALID_ENUM);
  2710. auto& light_state = m_light_states.at(light - GL_LIGHT0);
  2711. switch (pname) {
  2712. case GL_CONSTANT_ATTENUATION:
  2713. light_state.constant_attenuation = param;
  2714. break;
  2715. case GL_LINEAR_ATTENUATION:
  2716. light_state.linear_attenuation = param;
  2717. break;
  2718. case GL_QUADRATIC_ATTENUATION:
  2719. light_state.quadratic_attenuation = param;
  2720. break;
  2721. case GL_SPOT_EXPONENT:
  2722. light_state.spotlight_exponent = param;
  2723. break;
  2724. case GL_SPOT_CUTOFF:
  2725. light_state.spotlight_cutoff_angle = param;
  2726. break;
  2727. default:
  2728. VERIFY_NOT_REACHED();
  2729. }
  2730. m_light_state_is_dirty = true;
  2731. }
  2732. void SoftwareGLContext::gl_lightfv(GLenum light, GLenum pname, GLfloat const* params)
  2733. {
  2734. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_lightfv, light, pname, params);
  2735. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2736. RETURN_WITH_ERROR_IF(light < GL_LIGHT0 || light >= (GL_LIGHT0 + m_rasterizer.info().num_lights), GL_INVALID_ENUM);
  2737. RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_POSITION || pname == GL_CONSTANT_ATTENUATION || pname == GL_LINEAR_ATTENUATION || pname == GL_QUADRATIC_ATTENUATION || pname == GL_SPOT_CUTOFF || pname == GL_SPOT_EXPONENT || pname == GL_SPOT_DIRECTION), GL_INVALID_ENUM);
  2738. auto& light_state = m_light_states.at(light - GL_LIGHT0);
  2739. switch (pname) {
  2740. case GL_AMBIENT:
  2741. light_state.ambient_intensity = { params[0], params[1], params[2], params[3] };
  2742. break;
  2743. case GL_DIFFUSE:
  2744. light_state.diffuse_intensity = { params[0], params[1], params[2], params[3] };
  2745. break;
  2746. case GL_SPECULAR:
  2747. light_state.specular_intensity = { params[0], params[1], params[2], params[3] };
  2748. break;
  2749. case GL_POSITION:
  2750. light_state.position = { params[0], params[1], params[2], params[3] };
  2751. light_state.position = m_model_view_matrix * light_state.position;
  2752. break;
  2753. case GL_CONSTANT_ATTENUATION:
  2754. light_state.constant_attenuation = *params;
  2755. break;
  2756. case GL_LINEAR_ATTENUATION:
  2757. light_state.linear_attenuation = *params;
  2758. break;
  2759. case GL_QUADRATIC_ATTENUATION:
  2760. light_state.quadratic_attenuation = *params;
  2761. break;
  2762. case GL_SPOT_EXPONENT:
  2763. light_state.spotlight_exponent = *params;
  2764. break;
  2765. case GL_SPOT_CUTOFF:
  2766. light_state.spotlight_cutoff_angle = *params;
  2767. break;
  2768. case GL_SPOT_DIRECTION: {
  2769. FloatVector4 direction_vector = { params[0], params[1], params[2], 0.0f };
  2770. direction_vector = m_model_view_matrix * direction_vector;
  2771. light_state.spotlight_direction = { direction_vector.x(), direction_vector.y(), direction_vector.z() };
  2772. break;
  2773. }
  2774. default:
  2775. VERIFY_NOT_REACHED();
  2776. }
  2777. m_light_state_is_dirty = true;
  2778. }
  2779. void SoftwareGLContext::gl_materialf(GLenum face, GLenum pname, GLfloat param)
  2780. {
  2781. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_materialf, face, pname, param);
  2782. RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM);
  2783. RETURN_WITH_ERROR_IF(pname != GL_SHININESS, GL_INVALID_ENUM);
  2784. RETURN_WITH_ERROR_IF(param > 128.0f, GL_INVALID_VALUE);
  2785. switch (face) {
  2786. case GL_FRONT:
  2787. m_material_states.at(MaterialFace::Front).shininess = param;
  2788. break;
  2789. case GL_BACK:
  2790. m_material_states.at(MaterialFace::Back).shininess = param;
  2791. break;
  2792. case GL_FRONT_AND_BACK:
  2793. m_material_states.at(MaterialFace::Front).shininess = param;
  2794. m_material_states.at(MaterialFace::Back).shininess = param;
  2795. break;
  2796. default:
  2797. VERIFY_NOT_REACHED();
  2798. }
  2799. m_light_state_is_dirty = true;
  2800. }
  2801. void SoftwareGLContext::gl_materialfv(GLenum face, GLenum pname, GLfloat const* params)
  2802. {
  2803. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_materialfv, face, pname, params);
  2804. RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM);
  2805. RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_EMISSION || pname == GL_SHININESS || pname == GL_AMBIENT_AND_DIFFUSE), GL_INVALID_ENUM);
  2806. RETURN_WITH_ERROR_IF((pname == GL_SHININESS && *params > 128.0f), GL_INVALID_VALUE);
  2807. auto update_material = [](SoftGPU::Material& material, GLenum pname, GLfloat const* params) {
  2808. switch (pname) {
  2809. case GL_AMBIENT:
  2810. material.ambient = { params[0], params[1], params[2], params[3] };
  2811. break;
  2812. case GL_DIFFUSE:
  2813. material.diffuse = { params[0], params[1], params[2], params[3] };
  2814. break;
  2815. case GL_SPECULAR:
  2816. material.specular = { params[0], params[1], params[2], params[3] };
  2817. break;
  2818. case GL_EMISSION:
  2819. material.emissive = { params[0], params[1], params[2], params[3] };
  2820. break;
  2821. case GL_SHININESS:
  2822. material.shininess = *params;
  2823. break;
  2824. case GL_AMBIENT_AND_DIFFUSE:
  2825. material.ambient = { params[0], params[1], params[2], params[3] };
  2826. material.diffuse = { params[0], params[1], params[2], params[3] };
  2827. break;
  2828. }
  2829. };
  2830. switch (face) {
  2831. case GL_FRONT:
  2832. update_material(m_material_states.at(MaterialFace::Front), pname, params);
  2833. break;
  2834. case GL_BACK:
  2835. update_material(m_material_states.at(MaterialFace::Back), pname, params);
  2836. break;
  2837. case GL_FRONT_AND_BACK:
  2838. update_material(m_material_states.at(MaterialFace::Front), pname, params);
  2839. update_material(m_material_states.at(MaterialFace::Back), pname, params);
  2840. break;
  2841. }
  2842. m_light_state_is_dirty = true;
  2843. }
  2844. void SoftwareGLContext::gl_color_material(GLenum face, GLenum mode)
  2845. {
  2846. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_color_material, face, mode);
  2847. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2848. RETURN_WITH_ERROR_IF(face != GL_FRONT
  2849. && face != GL_BACK
  2850. && face != GL_FRONT_AND_BACK,
  2851. GL_INVALID_ENUM);
  2852. RETURN_WITH_ERROR_IF(mode != GL_EMISSION
  2853. && mode != GL_AMBIENT
  2854. && mode != GL_DIFFUSE
  2855. && mode != GL_SPECULAR
  2856. && mode != GL_AMBIENT_AND_DIFFUSE,
  2857. GL_INVALID_ENUM);
  2858. m_color_material_face = face;
  2859. m_color_material_mode = mode;
  2860. m_light_state_is_dirty = true;
  2861. }
  2862. }