SoftwareGLContext.cpp 83 KB

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