SoftwareGLContext.cpp 99 KB

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