SoftwareGLContext.cpp 89 KB

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