SoftwareGLContext.cpp 105 KB

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