SoftwareGLContext.cpp 95 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599
  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 "SoftwareGLContext.h"
  8. #include "GLStruct.h"
  9. #include "SoftwareRasterizer.h"
  10. #include <AK/Assertions.h>
  11. #include <AK/Debug.h>
  12. #include <AK/Format.h>
  13. #include <AK/QuickSort.h>
  14. #include <AK/TemporaryChange.h>
  15. #include <AK/Variant.h>
  16. #include <AK/Vector.h>
  17. #include <LibGfx/Bitmap.h>
  18. #include <LibGfx/Painter.h>
  19. #include <LibGfx/Vector4.h>
  20. using AK::dbgln;
  21. namespace GL {
  22. static constexpr size_t MODELVIEW_MATRIX_STACK_LIMIT = 64;
  23. static constexpr size_t PROJECTION_MATRIX_STACK_LIMIT = 8;
  24. static constexpr size_t TEXTURE_MATRIX_STACK_LIMIT = 8;
  25. #define APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(name, ...) \
  26. if (should_append_to_listing()) { \
  27. append_to_listing<&SoftwareGLContext::name>(__VA_ARGS__); \
  28. if (!should_execute_after_appending_to_listing()) \
  29. return; \
  30. }
  31. #define APPEND_TO_CALL_LIST_WITH_ARG_AND_RETURN_IF_NEEDED(name, arg) \
  32. if (should_append_to_listing()) { \
  33. auto ptr = store_in_listing(arg); \
  34. append_to_listing<&SoftwareGLContext::name>(*ptr); \
  35. if (!should_execute_after_appending_to_listing()) \
  36. return; \
  37. }
  38. #define RETURN_WITH_ERROR_IF(condition, error) \
  39. if (condition) { \
  40. if (m_error == GL_NO_ERROR) \
  41. m_error = error; \
  42. return; \
  43. }
  44. #define RETURN_VALUE_WITH_ERROR_IF(condition, error, return_value) \
  45. if (condition) { \
  46. if (m_error == GL_NO_ERROR) \
  47. m_error = error; \
  48. return return_value; \
  49. }
  50. SoftwareGLContext::SoftwareGLContext(Gfx::Bitmap& frontbuffer)
  51. : m_frontbuffer(frontbuffer)
  52. , m_rasterizer(frontbuffer.size())
  53. {
  54. }
  55. Optional<ContextParameter> SoftwareGLContext::get_context_parameter(GLenum name)
  56. {
  57. switch (name) {
  58. case GL_ALPHA_BITS:
  59. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  60. case GL_ALPHA_TEST:
  61. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_alpha_test_enabled } };
  62. case GL_BLEND:
  63. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_blend_enabled } };
  64. case GL_BLEND_DST_ALPHA:
  65. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_destination_factor) } };
  66. case GL_BLEND_SRC_ALPHA:
  67. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_source_factor) } };
  68. case GL_BLUE_BITS:
  69. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  70. case GL_CULL_FACE:
  71. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_cull_faces } };
  72. case GL_DEPTH_BITS:
  73. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  74. case GL_DEPTH_TEST:
  75. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_depth_test_enabled } };
  76. case GL_DITHER:
  77. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_dither_enabled } };
  78. case GL_DOUBLEBUFFER:
  79. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = true } };
  80. case GL_GREEN_BITS:
  81. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  82. case GL_LIGHTING:
  83. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_lighting_enabled } };
  84. case GL_MAX_MODELVIEW_STACK_DEPTH:
  85. return ContextParameter { .type = GL_INT, .value = { .integer_value = MODELVIEW_MATRIX_STACK_LIMIT } };
  86. case GL_MAX_PROJECTION_STACK_DEPTH:
  87. return ContextParameter { .type = GL_INT, .value = { .integer_value = PROJECTION_MATRIX_STACK_LIMIT } };
  88. case GL_MAX_TEXTURE_SIZE:
  89. return ContextParameter { .type = GL_INT, .value = { .integer_value = 4096 } };
  90. case GL_MAX_TEXTURE_STACK_DEPTH:
  91. return ContextParameter { .type = GL_INT, .value = { .integer_value = TEXTURE_MATRIX_STACK_LIMIT } };
  92. case GL_MAX_TEXTURE_UNITS:
  93. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_texture_units.size()) } };
  94. case GL_PACK_ALIGNMENT:
  95. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_pack_alignment } };
  96. case GL_RED_BITS:
  97. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  98. case GL_SCISSOR_BOX: {
  99. auto scissor_box = m_rasterizer.options().scissor_box;
  100. return ContextParameter {
  101. .type = GL_INT,
  102. .count = 4,
  103. .value = {
  104. .integer_list = {
  105. scissor_box.x(),
  106. scissor_box.y(),
  107. scissor_box.width(),
  108. scissor_box.height(),
  109. } }
  110. };
  111. } break;
  112. case GL_STENCIL_BITS:
  113. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  114. case GL_STENCIL_TEST:
  115. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_stencil_test_enabled } };
  116. case GL_TEXTURE_1D:
  117. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_1d_enabled() } };
  118. case GL_TEXTURE_2D:
  119. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_2d_enabled() } };
  120. case GL_TEXTURE_3D:
  121. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_3d_enabled() } };
  122. case GL_TEXTURE_CUBE_MAP:
  123. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_cube_map_enabled() } };
  124. case GL_UNPACK_ALIGNMENT:
  125. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpack_alignment } };
  126. case GL_UNPACK_ROW_LENGTH:
  127. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpack_row_length } };
  128. default:
  129. dbgln_if(GL_DEBUG, "get_context_parameter({:#x}): unknown context parameter", name);
  130. return {};
  131. }
  132. }
  133. void SoftwareGLContext::gl_begin(GLenum mode)
  134. {
  135. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_begin, mode);
  136. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  137. RETURN_WITH_ERROR_IF(mode < GL_TRIANGLES || mode > GL_POLYGON, GL_INVALID_ENUM);
  138. m_current_draw_mode = mode;
  139. m_in_draw_state = true; // Certain commands will now generate an error
  140. }
  141. void SoftwareGLContext::gl_clear(GLbitfield mask)
  142. {
  143. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_clear, mask);
  144. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  145. RETURN_WITH_ERROR_IF(mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT), GL_INVALID_ENUM);
  146. if (mask & GL_COLOR_BUFFER_BIT)
  147. m_rasterizer.clear_color(m_clear_color);
  148. if (mask & GL_DEPTH_BUFFER_BIT)
  149. m_rasterizer.clear_depth(static_cast<float>(m_clear_depth));
  150. // FIXME: implement GL_STENCIL_BUFFER_BIT
  151. }
  152. void SoftwareGLContext::gl_clear_color(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
  153. {
  154. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_clear_color, red, green, blue, alpha);
  155. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  156. m_clear_color = { red, green, blue, alpha };
  157. }
  158. void SoftwareGLContext::gl_clear_depth(GLdouble depth)
  159. {
  160. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_clear_depth, depth);
  161. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  162. m_clear_depth = depth;
  163. }
  164. void SoftwareGLContext::gl_clear_stencil(GLint s)
  165. {
  166. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_clear_stencil, s);
  167. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  168. // FIXME: "s is masked with 2^m - 1 , where m is the number of bits in the stencil buffer"
  169. m_clear_stencil = s;
  170. }
  171. void SoftwareGLContext::gl_color(GLdouble r, GLdouble g, GLdouble b, GLdouble a)
  172. {
  173. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_color, r, g, b, a);
  174. m_current_vertex_color = { (float)r, (float)g, (float)b, (float)a };
  175. }
  176. void SoftwareGLContext::gl_end()
  177. {
  178. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_end);
  179. // At this point, the user has effectively specified that they are done with defining the geometry
  180. // of what they want to draw. We now need to do a few things (https://www.khronos.org/opengl/wiki/Rendering_Pipeline_Overview):
  181. //
  182. // 1. Transform all of the vertices in the current vertex list into eye space by mulitplying the model-view matrix
  183. // 2. Transform all of the vertices from eye space into clip space by multiplying by the projection matrix
  184. // 3. If culling is enabled, we cull the desired faces (https://learnopengl.com/Advanced-OpenGL/Face-culling)
  185. // 4. Each element of the vertex is then divided by w to bring the positions into NDC (Normalized Device Coordinates)
  186. // 5. The vertices are sorted (for the rasteriser, how are we doing this? 3Dfx did this top to bottom in terms of vertex y coordinates)
  187. // 6. The vertices are then sent off to the rasteriser and drawn to the screen
  188. float scr_width = m_frontbuffer->width();
  189. float scr_height = m_frontbuffer->height();
  190. // Make sure we had a `glBegin` before this call...
  191. RETURN_WITH_ERROR_IF(!m_in_draw_state, GL_INVALID_OPERATION);
  192. m_in_draw_state = false;
  193. triangle_list.clear_with_capacity();
  194. processed_triangles.clear_with_capacity();
  195. // Let's construct some triangles
  196. if (m_current_draw_mode == GL_TRIANGLES) {
  197. GLTriangle triangle;
  198. for (size_t i = 0; i < vertex_list.size(); i += 3) {
  199. triangle.vertices[0] = vertex_list.at(i);
  200. triangle.vertices[1] = vertex_list.at(i + 1);
  201. triangle.vertices[2] = vertex_list.at(i + 2);
  202. triangle_list.append(triangle);
  203. }
  204. } else if (m_current_draw_mode == GL_QUADS) {
  205. // We need to construct two triangles to form the quad
  206. GLTriangle triangle;
  207. VERIFY(vertex_list.size() % 4 == 0);
  208. for (size_t i = 0; i < vertex_list.size(); i += 4) {
  209. // Triangle 1
  210. triangle.vertices[0] = vertex_list.at(i);
  211. triangle.vertices[1] = vertex_list.at(i + 1);
  212. triangle.vertices[2] = vertex_list.at(i + 2);
  213. triangle_list.append(triangle);
  214. // Triangle 2
  215. triangle.vertices[0] = vertex_list.at(i + 2);
  216. triangle.vertices[1] = vertex_list.at(i + 3);
  217. triangle.vertices[2] = vertex_list.at(i);
  218. triangle_list.append(triangle);
  219. }
  220. } else if (m_current_draw_mode == GL_TRIANGLE_FAN || m_current_draw_mode == GL_POLYGON) {
  221. GLTriangle triangle;
  222. triangle.vertices[0] = vertex_list.at(0); // Root vertex is always the vertex defined first
  223. for (size_t i = 1; i < vertex_list.size() - 1; i++) // This is technically `n-2` triangles. We start at index 1
  224. {
  225. triangle.vertices[1] = vertex_list.at(i);
  226. triangle.vertices[2] = vertex_list.at(i + 1);
  227. triangle_list.append(triangle);
  228. }
  229. } else if (m_current_draw_mode == GL_TRIANGLE_STRIP) {
  230. GLTriangle triangle;
  231. for (size_t i = 0; i < vertex_list.size() - 2; i++) {
  232. triangle.vertices[0] = vertex_list.at(i);
  233. triangle.vertices[1] = vertex_list.at(i + 1);
  234. triangle.vertices[2] = vertex_list.at(i + 2);
  235. triangle_list.append(triangle);
  236. }
  237. } else {
  238. vertex_list.clear_with_capacity();
  239. dbgln_if(GL_DEBUG, "gl_end: draw mode {:#x} unsupported", m_current_draw_mode);
  240. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  241. }
  242. vertex_list.clear_with_capacity();
  243. auto mvp = m_projection_matrix * m_model_view_matrix;
  244. // Now let's transform each triangle and send that to the GPU
  245. for (size_t i = 0; i < triangle_list.size(); i++) {
  246. GLTriangle& triangle = triangle_list.at(i);
  247. // First multiply the vertex by the MODELVIEW matrix and then the PROJECTION matrix
  248. triangle.vertices[0].position = mvp * triangle.vertices[0].position;
  249. triangle.vertices[1].position = mvp * triangle.vertices[1].position;
  250. triangle.vertices[2].position = mvp * triangle.vertices[2].position;
  251. // Apply texture transformation
  252. // FIXME: implement multi-texturing: texcoords should be stored per texture unit
  253. triangle.vertices[0].tex_coord = m_texture_matrix * triangle.vertices[0].tex_coord;
  254. triangle.vertices[1].tex_coord = m_texture_matrix * triangle.vertices[1].tex_coord;
  255. triangle.vertices[2].tex_coord = m_texture_matrix * triangle.vertices[2].tex_coord;
  256. // At this point, we're in clip space
  257. // Here's where we do the clipping. This is a really crude implementation of the
  258. // https://learnopengl.com/Getting-started/Coordinate-Systems
  259. // "Note that if only a part of a primitive e.g. a triangle is outside the clipping volume OpenGL
  260. // will reconstruct the triangle as one or more triangles to fit inside the clipping range. "
  261. //
  262. // ALL VERTICES ARE DEFINED IN A CLOCKWISE ORDER
  263. // Okay, let's do some face culling first
  264. m_clipped_vertices.clear_with_capacity();
  265. m_clipped_vertices.append(triangle.vertices[0]);
  266. m_clipped_vertices.append(triangle.vertices[1]);
  267. m_clipped_vertices.append(triangle.vertices[2]);
  268. m_clipper.clip_triangle_against_frustum(m_clipped_vertices);
  269. if (m_clipped_vertices.size() < 3)
  270. continue;
  271. for (auto& vec : m_clipped_vertices) {
  272. // perspective divide
  273. float w = vec.position.w();
  274. vec.position.set_x(vec.position.x() / w);
  275. vec.position.set_y(vec.position.y() / w);
  276. vec.position.set_z(vec.position.z() / w);
  277. vec.position.set_w(1 / w);
  278. // to screen space
  279. vec.position.set_x(scr_width / 2 + vec.position.x() * scr_width / 2);
  280. vec.position.set_y(scr_height / 2 - vec.position.y() * scr_height / 2);
  281. }
  282. GLTriangle tri;
  283. tri.vertices[0] = m_clipped_vertices[0];
  284. for (size_t i = 1; i < m_clipped_vertices.size() - 1; i++) {
  285. tri.vertices[1] = m_clipped_vertices[i];
  286. tri.vertices[2] = m_clipped_vertices[i + 1];
  287. processed_triangles.append(tri);
  288. }
  289. }
  290. m_bound_texture_units.clear();
  291. for (auto& texture_unit : m_texture_units) {
  292. if (texture_unit.is_bound())
  293. m_bound_texture_units.append(texture_unit);
  294. }
  295. for (size_t i = 0; i < processed_triangles.size(); i++) {
  296. GLTriangle& triangle = processed_triangles.at(i);
  297. // Let's calculate the (signed) area of the triangle
  298. // https://cp-algorithms.com/geometry/oriented-triangle-area.html
  299. float dxAB = triangle.vertices[0].position.x() - triangle.vertices[1].position.x(); // A.x - B.x
  300. float dxBC = triangle.vertices[1].position.x() - triangle.vertices[2].position.x(); // B.X - C.x
  301. float dyAB = triangle.vertices[0].position.y() - triangle.vertices[1].position.y();
  302. float dyBC = triangle.vertices[1].position.y() - triangle.vertices[2].position.y();
  303. float area = (dxAB * dyBC) - (dxBC * dyAB);
  304. if (area == 0.0f)
  305. continue;
  306. if (m_cull_faces) {
  307. bool is_front = (m_front_face == GL_CCW ? area < 0 : area > 0);
  308. if (is_front && (m_culled_sides == GL_FRONT || m_culled_sides == GL_FRONT_AND_BACK))
  309. continue;
  310. if (!is_front && (m_culled_sides == GL_BACK || m_culled_sides == GL_FRONT_AND_BACK))
  311. continue;
  312. }
  313. if (area > 0) {
  314. swap(triangle.vertices[0], triangle.vertices[1]);
  315. }
  316. m_rasterizer.submit_triangle(triangle, m_bound_texture_units);
  317. }
  318. }
  319. void SoftwareGLContext::gl_frustum(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val)
  320. {
  321. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_frustum, left, right, bottom, top, near_val, far_val);
  322. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  323. // Let's do some math!
  324. // FIXME: Are we losing too much precision by doing this?
  325. float a = static_cast<float>((right + left) / (right - left));
  326. float b = static_cast<float>((top + bottom) / (top - bottom));
  327. float c = static_cast<float>(-((far_val + near_val) / (far_val - near_val)));
  328. float d = static_cast<float>(-((2 * (far_val * near_val)) / (far_val - near_val)));
  329. FloatMatrix4x4 frustum {
  330. ((2 * (float)near_val) / ((float)right - (float)left)), 0, a, 0,
  331. 0, ((2 * (float)near_val) / ((float)top - (float)bottom)), b, 0,
  332. 0, 0, c, d,
  333. 0, 0, -1, 0
  334. };
  335. if (m_current_matrix_mode == GL_PROJECTION)
  336. m_projection_matrix = m_projection_matrix * frustum;
  337. else if (m_current_matrix_mode == GL_MODELVIEW)
  338. m_projection_matrix = m_model_view_matrix * frustum;
  339. else if (m_current_matrix_mode == GL_TEXTURE)
  340. m_texture_matrix = m_texture_matrix * frustum;
  341. else
  342. VERIFY_NOT_REACHED();
  343. }
  344. void SoftwareGLContext::gl_ortho(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble near_val, GLdouble far_val)
  345. {
  346. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_ortho, left, right, bottom, top, near_val, far_val);
  347. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  348. RETURN_WITH_ERROR_IF(left == right || bottom == top || near_val == far_val, GL_INVALID_VALUE);
  349. auto rl = right - left;
  350. auto tb = top - bottom;
  351. auto fn = far_val - near_val;
  352. auto tx = -(right + left) / rl;
  353. auto ty = -(top + bottom) / tb;
  354. auto tz = -(far_val + near_val) / fn;
  355. FloatMatrix4x4 projection {
  356. static_cast<float>(2 / rl), 0, 0, static_cast<float>(tx),
  357. 0, static_cast<float>(2 / tb), 0, static_cast<float>(ty),
  358. 0, 0, static_cast<float>(-2 / fn), static_cast<float>(tz),
  359. 0, 0, 0, 1
  360. };
  361. if (m_current_matrix_mode == GL_PROJECTION)
  362. m_projection_matrix = m_projection_matrix * projection;
  363. else if (m_current_matrix_mode == GL_MODELVIEW)
  364. m_projection_matrix = m_model_view_matrix * projection;
  365. else if (m_current_matrix_mode == GL_TEXTURE)
  366. m_texture_matrix = m_texture_matrix * projection;
  367. else
  368. VERIFY_NOT_REACHED();
  369. }
  370. GLenum SoftwareGLContext::gl_get_error()
  371. {
  372. if (m_in_draw_state)
  373. return GL_INVALID_OPERATION;
  374. auto last_error = m_error;
  375. m_error = GL_NO_ERROR;
  376. return last_error;
  377. }
  378. GLubyte* SoftwareGLContext::gl_get_string(GLenum name)
  379. {
  380. RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, nullptr);
  381. switch (name) {
  382. case GL_VENDOR:
  383. return reinterpret_cast<GLubyte*>(const_cast<char*>("The SerenityOS Developers"));
  384. case GL_RENDERER:
  385. return reinterpret_cast<GLubyte*>(const_cast<char*>("SerenityOS OpenGL"));
  386. case GL_VERSION:
  387. return reinterpret_cast<GLubyte*>(const_cast<char*>("1.5"));
  388. case GL_EXTENSIONS:
  389. return reinterpret_cast<GLubyte*>(const_cast<char*>(""));
  390. case GL_SHADING_LANGUAGE_VERSION:
  391. return reinterpret_cast<GLubyte*>(const_cast<char*>("0.0"));
  392. default:
  393. dbgln_if(GL_DEBUG, "gl_get_string({:#x}): unknown name", name);
  394. break;
  395. }
  396. RETURN_VALUE_WITH_ERROR_IF(true, GL_INVALID_ENUM, nullptr);
  397. }
  398. void SoftwareGLContext::gl_load_identity()
  399. {
  400. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_load_identity);
  401. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  402. if (m_current_matrix_mode == GL_PROJECTION)
  403. m_projection_matrix = FloatMatrix4x4::identity();
  404. else if (m_current_matrix_mode == GL_MODELVIEW)
  405. m_model_view_matrix = FloatMatrix4x4::identity();
  406. else if (m_current_matrix_mode == GL_TEXTURE)
  407. m_texture_matrix = FloatMatrix4x4::identity();
  408. else
  409. VERIFY_NOT_REACHED();
  410. }
  411. void SoftwareGLContext::gl_load_matrix(const FloatMatrix4x4& matrix)
  412. {
  413. APPEND_TO_CALL_LIST_WITH_ARG_AND_RETURN_IF_NEEDED(gl_load_matrix, matrix);
  414. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  415. if (m_current_matrix_mode == GL_PROJECTION)
  416. m_projection_matrix = matrix;
  417. else if (m_current_matrix_mode == GL_MODELVIEW)
  418. m_model_view_matrix = matrix;
  419. else if (m_current_matrix_mode == GL_TEXTURE)
  420. m_texture_matrix = matrix;
  421. else
  422. VERIFY_NOT_REACHED();
  423. }
  424. void SoftwareGLContext::gl_matrix_mode(GLenum mode)
  425. {
  426. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_matrix_mode, mode);
  427. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  428. RETURN_WITH_ERROR_IF(mode < GL_MODELVIEW || mode > GL_TEXTURE, GL_INVALID_ENUM);
  429. m_current_matrix_mode = mode;
  430. }
  431. void SoftwareGLContext::gl_push_matrix()
  432. {
  433. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_push_matrix);
  434. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  435. dbgln_if(GL_DEBUG, "glPushMatrix(): Pushing matrix to the matrix stack (matrix_mode {})", m_current_matrix_mode);
  436. switch (m_current_matrix_mode) {
  437. case GL_PROJECTION:
  438. RETURN_WITH_ERROR_IF(m_projection_matrix_stack.size() >= PROJECTION_MATRIX_STACK_LIMIT, GL_STACK_OVERFLOW);
  439. m_projection_matrix_stack.append(m_projection_matrix);
  440. break;
  441. case GL_MODELVIEW:
  442. RETURN_WITH_ERROR_IF(m_model_view_matrix_stack.size() >= MODELVIEW_MATRIX_STACK_LIMIT, GL_STACK_OVERFLOW);
  443. m_model_view_matrix_stack.append(m_model_view_matrix);
  444. break;
  445. case GL_TEXTURE:
  446. RETURN_WITH_ERROR_IF(m_texture_matrix_stack.size() >= TEXTURE_MATRIX_STACK_LIMIT, GL_STACK_OVERFLOW);
  447. m_texture_matrix_stack.append(m_texture_matrix);
  448. break;
  449. default:
  450. VERIFY_NOT_REACHED();
  451. }
  452. }
  453. void SoftwareGLContext::gl_pop_matrix()
  454. {
  455. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_pop_matrix);
  456. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  457. dbgln_if(GL_DEBUG, "glPopMatrix(): Popping matrix from matrix stack (matrix_mode = {})", m_current_matrix_mode);
  458. switch (m_current_matrix_mode) {
  459. case GL_PROJECTION:
  460. RETURN_WITH_ERROR_IF(m_projection_matrix_stack.size() == 0, GL_STACK_UNDERFLOW);
  461. m_projection_matrix = m_projection_matrix_stack.take_last();
  462. break;
  463. case GL_MODELVIEW:
  464. RETURN_WITH_ERROR_IF(m_model_view_matrix_stack.size() == 0, GL_STACK_UNDERFLOW);
  465. m_model_view_matrix = m_model_view_matrix_stack.take_last();
  466. break;
  467. case GL_TEXTURE:
  468. RETURN_WITH_ERROR_IF(m_texture_matrix_stack.size() == 0, GL_STACK_UNDERFLOW);
  469. m_texture_matrix = m_texture_matrix_stack.take_last();
  470. break;
  471. default:
  472. VERIFY_NOT_REACHED();
  473. }
  474. }
  475. void SoftwareGLContext::gl_mult_matrix(FloatMatrix4x4 const& matrix)
  476. {
  477. APPEND_TO_CALL_LIST_WITH_ARG_AND_RETURN_IF_NEEDED(gl_mult_matrix, matrix);
  478. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  479. if (m_current_matrix_mode == GL_MODELVIEW)
  480. m_model_view_matrix = m_model_view_matrix * matrix;
  481. else if (m_current_matrix_mode == GL_PROJECTION)
  482. m_projection_matrix = m_projection_matrix * matrix;
  483. else if (m_current_matrix_mode == GL_TEXTURE)
  484. m_texture_matrix = m_texture_matrix * matrix;
  485. else
  486. VERIFY_NOT_REACHED();
  487. }
  488. void SoftwareGLContext::gl_rotate(GLdouble angle, GLdouble x, GLdouble y, GLdouble z)
  489. {
  490. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_rotate, angle, x, y, z);
  491. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  492. FloatVector3 axis = { (float)x, (float)y, (float)z };
  493. axis.normalize();
  494. auto rotation_mat = Gfx::rotation_matrix(axis, static_cast<float>(angle * M_PI * 2 / 360));
  495. if (m_current_matrix_mode == GL_MODELVIEW)
  496. m_model_view_matrix = m_model_view_matrix * rotation_mat;
  497. else if (m_current_matrix_mode == GL_PROJECTION)
  498. m_projection_matrix = m_projection_matrix * rotation_mat;
  499. else if (m_current_matrix_mode == GL_TEXTURE)
  500. m_texture_matrix = m_texture_matrix * rotation_mat;
  501. else
  502. VERIFY_NOT_REACHED();
  503. }
  504. void SoftwareGLContext::gl_scale(GLdouble x, GLdouble y, GLdouble z)
  505. {
  506. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_scale, x, y, z);
  507. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  508. auto scale_matrix = Gfx::scale_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 * scale_matrix;
  511. else if (m_current_matrix_mode == GL_PROJECTION)
  512. m_projection_matrix = m_projection_matrix * scale_matrix;
  513. else if (m_current_matrix_mode == GL_TEXTURE)
  514. m_texture_matrix = m_texture_matrix * scale_matrix;
  515. else
  516. VERIFY_NOT_REACHED();
  517. }
  518. void SoftwareGLContext::gl_translate(GLdouble x, GLdouble y, GLdouble z)
  519. {
  520. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_translate, x, y, z);
  521. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  522. auto translation_matrix = Gfx::translation_matrix(FloatVector3 { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z) });
  523. if (m_current_matrix_mode == GL_MODELVIEW)
  524. m_model_view_matrix = m_model_view_matrix * translation_matrix;
  525. else if (m_current_matrix_mode == GL_PROJECTION)
  526. m_projection_matrix = m_projection_matrix * translation_matrix;
  527. else if (m_current_matrix_mode == GL_TEXTURE)
  528. m_texture_matrix = m_texture_matrix * translation_matrix;
  529. else
  530. VERIFY_NOT_REACHED();
  531. }
  532. void SoftwareGLContext::gl_vertex(GLdouble x, GLdouble y, GLdouble z, GLdouble w)
  533. {
  534. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_vertex, x, y, z, w);
  535. GLVertex vertex;
  536. vertex.position = { static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(w) };
  537. vertex.color = m_current_vertex_color;
  538. vertex.tex_coord = m_current_vertex_tex_coord;
  539. vertex.normal = m_current_vertex_normal;
  540. vertex_list.append(vertex);
  541. }
  542. // FIXME: We need to add `r` and `q` to our GLVertex?!
  543. void SoftwareGLContext::gl_tex_coord(GLfloat s, GLfloat t, GLfloat r, GLfloat q)
  544. {
  545. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_tex_coord, s, t, r, q);
  546. m_current_vertex_tex_coord = { s, t, r, q };
  547. }
  548. void SoftwareGLContext::gl_viewport(GLint x, GLint y, GLsizei width, GLsizei height)
  549. {
  550. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_viewport, x, y, width, height);
  551. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  552. (void)(x);
  553. (void)(y);
  554. (void)(width);
  555. (void)(height);
  556. }
  557. void SoftwareGLContext::gl_enable(GLenum capability)
  558. {
  559. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_enable, capability);
  560. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  561. auto rasterizer_options = m_rasterizer.options();
  562. bool update_rasterizer_options = false;
  563. switch (capability) {
  564. case GL_CULL_FACE:
  565. m_cull_faces = true;
  566. break;
  567. case GL_DEPTH_TEST:
  568. m_depth_test_enabled = true;
  569. rasterizer_options.enable_depth_test = true;
  570. update_rasterizer_options = true;
  571. break;
  572. case GL_BLEND:
  573. m_blend_enabled = true;
  574. rasterizer_options.enable_blending = true;
  575. update_rasterizer_options = true;
  576. break;
  577. case GL_ALPHA_TEST:
  578. m_alpha_test_enabled = true;
  579. rasterizer_options.enable_alpha_test = true;
  580. update_rasterizer_options = true;
  581. break;
  582. case GL_DITHER:
  583. m_dither_enabled = true;
  584. break;
  585. case GL_FOG:
  586. rasterizer_options.fog_enabled = true;
  587. update_rasterizer_options = true;
  588. break;
  589. case GL_LIGHTING:
  590. m_lighting_enabled = true;
  591. break;
  592. case GL_SCISSOR_TEST:
  593. rasterizer_options.scissor_enabled = true;
  594. update_rasterizer_options = true;
  595. break;
  596. case GL_STENCIL_TEST:
  597. m_stencil_test_enabled = true;
  598. break;
  599. case GL_TEXTURE_1D:
  600. m_active_texture_unit->set_texture_1d_enabled(true);
  601. break;
  602. case GL_TEXTURE_2D:
  603. m_active_texture_unit->set_texture_2d_enabled(true);
  604. break;
  605. case GL_TEXTURE_3D:
  606. m_active_texture_unit->set_texture_3d_enabled(true);
  607. break;
  608. case GL_TEXTURE_CUBE_MAP:
  609. m_active_texture_unit->set_texture_cube_map_enabled(true);
  610. break;
  611. default:
  612. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  613. }
  614. if (update_rasterizer_options)
  615. m_rasterizer.set_options(rasterizer_options);
  616. }
  617. void SoftwareGLContext::gl_disable(GLenum capability)
  618. {
  619. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_disable, capability);
  620. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  621. auto rasterizer_options = m_rasterizer.options();
  622. bool update_rasterizer_options = false;
  623. switch (capability) {
  624. case GL_CULL_FACE:
  625. m_cull_faces = false;
  626. break;
  627. case GL_DEPTH_TEST:
  628. m_depth_test_enabled = false;
  629. rasterizer_options.enable_depth_test = false;
  630. update_rasterizer_options = true;
  631. break;
  632. case GL_BLEND:
  633. m_blend_enabled = false;
  634. rasterizer_options.enable_blending = false;
  635. update_rasterizer_options = true;
  636. break;
  637. case GL_ALPHA_TEST:
  638. m_alpha_test_enabled = false;
  639. rasterizer_options.enable_alpha_test = false;
  640. update_rasterizer_options = true;
  641. break;
  642. case GL_DITHER:
  643. m_dither_enabled = false;
  644. break;
  645. case GL_FOG:
  646. rasterizer_options.fog_enabled = false;
  647. update_rasterizer_options = true;
  648. break;
  649. case GL_LIGHTING:
  650. m_lighting_enabled = false;
  651. break;
  652. case GL_SCISSOR_TEST:
  653. rasterizer_options.scissor_enabled = false;
  654. update_rasterizer_options = true;
  655. break;
  656. case GL_STENCIL_TEST:
  657. m_stencil_test_enabled = false;
  658. break;
  659. case GL_TEXTURE_1D:
  660. m_active_texture_unit->set_texture_1d_enabled(false);
  661. break;
  662. case GL_TEXTURE_2D:
  663. m_active_texture_unit->set_texture_2d_enabled(false);
  664. break;
  665. case GL_TEXTURE_3D:
  666. m_active_texture_unit->set_texture_3d_enabled(false);
  667. break;
  668. case GL_TEXTURE_CUBE_MAP:
  669. m_active_texture_unit->set_texture_cube_map_enabled(false);
  670. break;
  671. default:
  672. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  673. }
  674. if (update_rasterizer_options)
  675. m_rasterizer.set_options(rasterizer_options);
  676. }
  677. GLboolean SoftwareGLContext::gl_is_enabled(GLenum capability)
  678. {
  679. RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, 0);
  680. auto rasterizer_options = m_rasterizer.options();
  681. switch (capability) {
  682. case GL_CULL_FACE:
  683. return m_cull_faces;
  684. case GL_DEPTH_TEST:
  685. return m_depth_test_enabled;
  686. case GL_BLEND:
  687. return m_blend_enabled;
  688. case GL_ALPHA_TEST:
  689. return m_alpha_test_enabled;
  690. case GL_DITHER:
  691. return m_dither_enabled;
  692. case GL_FOG:
  693. return rasterizer_options.fog_enabled;
  694. case GL_LIGHTING:
  695. return m_lighting_enabled;
  696. case GL_SCISSOR_TEST:
  697. return rasterizer_options.scissor_enabled;
  698. case GL_STENCIL_TEST:
  699. return m_stencil_test_enabled;
  700. }
  701. RETURN_VALUE_WITH_ERROR_IF(true, GL_INVALID_ENUM, 0);
  702. }
  703. void SoftwareGLContext::gl_gen_textures(GLsizei n, GLuint* textures)
  704. {
  705. RETURN_WITH_ERROR_IF(n < 0, GL_INVALID_VALUE);
  706. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  707. m_name_allocator.allocate(n, textures);
  708. // Initialize all texture names with a nullptr
  709. for (auto i = 0; i < n; i++) {
  710. GLuint name = textures[i];
  711. m_allocated_textures.set(name, nullptr);
  712. }
  713. }
  714. void SoftwareGLContext::gl_delete_textures(GLsizei n, const GLuint* textures)
  715. {
  716. RETURN_WITH_ERROR_IF(n < 0, GL_INVALID_VALUE);
  717. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  718. for (auto i = 0; i < n; i++) {
  719. GLuint name = textures[i];
  720. if (name == 0)
  721. continue;
  722. m_name_allocator.free(name);
  723. auto texture_object = m_allocated_textures.find(name);
  724. if (texture_object == m_allocated_textures.end() || texture_object->value.is_null())
  725. continue;
  726. // Check all texture units
  727. for (auto& texture_unit : m_texture_units) {
  728. if (texture_object->value == texture_unit.bound_texture())
  729. texture_unit.bind_texture_to_target(GL_TEXTURE_2D, nullptr);
  730. }
  731. m_allocated_textures.remove(name);
  732. }
  733. }
  734. 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)
  735. {
  736. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  737. // We only support GL_TEXTURE_2D for now
  738. RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM);
  739. // Check if there is actually a texture bound
  740. RETURN_WITH_ERROR_IF(target == GL_TEXTURE_2D && m_active_texture_unit->currently_bound_target() != GL_TEXTURE_2D, GL_INVALID_OPERATION);
  741. // 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
  742. if (internal_format == 1)
  743. internal_format = GL_ALPHA;
  744. else if (internal_format == 2)
  745. internal_format = GL_LUMINANCE_ALPHA;
  746. else if (internal_format == 3)
  747. internal_format = GL_RGB;
  748. else if (internal_format == 4)
  749. internal_format = GL_RGBA;
  750. // We only support symbolic constants for now
  751. RETURN_WITH_ERROR_IF(!(internal_format == GL_RGB || internal_format == GL_RGBA), GL_INVALID_ENUM);
  752. RETURN_WITH_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT_5_6_5), GL_INVALID_VALUE);
  753. RETURN_WITH_ERROR_IF(level < 0 || level > Texture2D::LOG2_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
  754. RETURN_WITH_ERROR_IF(width < 0 || height < 0 || width > (2 + Texture2D::MAX_TEXTURE_SIZE) || height > (2 + Texture2D::MAX_TEXTURE_SIZE), GL_INVALID_VALUE);
  755. // Check if width and height are a power of 2
  756. RETURN_WITH_ERROR_IF((width & (width - 1)) != 0, GL_INVALID_VALUE);
  757. RETURN_WITH_ERROR_IF((height & (height - 1)) != 0, GL_INVALID_VALUE);
  758. RETURN_WITH_ERROR_IF(border < 0 || border > 1, GL_INVALID_VALUE);
  759. m_active_texture_unit->bound_texture_2d()->upload_texture_data(level, internal_format, width, height, border, format, type, data, m_unpack_row_length, m_unpack_alignment);
  760. }
  761. 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)
  762. {
  763. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  764. // We only support GL_TEXTURE_2D for now
  765. RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM);
  766. // Check if there is actually a texture bound
  767. RETURN_WITH_ERROR_IF(target == GL_TEXTURE_2D && m_active_texture_unit->currently_bound_target() != GL_TEXTURE_2D, GL_INVALID_OPERATION);
  768. // We only support symbolic constants for now
  769. RETURN_WITH_ERROR_IF(!(format == GL_RGBA || format == GL_RGB), GL_INVALID_VALUE);
  770. RETURN_WITH_ERROR_IF(!(type == GL_UNSIGNED_BYTE || type == GL_UNSIGNED_SHORT_5_6_5), GL_INVALID_VALUE);
  771. RETURN_WITH_ERROR_IF(level < 0 || level > Texture2D::LOG2_MAX_TEXTURE_SIZE, GL_INVALID_VALUE);
  772. RETURN_WITH_ERROR_IF(width < 0 || height < 0 || width > (2 + Texture2D::MAX_TEXTURE_SIZE) || height > (2 + Texture2D::MAX_TEXTURE_SIZE), GL_INVALID_VALUE);
  773. auto texture = m_active_texture_unit->bound_texture_2d();
  774. 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);
  775. texture->replace_sub_texture_data(level, xoffset, yoffset, width, height, format, type, data, m_unpack_row_length, m_unpack_alignment);
  776. }
  777. void SoftwareGLContext::gl_tex_parameter(GLenum target, GLenum pname, GLfloat param)
  778. {
  779. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_tex_parameter, target, pname, param);
  780. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  781. // FIXME: We currently only support GL_TETXURE_2D targets. 1D, 3D and CUBE should also be supported (https://docs.gl/gl2/glTexParameter)
  782. RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM);
  783. // FIXME: implement the remaining parameters. (https://docs.gl/gl2/glTexParameter)
  784. RETURN_WITH_ERROR_IF(!(pname == GL_TEXTURE_MIN_FILTER
  785. || pname == GL_TEXTURE_MAG_FILTER
  786. || pname == GL_TEXTURE_WRAP_S
  787. || pname == GL_TEXTURE_WRAP_T),
  788. GL_INVALID_ENUM);
  789. if (target == GL_TEXTURE_2D) {
  790. auto texture2d = m_active_texture_unit->bound_texture_2d();
  791. if (texture2d.is_null())
  792. return;
  793. switch (pname) {
  794. case GL_TEXTURE_MIN_FILTER:
  795. RETURN_WITH_ERROR_IF(!(param == GL_NEAREST
  796. || param == GL_LINEAR
  797. || param == GL_NEAREST_MIPMAP_NEAREST
  798. || param == GL_LINEAR_MIPMAP_NEAREST
  799. || param == GL_NEAREST_MIPMAP_LINEAR
  800. || param == GL_LINEAR_MIPMAP_LINEAR),
  801. GL_INVALID_ENUM);
  802. texture2d->sampler().set_min_filter(param);
  803. break;
  804. case GL_TEXTURE_MAG_FILTER:
  805. RETURN_WITH_ERROR_IF(!(param == GL_NEAREST
  806. || param == GL_LINEAR),
  807. GL_INVALID_ENUM);
  808. texture2d->sampler().set_mag_filter(param);
  809. break;
  810. case GL_TEXTURE_WRAP_S:
  811. RETURN_WITH_ERROR_IF(!(param == GL_CLAMP
  812. || param == GL_CLAMP_TO_BORDER
  813. || param == GL_CLAMP_TO_EDGE
  814. || param == GL_MIRRORED_REPEAT
  815. || param == GL_REPEAT),
  816. GL_INVALID_ENUM);
  817. texture2d->sampler().set_wrap_s_mode(param);
  818. break;
  819. case GL_TEXTURE_WRAP_T:
  820. RETURN_WITH_ERROR_IF(!(param == GL_CLAMP
  821. || param == GL_CLAMP_TO_BORDER
  822. || param == GL_CLAMP_TO_EDGE
  823. || param == GL_MIRRORED_REPEAT
  824. || param == GL_REPEAT),
  825. GL_INVALID_ENUM);
  826. texture2d->sampler().set_wrap_t_mode(param);
  827. break;
  828. default:
  829. VERIFY_NOT_REACHED();
  830. }
  831. }
  832. }
  833. void SoftwareGLContext::gl_front_face(GLenum face)
  834. {
  835. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_front_face, face);
  836. RETURN_WITH_ERROR_IF(face < GL_CW || face > GL_CCW, GL_INVALID_ENUM);
  837. m_front_face = face;
  838. }
  839. void SoftwareGLContext::gl_cull_face(GLenum cull_mode)
  840. {
  841. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_cull_face, cull_mode);
  842. RETURN_WITH_ERROR_IF(cull_mode < GL_FRONT || cull_mode > GL_FRONT_AND_BACK, GL_INVALID_ENUM);
  843. m_culled_sides = cull_mode;
  844. }
  845. GLuint SoftwareGLContext::gl_gen_lists(GLsizei range)
  846. {
  847. RETURN_VALUE_WITH_ERROR_IF(range <= 0, GL_INVALID_VALUE, 0);
  848. RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, 0);
  849. auto initial_entry = m_listings.size();
  850. m_listings.resize(range + initial_entry);
  851. return initial_entry + 1;
  852. }
  853. void SoftwareGLContext::invoke_list(size_t list_index)
  854. {
  855. auto& listing = m_listings[list_index - 1];
  856. for (auto& entry : listing.entries) {
  857. entry.function.visit([&](auto& function) {
  858. entry.arguments.visit([&](auto& arguments) {
  859. auto apply = [&]<typename... Args>(Args && ... args)
  860. {
  861. if constexpr (requires { (this->*function)(forward<Args>(args)...); })
  862. (this->*function)(forward<Args>(args)...);
  863. };
  864. arguments.apply_as_args(apply);
  865. });
  866. });
  867. }
  868. }
  869. void SoftwareGLContext::gl_call_list(GLuint list)
  870. {
  871. if (m_gl_call_depth > max_allowed_gl_call_depth)
  872. return;
  873. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_call_list, list);
  874. if (m_listings.size() < list)
  875. return;
  876. TemporaryChange change { m_gl_call_depth, m_gl_call_depth + 1 };
  877. invoke_list(list);
  878. }
  879. void SoftwareGLContext::gl_call_lists(GLsizei n, GLenum type, void const* lists)
  880. {
  881. if (m_gl_call_depth > max_allowed_gl_call_depth)
  882. return;
  883. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_call_lists, n, type, lists);
  884. RETURN_WITH_ERROR_IF(n < 0, GL_INVALID_VALUE);
  885. RETURN_WITH_ERROR_IF(!(type == GL_BYTE
  886. || type == GL_UNSIGNED_BYTE
  887. || type == GL_SHORT
  888. || type == GL_UNSIGNED_SHORT
  889. || type == GL_INT
  890. || type == GL_UNSIGNED_INT
  891. || type == GL_FLOAT
  892. || type == GL_2_BYTES
  893. || type == GL_3_BYTES
  894. || type == GL_4_BYTES),
  895. GL_INVALID_ENUM);
  896. TemporaryChange change { m_gl_call_depth, m_gl_call_depth + 1 };
  897. auto invoke_all_lists = [&]<typename T>(T const* lists) {
  898. for (int i = 0; i < n; ++i) {
  899. auto list = static_cast<size_t>(lists[i]);
  900. invoke_list(m_list_base + list);
  901. }
  902. };
  903. switch (type) {
  904. case GL_BYTE:
  905. invoke_all_lists(static_cast<GLbyte const*>(lists));
  906. break;
  907. case GL_UNSIGNED_BYTE:
  908. invoke_all_lists(static_cast<GLubyte const*>(lists));
  909. break;
  910. case GL_SHORT:
  911. invoke_all_lists(static_cast<GLshort const*>(lists));
  912. break;
  913. case GL_UNSIGNED_SHORT:
  914. invoke_all_lists(static_cast<GLushort const*>(lists));
  915. break;
  916. case GL_INT:
  917. invoke_all_lists(static_cast<GLint const*>(lists));
  918. break;
  919. case GL_UNSIGNED_INT:
  920. invoke_all_lists(static_cast<GLuint const*>(lists));
  921. break;
  922. case GL_FLOAT:
  923. invoke_all_lists(static_cast<GLfloat const*>(lists));
  924. break;
  925. case GL_2_BYTES:
  926. case GL_3_BYTES:
  927. case GL_4_BYTES:
  928. dbgln("SoftwareGLContext FIXME: unimplemented glCallLists() with type {}", type);
  929. break;
  930. default:
  931. VERIFY_NOT_REACHED();
  932. }
  933. }
  934. void SoftwareGLContext::gl_delete_lists(GLuint list, GLsizei range)
  935. {
  936. if (m_listings.size() < list || m_listings.size() <= list + range)
  937. return;
  938. for (auto& entry : m_listings.span().slice(list - 1, range))
  939. entry.entries.clear_with_capacity();
  940. }
  941. void SoftwareGLContext::gl_list_base(GLuint base)
  942. {
  943. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_list_base, base);
  944. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  945. m_list_base = base;
  946. }
  947. void SoftwareGLContext::gl_end_list()
  948. {
  949. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  950. RETURN_WITH_ERROR_IF(!m_current_listing_index.has_value(), GL_INVALID_OPERATION);
  951. m_listings[m_current_listing_index->index] = move(m_current_listing_index->listing);
  952. m_current_listing_index.clear();
  953. }
  954. void SoftwareGLContext::gl_new_list(GLuint list, GLenum mode)
  955. {
  956. RETURN_WITH_ERROR_IF(list == 0, GL_INVALID_VALUE);
  957. RETURN_WITH_ERROR_IF(mode != GL_COMPILE && mode != GL_COMPILE_AND_EXECUTE, GL_INVALID_ENUM);
  958. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  959. RETURN_WITH_ERROR_IF(m_current_listing_index.has_value(), GL_INVALID_OPERATION);
  960. if (m_listings.size() < list)
  961. return;
  962. m_current_listing_index = CurrentListing { {}, static_cast<size_t>(list - 1), mode };
  963. }
  964. GLboolean SoftwareGLContext::gl_is_list(GLuint list)
  965. {
  966. RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, GL_FALSE);
  967. return list < m_listings.size() ? GL_TRUE : GL_FALSE;
  968. }
  969. void SoftwareGLContext::gl_flush()
  970. {
  971. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  972. // No-op since SoftwareGLContext is completely synchronous at the moment
  973. }
  974. void SoftwareGLContext::gl_finish()
  975. {
  976. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  977. // No-op since SoftwareGLContext is completely synchronous at the moment
  978. }
  979. void SoftwareGLContext::gl_blend_func(GLenum src_factor, GLenum dst_factor)
  980. {
  981. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_blend_func, src_factor, dst_factor);
  982. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  983. // FIXME: The list of allowed enums differs between API versions
  984. // This was taken from the 2.0 spec on https://docs.gl/gl2/glBlendFunc
  985. RETURN_WITH_ERROR_IF(!(src_factor == GL_ZERO
  986. || src_factor == GL_ONE
  987. || src_factor == GL_SRC_COLOR
  988. || src_factor == GL_ONE_MINUS_SRC_COLOR
  989. || src_factor == GL_DST_COLOR
  990. || src_factor == GL_ONE_MINUS_DST_COLOR
  991. || src_factor == GL_SRC_ALPHA
  992. || src_factor == GL_ONE_MINUS_SRC_ALPHA
  993. || src_factor == GL_DST_ALPHA
  994. || src_factor == GL_ONE_MINUS_DST_ALPHA
  995. || src_factor == GL_CONSTANT_COLOR
  996. || src_factor == GL_ONE_MINUS_CONSTANT_COLOR
  997. || src_factor == GL_CONSTANT_ALPHA
  998. || src_factor == GL_ONE_MINUS_CONSTANT_ALPHA
  999. || src_factor == GL_SRC_ALPHA_SATURATE),
  1000. GL_INVALID_ENUM);
  1001. RETURN_WITH_ERROR_IF(!(dst_factor == GL_ZERO
  1002. || dst_factor == GL_ONE
  1003. || dst_factor == GL_SRC_COLOR
  1004. || dst_factor == GL_ONE_MINUS_SRC_COLOR
  1005. || dst_factor == GL_DST_COLOR
  1006. || dst_factor == GL_ONE_MINUS_DST_COLOR
  1007. || dst_factor == GL_SRC_ALPHA
  1008. || dst_factor == GL_ONE_MINUS_SRC_ALPHA
  1009. || dst_factor == GL_DST_ALPHA
  1010. || dst_factor == GL_ONE_MINUS_DST_ALPHA
  1011. || dst_factor == GL_CONSTANT_COLOR
  1012. || dst_factor == GL_ONE_MINUS_CONSTANT_COLOR
  1013. || dst_factor == GL_CONSTANT_ALPHA
  1014. || dst_factor == GL_ONE_MINUS_CONSTANT_ALPHA),
  1015. GL_INVALID_ENUM);
  1016. m_blend_source_factor = src_factor;
  1017. m_blend_destination_factor = dst_factor;
  1018. auto options = m_rasterizer.options();
  1019. options.blend_source_factor = m_blend_source_factor;
  1020. options.blend_destination_factor = m_blend_destination_factor;
  1021. m_rasterizer.set_options(options);
  1022. }
  1023. void SoftwareGLContext::gl_shade_model(GLenum mode)
  1024. {
  1025. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_shade_model, mode);
  1026. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1027. RETURN_WITH_ERROR_IF(mode != GL_FLAT && mode != GL_SMOOTH, GL_INVALID_ENUM);
  1028. auto options = m_rasterizer.options();
  1029. options.shade_smooth = (mode == GL_SMOOTH);
  1030. m_rasterizer.set_options(options);
  1031. }
  1032. void SoftwareGLContext::gl_alpha_func(GLenum func, GLclampf ref)
  1033. {
  1034. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_alpha_func, func, ref);
  1035. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1036. RETURN_WITH_ERROR_IF(func < GL_NEVER || func > GL_ALWAYS, GL_INVALID_ENUM);
  1037. m_alpha_test_func = func;
  1038. m_alpha_test_ref_value = ref;
  1039. auto options = m_rasterizer.options();
  1040. options.alpha_test_func = m_alpha_test_func;
  1041. options.alpha_test_ref_value = m_alpha_test_ref_value;
  1042. m_rasterizer.set_options(options);
  1043. }
  1044. void SoftwareGLContext::gl_hint(GLenum target, GLenum mode)
  1045. {
  1046. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_hint, target, mode);
  1047. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1048. RETURN_WITH_ERROR_IF(target != GL_PERSPECTIVE_CORRECTION_HINT
  1049. && target != GL_POINT_SMOOTH_HINT
  1050. && target != GL_LINE_SMOOTH_HINT
  1051. && target != GL_POLYGON_SMOOTH_HINT
  1052. && target != GL_FOG_HINT
  1053. && target != GL_GENERATE_MIPMAP_HINT
  1054. && target != GL_TEXTURE_COMPRESSION_HINT,
  1055. GL_INVALID_ENUM);
  1056. RETURN_WITH_ERROR_IF(mode != GL_DONT_CARE
  1057. && mode != GL_FASTEST
  1058. && mode != GL_NICEST,
  1059. GL_INVALID_ENUM);
  1060. // According to the spec implementors are free to ignore glHint. So we do.
  1061. }
  1062. void SoftwareGLContext::gl_read_buffer(GLenum mode)
  1063. {
  1064. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_read_buffer, mode);
  1065. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1066. // FIXME: Also allow aux buffers GL_AUX0 through GL_AUX3 here
  1067. // plus any aux buffer between 0 and GL_AUX_BUFFERS
  1068. RETURN_WITH_ERROR_IF(mode != GL_FRONT_LEFT
  1069. && mode != GL_FRONT_RIGHT
  1070. && mode != GL_BACK_LEFT
  1071. && mode != GL_BACK_RIGHT
  1072. && mode != GL_FRONT
  1073. && mode != GL_BACK
  1074. && mode != GL_LEFT
  1075. && mode != GL_RIGHT,
  1076. GL_INVALID_ENUM);
  1077. // FIXME: We do not currently have aux buffers, so make it an invalid
  1078. // operation to select anything but front or back buffers. Also we do
  1079. // not allow selecting the stereoscopic RIGHT buffers since we do not
  1080. // have them configured.
  1081. RETURN_WITH_ERROR_IF(mode != GL_FRONT_LEFT
  1082. && mode != GL_FRONT
  1083. && mode != GL_BACK_LEFT
  1084. && mode != GL_BACK
  1085. && mode != GL_FRONT
  1086. && mode != GL_BACK
  1087. && mode != GL_LEFT,
  1088. GL_INVALID_OPERATION);
  1089. m_current_read_buffer = mode;
  1090. }
  1091. void SoftwareGLContext::gl_draw_buffer(GLenum buffer)
  1092. {
  1093. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_draw_buffer, buffer);
  1094. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1095. // FIXME: Also allow aux buffers GL_AUX0 through GL_AUX3 here
  1096. // plus any aux buffer between 0 and GL_AUX_BUFFERS
  1097. RETURN_WITH_ERROR_IF(buffer != GL_NONE
  1098. && buffer != GL_FRONT_LEFT
  1099. && buffer != GL_FRONT_RIGHT
  1100. && buffer != GL_BACK_LEFT
  1101. && buffer != GL_BACK_RIGHT
  1102. && buffer != GL_FRONT
  1103. && buffer != GL_BACK
  1104. && buffer != GL_LEFT
  1105. && buffer != GL_RIGHT,
  1106. GL_INVALID_ENUM);
  1107. // FIXME: We do not currently have aux buffers, so make it an invalid
  1108. // operation to select anything but front or back buffers. Also we do
  1109. // not allow selecting the stereoscopic RIGHT buffers since we do not
  1110. // have them configured.
  1111. RETURN_WITH_ERROR_IF(buffer != GL_NONE
  1112. && buffer != GL_FRONT_LEFT
  1113. && buffer != GL_FRONT
  1114. && buffer != GL_BACK_LEFT
  1115. && buffer != GL_BACK
  1116. && buffer != GL_FRONT
  1117. && buffer != GL_BACK
  1118. && buffer != GL_LEFT,
  1119. GL_INVALID_OPERATION);
  1120. m_current_draw_buffer = buffer;
  1121. auto rasterizer_options = m_rasterizer.options();
  1122. rasterizer_options.draw_buffer = m_current_draw_buffer;
  1123. m_rasterizer.set_options(rasterizer_options);
  1124. }
  1125. void SoftwareGLContext::gl_read_pixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
  1126. {
  1127. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1128. RETURN_WITH_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
  1129. RETURN_WITH_ERROR_IF(format != GL_COLOR_INDEX
  1130. && format != GL_STENCIL_INDEX
  1131. && format != GL_DEPTH_COMPONENT
  1132. && format != GL_RED
  1133. && format != GL_GREEN
  1134. && format != GL_BLUE
  1135. && format != GL_ALPHA
  1136. && format != GL_RGB
  1137. && format != GL_RGBA
  1138. && format != GL_LUMINANCE
  1139. && format != GL_LUMINANCE_ALPHA,
  1140. GL_INVALID_ENUM);
  1141. RETURN_WITH_ERROR_IF(type != GL_UNSIGNED_BYTE
  1142. && type != GL_BYTE
  1143. && type != GL_BITMAP
  1144. && type != GL_UNSIGNED_SHORT
  1145. && type != GL_SHORT
  1146. && type != GL_BLUE
  1147. && type != GL_UNSIGNED_INT
  1148. && type != GL_INT
  1149. && type != GL_FLOAT,
  1150. GL_INVALID_ENUM);
  1151. // FIXME: We only support RGBA buffers for now.
  1152. // Once we add support for indexed color modes do the correct check here
  1153. RETURN_WITH_ERROR_IF(format == GL_COLOR_INDEX, GL_INVALID_OPERATION);
  1154. // FIXME: We do not have stencil buffers yet
  1155. // Once we add support for stencil buffers do the correct check here
  1156. RETURN_WITH_ERROR_IF(format == GL_STENCIL_INDEX, GL_INVALID_OPERATION);
  1157. if (format == GL_DEPTH_COMPONENT) {
  1158. // FIXME: This check needs to be a bit more sophisticated. Currently the buffers
  1159. // are hardcoded. Once we add proper structures for them we need to correct this check
  1160. // Error because only back buffer has a depth buffer
  1161. RETURN_WITH_ERROR_IF(m_current_read_buffer == GL_FRONT
  1162. || m_current_read_buffer == GL_FRONT_LEFT
  1163. || m_current_read_buffer == GL_FRONT_RIGHT,
  1164. GL_INVALID_OPERATION);
  1165. }
  1166. // Some helper functions for converting float values to integer types
  1167. auto float_to_i8 = [](float f) -> GLchar {
  1168. return static_cast<GLchar>((0x7f * min(max(f, 0.0f), 1.0f) - 1) / 2);
  1169. };
  1170. auto float_to_i16 = [](float f) -> GLshort {
  1171. return static_cast<GLshort>((0x7fff * min(max(f, 0.0f), 1.0f) - 1) / 2);
  1172. };
  1173. auto float_to_i32 = [](float f) -> GLint {
  1174. return static_cast<GLint>((0x7fffffff * min(max(f, 0.0f), 1.0f) - 1) / 2);
  1175. };
  1176. auto float_to_u8 = [](float f) -> GLubyte {
  1177. return static_cast<GLubyte>(0xff * min(max(f, 0.0f), 1.0f));
  1178. };
  1179. auto float_to_u16 = [](float f) -> GLushort {
  1180. return static_cast<GLushort>(0xffff * min(max(f, 0.0f), 1.0f));
  1181. };
  1182. auto float_to_u32 = [](float f) -> GLuint {
  1183. return static_cast<GLuint>(0xffffffff * min(max(f, 0.0f), 1.0f));
  1184. };
  1185. u8 component_size = 0;
  1186. switch (type) {
  1187. case GL_BYTE:
  1188. case GL_UNSIGNED_BYTE:
  1189. component_size = 1;
  1190. break;
  1191. case GL_SHORT:
  1192. case GL_UNSIGNED_SHORT:
  1193. component_size = 2;
  1194. break;
  1195. case GL_INT:
  1196. case GL_UNSIGNED_INT:
  1197. case GL_FLOAT:
  1198. component_size = 4;
  1199. break;
  1200. }
  1201. if (format == GL_DEPTH_COMPONENT) {
  1202. auto const row_stride = (width * component_size + m_pack_alignment - 1) / m_pack_alignment * m_pack_alignment;
  1203. // Read from depth buffer
  1204. for (GLsizei i = 0; i < height; ++i) {
  1205. for (GLsizei j = 0; j < width; ++j) {
  1206. float depth = m_rasterizer.get_depthbuffer_value(x + j, y + i);
  1207. auto char_ptr = reinterpret_cast<char*>(pixels) + i * row_stride + j * component_size;
  1208. switch (type) {
  1209. case GL_BYTE:
  1210. *reinterpret_cast<GLchar*>(char_ptr) = float_to_i8(depth);
  1211. break;
  1212. case GL_SHORT:
  1213. *reinterpret_cast<GLshort*>(char_ptr) = float_to_i16(depth);
  1214. break;
  1215. case GL_INT:
  1216. *reinterpret_cast<GLint*>(char_ptr) = float_to_i32(depth);
  1217. break;
  1218. case GL_UNSIGNED_BYTE:
  1219. *reinterpret_cast<GLubyte*>(char_ptr) = float_to_u8(depth);
  1220. break;
  1221. case GL_UNSIGNED_SHORT:
  1222. *reinterpret_cast<GLushort*>(char_ptr) = float_to_u16(depth);
  1223. break;
  1224. case GL_UNSIGNED_INT:
  1225. *reinterpret_cast<GLuint*>(char_ptr) = float_to_u32(depth);
  1226. break;
  1227. case GL_FLOAT:
  1228. *reinterpret_cast<GLfloat*>(char_ptr) = min(max(depth, 0.0f), 1.0f);
  1229. break;
  1230. }
  1231. }
  1232. }
  1233. return;
  1234. }
  1235. bool write_red = false;
  1236. bool write_green = false;
  1237. bool write_blue = false;
  1238. bool write_alpha = false;
  1239. size_t component_count = 0;
  1240. size_t red_offset = 0;
  1241. size_t green_offset = 0;
  1242. size_t blue_offset = 0;
  1243. size_t alpha_offset = 0;
  1244. char* red_ptr = nullptr;
  1245. char* green_ptr = nullptr;
  1246. char* blue_ptr = nullptr;
  1247. char* alpha_ptr = nullptr;
  1248. switch (format) {
  1249. case GL_RGB:
  1250. write_red = true;
  1251. write_green = true;
  1252. write_blue = true;
  1253. component_count = 3;
  1254. red_offset = 2;
  1255. green_offset = 1;
  1256. blue_offset = 0;
  1257. break;
  1258. case GL_RGBA:
  1259. write_red = true;
  1260. write_green = true;
  1261. write_blue = true;
  1262. write_alpha = true;
  1263. component_count = 4;
  1264. red_offset = 3;
  1265. green_offset = 2;
  1266. blue_offset = 1;
  1267. alpha_offset = 0;
  1268. break;
  1269. case GL_RED:
  1270. write_red = true;
  1271. component_count = 1;
  1272. red_offset = 0;
  1273. break;
  1274. case GL_GREEN:
  1275. write_green = true;
  1276. component_count = 1;
  1277. green_offset = 0;
  1278. break;
  1279. case GL_BLUE:
  1280. write_blue = true;
  1281. component_count = 1;
  1282. blue_offset = 0;
  1283. break;
  1284. case GL_ALPHA:
  1285. write_alpha = true;
  1286. component_count = 1;
  1287. alpha_offset = 0;
  1288. break;
  1289. }
  1290. auto const pixel_bytes = component_size * component_count;
  1291. auto const row_alignment_bytes = (m_pack_alignment - ((width * pixel_bytes) % m_pack_alignment)) % m_pack_alignment;
  1292. char* out_ptr = reinterpret_cast<char*>(pixels);
  1293. for (int i = 0; i < (int)height; ++i) {
  1294. for (int j = 0; j < (int)width; ++j) {
  1295. Gfx::RGBA32 color {};
  1296. if (m_current_read_buffer == GL_FRONT || m_current_read_buffer == GL_LEFT || m_current_read_buffer == GL_FRONT_LEFT) {
  1297. if (y + i >= m_frontbuffer->width() || x + j >= m_frontbuffer->height())
  1298. color = 0;
  1299. else
  1300. color = m_frontbuffer->scanline(y + i)[x + j];
  1301. } else {
  1302. color = m_rasterizer.get_backbuffer_pixel(x + j, y + i);
  1303. }
  1304. float red = ((color >> 24) & 0xff) / 255.0f;
  1305. float green = ((color >> 16) & 0xff) / 255.0f;
  1306. float blue = ((color >> 8) & 0xff) / 255.0f;
  1307. float alpha = (color & 0xff) / 255.0f;
  1308. // FIXME: Set up write pointers based on selected endianness (glPixelStore)
  1309. red_ptr = out_ptr + (component_size * red_offset);
  1310. green_ptr = out_ptr + (component_size * green_offset);
  1311. blue_ptr = out_ptr + (component_size * blue_offset);
  1312. alpha_ptr = out_ptr + (component_size * alpha_offset);
  1313. switch (type) {
  1314. case GL_BYTE:
  1315. if (write_red)
  1316. *reinterpret_cast<GLchar*>(red_ptr) = float_to_i8(red);
  1317. if (write_green)
  1318. *reinterpret_cast<GLchar*>(green_ptr) = float_to_i8(green);
  1319. if (write_blue)
  1320. *reinterpret_cast<GLchar*>(blue_ptr) = float_to_i8(blue);
  1321. if (write_alpha)
  1322. *reinterpret_cast<GLchar*>(alpha_ptr) = float_to_i8(alpha);
  1323. break;
  1324. case GL_UNSIGNED_BYTE:
  1325. if (write_red)
  1326. *reinterpret_cast<GLubyte*>(red_ptr) = float_to_u8(red);
  1327. if (write_green)
  1328. *reinterpret_cast<GLubyte*>(green_ptr) = float_to_u8(green);
  1329. if (write_blue)
  1330. *reinterpret_cast<GLubyte*>(blue_ptr) = float_to_u8(blue);
  1331. if (write_alpha)
  1332. *reinterpret_cast<GLubyte*>(alpha_ptr) = float_to_u8(alpha);
  1333. break;
  1334. case GL_SHORT:
  1335. if (write_red)
  1336. *reinterpret_cast<GLshort*>(red_ptr) = float_to_i16(red);
  1337. if (write_green)
  1338. *reinterpret_cast<GLshort*>(green_ptr) = float_to_i16(green);
  1339. if (write_blue)
  1340. *reinterpret_cast<GLshort*>(blue_ptr) = float_to_i16(blue);
  1341. if (write_alpha)
  1342. *reinterpret_cast<GLshort*>(alpha_ptr) = float_to_i16(alpha);
  1343. break;
  1344. case GL_UNSIGNED_SHORT:
  1345. if (write_red)
  1346. *reinterpret_cast<GLushort*>(red_ptr) = float_to_u16(red);
  1347. if (write_green)
  1348. *reinterpret_cast<GLushort*>(green_ptr) = float_to_u16(green);
  1349. if (write_blue)
  1350. *reinterpret_cast<GLushort*>(blue_ptr) = float_to_u16(blue);
  1351. if (write_alpha)
  1352. *reinterpret_cast<GLushort*>(alpha_ptr) = float_to_u16(alpha);
  1353. break;
  1354. case GL_INT:
  1355. if (write_red)
  1356. *reinterpret_cast<GLint*>(red_ptr) = float_to_i32(red);
  1357. if (write_green)
  1358. *reinterpret_cast<GLint*>(green_ptr) = float_to_i32(green);
  1359. if (write_blue)
  1360. *reinterpret_cast<GLint*>(blue_ptr) = float_to_i32(blue);
  1361. if (write_alpha)
  1362. *reinterpret_cast<GLint*>(alpha_ptr) = float_to_i32(alpha);
  1363. break;
  1364. case GL_UNSIGNED_INT:
  1365. if (write_red)
  1366. *reinterpret_cast<GLuint*>(red_ptr) = float_to_u32(red);
  1367. if (write_green)
  1368. *reinterpret_cast<GLuint*>(green_ptr) = float_to_u32(green);
  1369. if (write_blue)
  1370. *reinterpret_cast<GLuint*>(blue_ptr) = float_to_u32(blue);
  1371. if (write_alpha)
  1372. *reinterpret_cast<GLuint*>(alpha_ptr) = float_to_u32(alpha);
  1373. break;
  1374. case GL_FLOAT:
  1375. if (write_red)
  1376. *reinterpret_cast<GLfloat*>(red_ptr) = min(max(red, 0.0f), 1.0f);
  1377. if (write_green)
  1378. *reinterpret_cast<GLfloat*>(green_ptr) = min(max(green, 0.0f), 1.0f);
  1379. if (write_blue)
  1380. *reinterpret_cast<GLfloat*>(blue_ptr) = min(max(blue, 0.0f), 1.0f);
  1381. if (write_alpha)
  1382. *reinterpret_cast<GLfloat*>(alpha_ptr) = min(max(alpha, 0.0f), 1.0f);
  1383. break;
  1384. }
  1385. out_ptr += pixel_bytes;
  1386. }
  1387. out_ptr += row_alignment_bytes;
  1388. }
  1389. }
  1390. void SoftwareGLContext::gl_bind_texture(GLenum target, GLuint texture)
  1391. {
  1392. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1393. // FIXME: We only support GL_TEXTURE_2D for now
  1394. RETURN_WITH_ERROR_IF(target != GL_TEXTURE_2D, GL_INVALID_ENUM);
  1395. if (texture == 0) {
  1396. switch (target) {
  1397. case GL_TEXTURE_2D:
  1398. m_active_texture_unit->bind_texture_to_target(target, nullptr);
  1399. return;
  1400. default:
  1401. VERIFY_NOT_REACHED();
  1402. return;
  1403. }
  1404. }
  1405. auto it = m_allocated_textures.find(texture);
  1406. // The texture name does not exist
  1407. RETURN_WITH_ERROR_IF(it == m_allocated_textures.end(), GL_INVALID_VALUE);
  1408. auto texture_object = it->value;
  1409. // Binding a texture to a different target than it was first bound is an invalid operation
  1410. // FIXME: We only support GL_TEXTURE_2D for now
  1411. RETURN_WITH_ERROR_IF(target == GL_TEXTURE_2D && !texture_object.is_null() && !texture_object->is_texture_2d(), GL_INVALID_OPERATION);
  1412. if (!texture_object) {
  1413. // This is the first time the texture is bound. Allocate an actual texture object
  1414. switch (target) {
  1415. case GL_TEXTURE_2D:
  1416. texture_object = adopt_ref(*new Texture2D());
  1417. break;
  1418. default:
  1419. VERIFY_NOT_REACHED();
  1420. }
  1421. m_allocated_textures.set(texture, texture_object);
  1422. }
  1423. switch (target) {
  1424. case GL_TEXTURE_2D:
  1425. m_active_texture_unit->bind_texture_to_target(target, texture_object);
  1426. break;
  1427. }
  1428. }
  1429. void SoftwareGLContext::gl_active_texture(GLenum texture)
  1430. {
  1431. RETURN_WITH_ERROR_IF(texture < GL_TEXTURE0 || texture > GL_TEXTURE31, GL_INVALID_ENUM);
  1432. m_active_texture_unit = &m_texture_units.at(texture - GL_TEXTURE0);
  1433. }
  1434. void SoftwareGLContext::gl_get_booleanv(GLenum pname, GLboolean* data)
  1435. {
  1436. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1437. auto optional_parameter = get_context_parameter(pname);
  1438. RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
  1439. auto parameter = optional_parameter.release_value();
  1440. switch (parameter.type) {
  1441. case GL_BOOL:
  1442. *data = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
  1443. break;
  1444. case GL_DOUBLE:
  1445. *data = (parameter.value.double_value == 0.0) ? GL_FALSE : GL_TRUE;
  1446. break;
  1447. case GL_INT:
  1448. *data = (parameter.value.integer_value == 0) ? GL_FALSE : GL_TRUE;
  1449. break;
  1450. default:
  1451. VERIFY_NOT_REACHED();
  1452. }
  1453. }
  1454. void SoftwareGLContext::gl_get_doublev(GLenum pname, GLdouble* params)
  1455. {
  1456. get_floating_point(pname, params);
  1457. }
  1458. void SoftwareGLContext::gl_get_floatv(GLenum pname, GLfloat* params)
  1459. {
  1460. get_floating_point(pname, params);
  1461. }
  1462. template<typename T>
  1463. void SoftwareGLContext::get_floating_point(GLenum pname, T* params)
  1464. {
  1465. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1466. // Handle special matrix cases first
  1467. auto flatten_and_assign_matrix = [&params](const FloatMatrix4x4& matrix) {
  1468. auto elements = matrix.elements();
  1469. for (size_t i = 0; i < 4; ++i)
  1470. for (size_t j = 0; j < 4; ++j)
  1471. params[i * 4 + j] = static_cast<T>(elements[i][j]);
  1472. };
  1473. switch (pname) {
  1474. case GL_MODELVIEW_MATRIX:
  1475. if (m_current_matrix_mode == GL_MODELVIEW)
  1476. flatten_and_assign_matrix(m_model_view_matrix);
  1477. else if (m_model_view_matrix_stack.is_empty())
  1478. flatten_and_assign_matrix(FloatMatrix4x4::identity());
  1479. else
  1480. flatten_and_assign_matrix(m_model_view_matrix_stack.last());
  1481. return;
  1482. case GL_PROJECTION_MATRIX:
  1483. if (m_current_matrix_mode == GL_PROJECTION)
  1484. flatten_and_assign_matrix(m_projection_matrix);
  1485. else if (m_projection_matrix_stack.is_empty())
  1486. flatten_and_assign_matrix(FloatMatrix4x4::identity());
  1487. else
  1488. flatten_and_assign_matrix(m_projection_matrix_stack.last());
  1489. return;
  1490. }
  1491. // Regular parameters
  1492. auto optional_parameter = get_context_parameter(pname);
  1493. RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
  1494. auto parameter = optional_parameter.release_value();
  1495. switch (parameter.type) {
  1496. case GL_BOOL:
  1497. *params = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
  1498. break;
  1499. case GL_DOUBLE:
  1500. for (size_t i = 0; i < parameter.count; ++i) {
  1501. params[i] = parameter.value.double_list[i];
  1502. }
  1503. break;
  1504. case GL_INT:
  1505. for (size_t i = 0; i < parameter.count; ++i) {
  1506. params[i] = parameter.value.integer_list[i];
  1507. }
  1508. break;
  1509. default:
  1510. VERIFY_NOT_REACHED();
  1511. }
  1512. }
  1513. void SoftwareGLContext::gl_get_integerv(GLenum pname, GLint* data)
  1514. {
  1515. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1516. auto optional_parameter = get_context_parameter(pname);
  1517. RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
  1518. auto parameter = optional_parameter.release_value();
  1519. switch (parameter.type) {
  1520. case GL_BOOL:
  1521. *data = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
  1522. break;
  1523. case GL_DOUBLE: {
  1524. double const int_range = static_cast<double>(NumericLimits<GLint>::max()) - NumericLimits<GLint>::min();
  1525. for (size_t i = 0; i < parameter.count; ++i) {
  1526. double const result_factor = (clamp(parameter.value.double_list[i], -1.0, 1.0) + 1.0) / 2.0;
  1527. data[i] = static_cast<GLint>(NumericLimits<GLint>::min() + result_factor * int_range);
  1528. }
  1529. break;
  1530. }
  1531. case GL_INT:
  1532. for (size_t i = 0; i < parameter.count; ++i) {
  1533. data[i] = parameter.value.integer_list[i];
  1534. }
  1535. break;
  1536. default:
  1537. VERIFY_NOT_REACHED();
  1538. }
  1539. }
  1540. void SoftwareGLContext::gl_depth_mask(GLboolean flag)
  1541. {
  1542. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_depth_mask, flag);
  1543. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1544. auto options = m_rasterizer.options();
  1545. options.enable_depth_write = (flag != GL_FALSE);
  1546. m_rasterizer.set_options(options);
  1547. }
  1548. void SoftwareGLContext::gl_enable_client_state(GLenum cap)
  1549. {
  1550. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1551. switch (cap) {
  1552. case GL_VERTEX_ARRAY:
  1553. m_client_side_vertex_array_enabled = true;
  1554. break;
  1555. case GL_COLOR_ARRAY:
  1556. m_client_side_color_array_enabled = true;
  1557. break;
  1558. case GL_TEXTURE_COORD_ARRAY:
  1559. m_client_side_texture_coord_array_enabled = true;
  1560. break;
  1561. default:
  1562. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  1563. }
  1564. }
  1565. void SoftwareGLContext::gl_disable_client_state(GLenum cap)
  1566. {
  1567. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1568. switch (cap) {
  1569. case GL_VERTEX_ARRAY:
  1570. m_client_side_vertex_array_enabled = false;
  1571. break;
  1572. case GL_COLOR_ARRAY:
  1573. m_client_side_color_array_enabled = false;
  1574. break;
  1575. case GL_TEXTURE_COORD_ARRAY:
  1576. m_client_side_texture_coord_array_enabled = false;
  1577. break;
  1578. default:
  1579. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  1580. }
  1581. }
  1582. void SoftwareGLContext::gl_vertex_pointer(GLint size, GLenum type, GLsizei stride, const void* pointer)
  1583. {
  1584. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1585. RETURN_WITH_ERROR_IF(!(size == 2 || size == 3 || size == 4), GL_INVALID_VALUE);
  1586. RETURN_WITH_ERROR_IF(!(type == GL_SHORT || type == GL_INT || type == GL_FLOAT || type == GL_DOUBLE), GL_INVALID_ENUM);
  1587. RETURN_WITH_ERROR_IF(stride < 0, GL_INVALID_VALUE);
  1588. m_client_vertex_pointer.size = size;
  1589. m_client_vertex_pointer.type = type;
  1590. m_client_vertex_pointer.stride = stride;
  1591. m_client_vertex_pointer.pointer = pointer;
  1592. }
  1593. void SoftwareGLContext::gl_color_pointer(GLint size, GLenum type, GLsizei stride, const void* pointer)
  1594. {
  1595. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1596. RETURN_WITH_ERROR_IF(!(size == 3 || size == 4), GL_INVALID_VALUE);
  1597. RETURN_WITH_ERROR_IF(!(type == GL_BYTE
  1598. || type == GL_UNSIGNED_BYTE
  1599. || type == GL_SHORT
  1600. || type == GL_UNSIGNED_SHORT
  1601. || type == GL_INT
  1602. || type == GL_UNSIGNED_INT
  1603. || type == GL_FLOAT
  1604. || type == GL_DOUBLE),
  1605. GL_INVALID_ENUM);
  1606. RETURN_WITH_ERROR_IF(stride < 0, GL_INVALID_VALUE);
  1607. m_client_color_pointer.size = size;
  1608. m_client_color_pointer.type = type;
  1609. m_client_color_pointer.stride = stride;
  1610. m_client_color_pointer.pointer = pointer;
  1611. }
  1612. void SoftwareGLContext::gl_tex_coord_pointer(GLint size, GLenum type, GLsizei stride, const void* pointer)
  1613. {
  1614. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1615. RETURN_WITH_ERROR_IF(!(size == 1 || size == 2 || size == 3 || size == 4), GL_INVALID_VALUE);
  1616. RETURN_WITH_ERROR_IF(!(type == GL_SHORT || type == GL_INT || type == GL_FLOAT || type == GL_DOUBLE), GL_INVALID_ENUM);
  1617. RETURN_WITH_ERROR_IF(stride < 0, GL_INVALID_VALUE);
  1618. m_client_tex_coord_pointer.size = size;
  1619. m_client_tex_coord_pointer.type = type;
  1620. m_client_tex_coord_pointer.stride = stride;
  1621. m_client_tex_coord_pointer.pointer = pointer;
  1622. }
  1623. void SoftwareGLContext::gl_tex_env(GLenum target, GLenum pname, GLfloat param)
  1624. {
  1625. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_tex_env, target, pname, param);
  1626. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1627. if (target == GL_TEXTURE_ENV) {
  1628. if (pname == GL_TEXTURE_ENV_MODE) {
  1629. auto param_enum = static_cast<GLenum>(param);
  1630. switch (param_enum) {
  1631. case GL_MODULATE:
  1632. case GL_REPLACE:
  1633. case GL_DECAL:
  1634. m_active_texture_unit->set_env_mode(param_enum);
  1635. break;
  1636. default:
  1637. // FIXME: We currently only support a subset of possible param values. Implement the rest!
  1638. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  1639. break;
  1640. }
  1641. } else {
  1642. // FIXME: We currently only support a subset of possible pname values. Implement the rest!
  1643. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  1644. }
  1645. } else {
  1646. // FIXME: We currently only support a subset of possible target values. Implement the rest!
  1647. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  1648. }
  1649. }
  1650. void SoftwareGLContext::gl_draw_arrays(GLenum mode, GLint first, GLsizei count)
  1651. {
  1652. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_draw_arrays, mode, first, count);
  1653. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1654. // FIXME: Some modes are still missing (GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES,GL_QUAD_STRIP)
  1655. RETURN_WITH_ERROR_IF(!(mode == GL_TRIANGLE_STRIP
  1656. || mode == GL_TRIANGLE_FAN
  1657. || mode == GL_TRIANGLES
  1658. || mode == GL_QUADS
  1659. || mode == GL_POLYGON),
  1660. GL_INVALID_ENUM);
  1661. RETURN_WITH_ERROR_IF(count < 0, GL_INVALID_VALUE);
  1662. // At least the vertex array needs to be enabled
  1663. if (!m_client_side_vertex_array_enabled)
  1664. return;
  1665. auto last = first + count;
  1666. gl_begin(mode);
  1667. for (int i = first; i < last; i++) {
  1668. if (m_client_side_texture_coord_array_enabled) {
  1669. float tex_coords[4] { 0, 0, 0, 0 };
  1670. read_from_vertex_attribute_pointer(m_client_tex_coord_pointer, i, tex_coords, false);
  1671. gl_tex_coord(tex_coords[0], tex_coords[1], tex_coords[2], tex_coords[3]);
  1672. }
  1673. if (m_client_side_color_array_enabled) {
  1674. float color[4] { 0, 0, 0, 1 };
  1675. read_from_vertex_attribute_pointer(m_client_color_pointer, i, color, true);
  1676. glColor4fv(color);
  1677. }
  1678. float vertex[4] { 0, 0, 0, 1 };
  1679. read_from_vertex_attribute_pointer(m_client_vertex_pointer, i, vertex, false);
  1680. glVertex4fv(vertex);
  1681. }
  1682. gl_end();
  1683. }
  1684. void SoftwareGLContext::gl_draw_elements(GLenum mode, GLsizei count, GLenum type, const void* indices)
  1685. {
  1686. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_draw_elements, mode, count, type, indices);
  1687. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1688. // FIXME: Some modes are still missing (GL_POINTS, GL_LINE_STRIP, GL_LINE_LOOP, GL_LINES,GL_QUAD_STRIP)
  1689. RETURN_WITH_ERROR_IF(!(mode == GL_TRIANGLE_STRIP
  1690. || mode == GL_TRIANGLE_FAN
  1691. || mode == GL_TRIANGLES
  1692. || mode == GL_QUADS
  1693. || mode == GL_POLYGON),
  1694. GL_INVALID_ENUM);
  1695. RETURN_WITH_ERROR_IF(!(type == GL_UNSIGNED_BYTE
  1696. || type == GL_UNSIGNED_SHORT
  1697. || type == GL_UNSIGNED_INT),
  1698. GL_INVALID_ENUM);
  1699. RETURN_WITH_ERROR_IF(count < 0, GL_INVALID_VALUE);
  1700. // At least the vertex array needs to be enabled
  1701. if (!m_client_side_vertex_array_enabled)
  1702. return;
  1703. gl_begin(mode);
  1704. for (int index = 0; index < count; index++) {
  1705. int i = 0;
  1706. switch (type) {
  1707. case GL_UNSIGNED_BYTE:
  1708. i = reinterpret_cast<const GLubyte*>(indices)[index];
  1709. break;
  1710. case GL_UNSIGNED_SHORT:
  1711. i = reinterpret_cast<const GLushort*>(indices)[index];
  1712. break;
  1713. case GL_UNSIGNED_INT:
  1714. i = reinterpret_cast<const GLuint*>(indices)[index];
  1715. break;
  1716. }
  1717. if (m_client_side_texture_coord_array_enabled) {
  1718. float tex_coords[4] { 0, 0, 0, 0 };
  1719. read_from_vertex_attribute_pointer(m_client_tex_coord_pointer, i, tex_coords, false);
  1720. gl_tex_coord(tex_coords[0], tex_coords[1], tex_coords[2], tex_coords[3]);
  1721. }
  1722. if (m_client_side_color_array_enabled) {
  1723. float color[4] { 0, 0, 0, 1 };
  1724. read_from_vertex_attribute_pointer(m_client_color_pointer, i, color, true);
  1725. glColor4fv(color);
  1726. }
  1727. float vertex[4] { 0, 0, 0, 1 };
  1728. read_from_vertex_attribute_pointer(m_client_vertex_pointer, i, vertex, false);
  1729. glVertex4fv(vertex);
  1730. }
  1731. gl_end();
  1732. }
  1733. void SoftwareGLContext::gl_draw_pixels(GLsizei width, GLsizei height, GLenum format, GLenum type, const void* data)
  1734. {
  1735. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_draw_pixels, width, height, format, type, data);
  1736. RETURN_WITH_ERROR_IF(format < GL_COLOR_INDEX || format > GL_BGRA, GL_INVALID_ENUM);
  1737. RETURN_WITH_ERROR_IF((type < GL_BYTE || type > GL_FLOAT)
  1738. && (type < GL_UNSIGNED_BYTE_3_3_2 || type > GL_UNSIGNED_INT_10_10_10_2)
  1739. && (type < GL_UNSIGNED_BYTE_2_3_3_REV || type > GL_UNSIGNED_INT_2_10_10_10_REV),
  1740. GL_INVALID_ENUM);
  1741. RETURN_WITH_ERROR_IF(type == GL_BITMAP && !(format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX), GL_INVALID_ENUM);
  1742. RETURN_WITH_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
  1743. // FIXME: GL_INVALID_OPERATION is generated if format is GL_STENCIL_INDEX and there is no stencil buffer
  1744. // FIXME: GL_INVALID_OPERATION is generated if format is GL_RED, GL_GREEN, GL_BLUE, GL_ALPHA, GL_RGB, GL_RGBA,
  1745. // GL_BGR, GL_BGRA, GL_LUMINANCE, or GL_LUMINANCE_ALPHA, and the GL is in color index mode
  1746. RETURN_WITH_ERROR_IF(format != GL_RGB
  1747. && (type == GL_UNSIGNED_BYTE_3_3_2
  1748. || type == GL_UNSIGNED_BYTE_2_3_3_REV
  1749. || type == GL_UNSIGNED_SHORT_5_6_5
  1750. || type == GL_UNSIGNED_SHORT_5_6_5_REV),
  1751. GL_INVALID_OPERATION);
  1752. RETURN_WITH_ERROR_IF(!(format == GL_RGBA || format == GL_BGRA)
  1753. && (type == GL_UNSIGNED_SHORT_4_4_4_4
  1754. || type == GL_UNSIGNED_SHORT_4_4_4_4_REV
  1755. || type == GL_UNSIGNED_SHORT_5_5_5_1
  1756. || type == GL_UNSIGNED_SHORT_1_5_5_5_REV
  1757. || type == GL_UNSIGNED_INT_8_8_8_8
  1758. || type == GL_UNSIGNED_INT_8_8_8_8_REV
  1759. || type == GL_UNSIGNED_INT_10_10_10_2
  1760. || type == GL_UNSIGNED_INT_2_10_10_10_REV),
  1761. GL_INVALID_OPERATION);
  1762. // FIXME: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER
  1763. // target and the buffer object's data store is currently mapped.
  1764. // FIXME: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER
  1765. // target and the data would be unpacked from the buffer object such that the memory reads required would
  1766. // exceed the data store size.
  1767. // FIXME: GL_INVALID_OPERATION is generated if a non-zero buffer object name is bound to the GL_PIXEL_UNPACK_BUFFER
  1768. // target and data is not evenly divisible into the number of bytes needed to store in memory a datum
  1769. // indicated by type.
  1770. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1771. // FIXME: we only support RGBA + GL_UNSIGNED_BYTE, implement all the others!
  1772. if (format != GL_RGBA) {
  1773. dbgln_if(GL_DEBUG, "gl_draw_pixels(): support for format {:#x} not implemented", format);
  1774. return;
  1775. } else if (type != GL_UNSIGNED_BYTE) {
  1776. dbgln_if(GL_DEBUG, "gl_draw_pixels(): support for type {:#x} not implemented", type);
  1777. return;
  1778. }
  1779. auto bitmap_or_error = Gfx::Bitmap::try_create(Gfx::BitmapFormat::BGRA8888, { width, height });
  1780. RETURN_WITH_ERROR_IF(bitmap_or_error.is_error(), GL_OUT_OF_MEMORY);
  1781. auto bitmap = bitmap_or_error.release_value();
  1782. // FIXME: implement support for GL_UNPACK_ALIGNMENT and other pixel parameters
  1783. auto pixel_data = static_cast<u32 const*>(data);
  1784. for (int y = 0; y < height; ++y)
  1785. for (int x = 0; x < width; ++x)
  1786. bitmap->set_pixel(x, y, Color::from_rgba(*(pixel_data++)));
  1787. m_rasterizer.blit(
  1788. bitmap,
  1789. static_cast<int>(m_current_raster_position.window_coordinates.x()),
  1790. static_cast<int>(m_current_raster_position.window_coordinates.y()));
  1791. }
  1792. void SoftwareGLContext::gl_depth_range(GLdouble min, GLdouble max)
  1793. {
  1794. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_depth_range, min, max);
  1795. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1796. auto options = m_rasterizer.options();
  1797. options.depth_min = clamp(min, 0.f, 1.f);
  1798. options.depth_max = clamp(max, 0.f, 1.f);
  1799. m_rasterizer.set_options(options);
  1800. }
  1801. void SoftwareGLContext::gl_depth_func(GLenum func)
  1802. {
  1803. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_depth_func, func);
  1804. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1805. RETURN_WITH_ERROR_IF(!(func == GL_NEVER
  1806. || func == GL_LESS
  1807. || func == GL_EQUAL
  1808. || func == GL_LEQUAL
  1809. || func == GL_GREATER
  1810. || func == GL_NOTEQUAL
  1811. || func == GL_GEQUAL
  1812. || func == GL_ALWAYS),
  1813. GL_INVALID_ENUM);
  1814. auto options = m_rasterizer.options();
  1815. options.depth_func = func;
  1816. m_rasterizer.set_options(options);
  1817. }
  1818. // General helper function to read arbitrary vertex attribute data into a float array
  1819. void SoftwareGLContext::read_from_vertex_attribute_pointer(VertexAttribPointer const& attrib, int index, float* elements, bool normalize)
  1820. {
  1821. auto byte_ptr = reinterpret_cast<const char*>(attrib.pointer);
  1822. size_t stride = attrib.stride;
  1823. switch (attrib.type) {
  1824. case GL_BYTE: {
  1825. if (stride == 0)
  1826. stride = sizeof(GLbyte) * attrib.size;
  1827. for (int i = 0; i < attrib.size; i++) {
  1828. elements[i] = *(reinterpret_cast<const GLbyte*>(byte_ptr + stride * index) + i);
  1829. if (normalize)
  1830. elements[i] /= 0x80;
  1831. }
  1832. break;
  1833. }
  1834. case GL_UNSIGNED_BYTE: {
  1835. if (stride == 0)
  1836. stride = sizeof(GLubyte) * attrib.size;
  1837. for (int i = 0; i < attrib.size; i++) {
  1838. elements[i] = *(reinterpret_cast<const GLubyte*>(byte_ptr + stride * index) + i);
  1839. if (normalize)
  1840. elements[i] /= 0xff;
  1841. }
  1842. break;
  1843. }
  1844. case GL_SHORT: {
  1845. if (stride == 0)
  1846. stride = sizeof(GLshort) * attrib.size;
  1847. for (int i = 0; i < attrib.size; i++) {
  1848. elements[i] = *(reinterpret_cast<const GLshort*>(byte_ptr + stride * index) + i);
  1849. if (normalize)
  1850. elements[i] /= 0x8000;
  1851. }
  1852. break;
  1853. }
  1854. case GL_UNSIGNED_SHORT: {
  1855. if (stride == 0)
  1856. stride = sizeof(GLushort) * attrib.size;
  1857. for (int i = 0; i < attrib.size; i++) {
  1858. elements[i] = *(reinterpret_cast<const GLushort*>(byte_ptr + stride * index) + i);
  1859. if (normalize)
  1860. elements[i] /= 0xffff;
  1861. }
  1862. break;
  1863. }
  1864. case GL_INT: {
  1865. if (stride == 0)
  1866. stride = sizeof(GLint) * attrib.size;
  1867. for (int i = 0; i < attrib.size; i++) {
  1868. elements[i] = *(reinterpret_cast<const GLint*>(byte_ptr + stride * index) + i);
  1869. if (normalize)
  1870. elements[i] /= 0x80000000;
  1871. }
  1872. break;
  1873. }
  1874. case GL_UNSIGNED_INT: {
  1875. if (stride == 0)
  1876. stride = sizeof(GLuint) * attrib.size;
  1877. for (int i = 0; i < attrib.size; i++) {
  1878. elements[i] = *(reinterpret_cast<const GLuint*>(byte_ptr + stride * index) + i);
  1879. if (normalize)
  1880. elements[i] /= 0xffffffff;
  1881. }
  1882. break;
  1883. }
  1884. case GL_FLOAT: {
  1885. if (stride == 0)
  1886. stride = sizeof(GLfloat) * attrib.size;
  1887. for (int i = 0; i < attrib.size; i++) {
  1888. elements[i] = *(reinterpret_cast<const GLfloat*>(byte_ptr + stride * index) + i);
  1889. }
  1890. break;
  1891. }
  1892. case GL_DOUBLE: {
  1893. if (stride == 0)
  1894. stride = sizeof(GLdouble) * attrib.size;
  1895. for (int i = 0; i < attrib.size; i++) {
  1896. elements[i] = static_cast<float>(*(reinterpret_cast<const GLdouble*>(byte_ptr + stride * index) + i));
  1897. }
  1898. break;
  1899. }
  1900. }
  1901. }
  1902. void SoftwareGLContext::gl_color_mask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
  1903. {
  1904. auto options = m_rasterizer.options();
  1905. auto mask = options.color_mask;
  1906. if (!red)
  1907. mask &= ~0x000000ff;
  1908. else
  1909. mask |= 0x000000ff;
  1910. if (!green)
  1911. mask &= ~0x0000ff00;
  1912. else
  1913. mask |= 0x0000ff00;
  1914. if (!blue)
  1915. mask &= ~0x00ff0000;
  1916. else
  1917. mask |= 0x00ff0000;
  1918. if (!alpha)
  1919. mask &= ~0xff000000;
  1920. else
  1921. mask |= 0xff000000;
  1922. options.color_mask = mask;
  1923. m_rasterizer.set_options(options);
  1924. }
  1925. void SoftwareGLContext::gl_polygon_mode(GLenum face, GLenum mode)
  1926. {
  1927. RETURN_WITH_ERROR_IF(!(face == GL_BACK || face == GL_FRONT || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM);
  1928. RETURN_WITH_ERROR_IF(!(mode == GL_POINT || mode == GL_LINE || mode == GL_FILL), GL_INVALID_ENUM);
  1929. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1930. auto options = m_rasterizer.options();
  1931. options.polygon_mode = mode;
  1932. m_rasterizer.set_options(options);
  1933. }
  1934. void SoftwareGLContext::gl_polygon_offset(GLfloat factor, GLfloat units)
  1935. {
  1936. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_polygon_offset, factor, units);
  1937. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1938. auto rasterizer_options = m_rasterizer.options();
  1939. rasterizer_options.depth_offset_factor = factor;
  1940. rasterizer_options.depth_offset_constant = units;
  1941. m_rasterizer.set_options(rasterizer_options);
  1942. }
  1943. void SoftwareGLContext::gl_fogfv(GLenum pname, GLfloat* params)
  1944. {
  1945. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1946. auto options = m_rasterizer.options();
  1947. switch (pname) {
  1948. case GL_FOG_COLOR:
  1949. // Set rasterizer options fog color
  1950. // NOTE: We purposefully don't check for `nullptr` here (as with other calls). The spec states nothing
  1951. // about us checking for such things. If the programmer does so and hits SIGSEGV, that's on them.
  1952. options.fog_color = FloatVector4 { params[0], params[1], params[2], params[3] };
  1953. break;
  1954. default:
  1955. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  1956. }
  1957. m_rasterizer.set_options(options);
  1958. }
  1959. void SoftwareGLContext::gl_fogf(GLenum pname, GLfloat param)
  1960. {
  1961. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1962. RETURN_WITH_ERROR_IF(param < 0.0f, GL_INVALID_VALUE);
  1963. auto options = m_rasterizer.options();
  1964. switch (pname) {
  1965. case GL_FOG_DENSITY:
  1966. options.fog_density = param;
  1967. break;
  1968. default:
  1969. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  1970. }
  1971. m_rasterizer.set_options(options);
  1972. }
  1973. void SoftwareGLContext::gl_fogi(GLenum pname, GLint param)
  1974. {
  1975. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  1976. RETURN_WITH_ERROR_IF(!(param == GL_EXP || param == GL_EXP2 || param != GL_LINEAR), GL_INVALID_ENUM);
  1977. auto options = m_rasterizer.options();
  1978. switch (pname) {
  1979. case GL_FOG_MODE:
  1980. options.fog_mode = param;
  1981. break;
  1982. default:
  1983. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  1984. }
  1985. m_rasterizer.set_options(options);
  1986. }
  1987. void SoftwareGLContext::gl_pixel_storei(GLenum pname, GLint param)
  1988. {
  1989. // FIXME: Implement missing parameters
  1990. switch (pname) {
  1991. case GL_PACK_ALIGNMENT:
  1992. RETURN_WITH_ERROR_IF(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE);
  1993. m_pack_alignment = param;
  1994. break;
  1995. case GL_UNPACK_ROW_LENGTH:
  1996. RETURN_WITH_ERROR_IF(param < 0, GL_INVALID_VALUE);
  1997. m_unpack_row_length = static_cast<size_t>(param);
  1998. break;
  1999. case GL_UNPACK_ALIGNMENT:
  2000. RETURN_WITH_ERROR_IF(param != 1 && param != 2 && param != 4 && param != 8, GL_INVALID_VALUE);
  2001. m_unpack_alignment = param;
  2002. break;
  2003. default:
  2004. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  2005. break;
  2006. }
  2007. }
  2008. void SoftwareGLContext::gl_scissor(GLint x, GLint y, GLsizei width, GLsizei height)
  2009. {
  2010. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_scissor, x, y, width, height);
  2011. RETURN_WITH_ERROR_IF(width < 0 || height < 0, GL_INVALID_VALUE);
  2012. auto options = m_rasterizer.options();
  2013. options.scissor_box = { x, y, width, height };
  2014. m_rasterizer.set_options(options);
  2015. }
  2016. void SoftwareGLContext::gl_stencil_func_separate(GLenum face, GLenum func, GLint ref, GLuint mask)
  2017. {
  2018. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_stencil_func_separate, face, func, ref, mask);
  2019. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2020. RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM);
  2021. RETURN_WITH_ERROR_IF(!(func == GL_NEVER
  2022. || func == GL_LESS
  2023. || func == GL_LEQUAL
  2024. || func == GL_GREATER
  2025. || func == GL_GEQUAL
  2026. || func == GL_EQUAL
  2027. || func == GL_NOTEQUAL
  2028. || func == GL_ALWAYS),
  2029. GL_INVALID_ENUM);
  2030. // FIXME: "ref is clamped to the range 02^n - 1 , where n is the number of bitplanes in the stencil buffer"
  2031. StencilFunctionOptions new_options = { func, ref, mask };
  2032. if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
  2033. m_stencil_frontfacing_func = new_options;
  2034. if (face == GL_BACK || face == GL_FRONT_AND_BACK)
  2035. m_stencil_backfacing_func = new_options;
  2036. }
  2037. void SoftwareGLContext::gl_stencil_op_separate(GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass)
  2038. {
  2039. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_stencil_op_separate, face, sfail, dpfail, dppass);
  2040. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2041. RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM);
  2042. RETURN_WITH_ERROR_IF(!(sfail == GL_KEEP
  2043. || sfail == GL_ZERO
  2044. || sfail == GL_REPLACE
  2045. || sfail == GL_INCR
  2046. || sfail == GL_INCR_WRAP
  2047. || sfail == GL_DECR
  2048. || sfail == GL_DECR_WRAP
  2049. || sfail == GL_INVERT),
  2050. GL_INVALID_ENUM);
  2051. RETURN_WITH_ERROR_IF(!(dpfail == GL_KEEP
  2052. || dpfail == GL_ZERO
  2053. || dpfail == GL_REPLACE
  2054. || dpfail == GL_INCR
  2055. || dpfail == GL_INCR_WRAP
  2056. || dpfail == GL_DECR
  2057. || dpfail == GL_DECR_WRAP
  2058. || dpfail == GL_INVERT),
  2059. GL_INVALID_ENUM);
  2060. RETURN_WITH_ERROR_IF(!(dppass == GL_KEEP
  2061. || dppass == GL_ZERO
  2062. || dppass == GL_REPLACE
  2063. || dppass == GL_INCR
  2064. || dppass == GL_INCR_WRAP
  2065. || dppass == GL_DECR
  2066. || dppass == GL_DECR_WRAP
  2067. || dppass == GL_INVERT),
  2068. GL_INVALID_ENUM);
  2069. StencilOperationOptions new_options = { sfail, dpfail, dppass };
  2070. if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
  2071. m_stencil_frontfacing_op = new_options;
  2072. if (face == GL_BACK || face == GL_FRONT_AND_BACK)
  2073. m_stencil_backfacing_op = new_options;
  2074. }
  2075. void SoftwareGLContext::gl_normal(GLfloat nx, GLfloat ny, GLfloat nz)
  2076. {
  2077. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_normal, nx, ny, nz);
  2078. m_current_vertex_normal = { nx, ny, nz };
  2079. }
  2080. void SoftwareGLContext::gl_raster_pos(GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  2081. {
  2082. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_raster_pos, x, y, z, w);
  2083. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2084. m_current_raster_position.window_coordinates = { x, y, z };
  2085. m_current_raster_position.clip_coordinate_value = w;
  2086. }
  2087. void SoftwareGLContext::gl_materialv(GLenum face, GLenum pname, GLfloat const* params)
  2088. {
  2089. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_materialv, face, pname, params);
  2090. RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM);
  2091. RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT
  2092. || pname == GL_DIFFUSE
  2093. || pname == GL_SPECULAR
  2094. || pname == GL_EMISSION
  2095. || pname == GL_SHININESS
  2096. || pname == GL_AMBIENT_AND_DIFFUSE
  2097. || pname == GL_COLOR_INDEXES),
  2098. GL_INVALID_ENUM);
  2099. GLfloat x, y, z, w;
  2100. switch (pname) {
  2101. case GL_SHININESS:
  2102. x = params[0];
  2103. y = 0.0f;
  2104. z = 0.0f;
  2105. w = 0.0f;
  2106. break;
  2107. case GL_COLOR_INDEXES:
  2108. x = params[0];
  2109. y = params[1];
  2110. z = params[2];
  2111. w = 0.0f;
  2112. break;
  2113. default:
  2114. x = params[0];
  2115. y = params[1];
  2116. z = params[2];
  2117. w = params[3];
  2118. }
  2119. // FIXME: implement this method
  2120. dbgln_if(GL_DEBUG, "SoftwareGLContext FIXME: gl_materialv({}, {}, {}, {}, {}, {})", face, pname, x, y, z, w);
  2121. }
  2122. void SoftwareGLContext::gl_line_width(GLfloat width)
  2123. {
  2124. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_line_width, width);
  2125. RETURN_WITH_ERROR_IF(width <= 0, GL_INVALID_VALUE);
  2126. m_line_width = width;
  2127. }
  2128. void SoftwareGLContext::gl_push_attrib(GLbitfield mask)
  2129. {
  2130. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_push_attrib, mask);
  2131. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2132. // FIXME: implement
  2133. dbgln_if(GL_DEBUG, "SoftwareGLContext FIXME: implement gl_push_attrib({})", mask);
  2134. }
  2135. void SoftwareGLContext::gl_pop_attrib()
  2136. {
  2137. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_pop_attrib);
  2138. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2139. // FIXME: implement
  2140. dbgln_if(GL_DEBUG, "SoftwareGLContext FIXME: implement gl_pop_attrib()");
  2141. }
  2142. void SoftwareGLContext::gl_light_model(GLenum pname, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
  2143. {
  2144. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_light_model, pname, x, y, z, w);
  2145. RETURN_WITH_ERROR_IF(!(pname == GL_LIGHT_MODEL_AMBIENT
  2146. || pname == GL_LIGHT_MODEL_TWO_SIDE),
  2147. GL_INVALID_ENUM);
  2148. switch (pname) {
  2149. case GL_LIGHT_MODEL_AMBIENT:
  2150. m_light_model_ambient = { x, y, z, w };
  2151. break;
  2152. case GL_LIGHT_MODEL_TWO_SIDE:
  2153. VERIFY(y == 0.0f && z == 0.0f && w == 0.0f);
  2154. m_light_model_two_side = x;
  2155. break;
  2156. default:
  2157. VERIFY_NOT_REACHED();
  2158. }
  2159. }
  2160. void SoftwareGLContext::gl_bitmap(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, GLubyte const* bitmap)
  2161. {
  2162. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_bitmap, width, height, xorig, yorig, xmove, ymove, bitmap);
  2163. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2164. // FIXME: implement
  2165. dbgln_if(GL_DEBUG, "SoftwareGLContext FIXME: implement gl_bitmap({}, {}, {}, {}, {}, {}, {})", width, height, xorig, yorig, xmove, ymove, bitmap);
  2166. }
  2167. void SoftwareGLContext::gl_copy_tex_image_2d(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
  2168. {
  2169. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_copy_tex_image_2d, target, level, internalformat, x, y, width, height, border);
  2170. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  2171. // FIXME: implement
  2172. dbgln_if(GL_DEBUG, "SoftwareGLContext FIXME: implement gl_copy_tex_image_2d({:#x}, {}, {:#x}, {}, {}, {}, {}, {})",
  2173. target, level, internalformat, x, y, width, height, border);
  2174. }
  2175. void SoftwareGLContext::present()
  2176. {
  2177. m_rasterizer.blit_to(*m_frontbuffer);
  2178. }
  2179. }