ContextParameter.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. /*
  2. * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
  3. * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org>
  4. * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
  5. *
  6. * SPDX-License-Identifier: BSD-2-Clause
  7. */
  8. #include <AK/Debug.h>
  9. #include <LibGL/GLContext.h>
  10. namespace GL {
  11. Optional<ContextParameter> GLContext::get_context_parameter(GLenum name)
  12. {
  13. switch (name) {
  14. case GL_ACTIVE_TEXTURE:
  15. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(GL_TEXTURE0 + m_active_texture_unit_index) } };
  16. case GL_ALPHA_BITS:
  17. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(u8) * 8 } };
  18. case GL_ALPHA_TEST:
  19. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_alpha_test_enabled } };
  20. case GL_BLEND:
  21. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_blend_enabled } };
  22. case GL_BLEND_DST_ALPHA:
  23. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_destination_factor) } };
  24. case GL_BLEND_SRC_ALPHA:
  25. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_source_factor) } };
  26. case GL_BLUE_BITS:
  27. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(u8) * 8 } };
  28. case GL_CLIENT_ACTIVE_TEXTURE:
  29. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(GL_TEXTURE0 + m_client_active_texture) } };
  30. case GL_COLOR_CLEAR_VALUE:
  31. return ContextParameter {
  32. .type = GL_DOUBLE,
  33. .count = 4,
  34. .value = {
  35. .double_list = {
  36. static_cast<GLdouble>(m_clear_color.x()),
  37. static_cast<GLdouble>(m_clear_color.y()),
  38. static_cast<GLdouble>(m_clear_color.z()),
  39. static_cast<GLdouble>(m_clear_color.w()),
  40. } }
  41. };
  42. case GL_COLOR_MATERIAL:
  43. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_color_material_enabled } };
  44. case GL_COLOR_MATERIAL_FACE:
  45. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_color_material_face) } };
  46. case GL_COLOR_MATERIAL_MODE:
  47. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_color_material_mode) } };
  48. case GL_CURRENT_COLOR:
  49. return ContextParameter {
  50. .type = GL_DOUBLE,
  51. .count = 4,
  52. .value = {
  53. .double_list = {
  54. static_cast<double>(m_current_vertex_color.x()),
  55. static_cast<double>(m_current_vertex_color.y()),
  56. static_cast<double>(m_current_vertex_color.z()),
  57. static_cast<double>(m_current_vertex_color.w()),
  58. } }
  59. };
  60. case GL_CULL_FACE:
  61. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_cull_faces } };
  62. case GL_DEPTH_BITS:
  63. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  64. case GL_DEPTH_CLEAR_VALUE:
  65. return ContextParameter { .type = GL_DOUBLE, .value = { .double_value = static_cast<GLdouble>(m_clear_depth) } };
  66. case GL_DEPTH_TEST:
  67. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_depth_test_enabled } };
  68. case GL_DITHER:
  69. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_dither_enabled } };
  70. case GL_DOUBLEBUFFER:
  71. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = true } };
  72. case GL_FOG: {
  73. auto fog_enabled = m_rasterizer->options().fog_enabled;
  74. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = fog_enabled } };
  75. }
  76. case GL_GREEN_BITS:
  77. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(u8) * 8 } };
  78. case GL_LIGHTING:
  79. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_lighting_enabled } };
  80. case GL_LINE_SMOOTH:
  81. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_line_smooth } };
  82. case GL_MAX_CLIP_PLANES:
  83. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_device_info.max_clip_planes) } };
  84. case GL_MAX_LIGHTS:
  85. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_device_info.num_lights) } };
  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_LOD_BIAS:
  91. return ContextParameter { .type = GL_DOUBLE, .value = { .double_value = static_cast<GLdouble>(m_device_info.max_texture_lod_bias) } };
  92. case GL_MAX_TEXTURE_SIZE:
  93. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_device_info.max_texture_size) } };
  94. case GL_MAX_TEXTURE_STACK_DEPTH:
  95. return ContextParameter { .type = GL_INT, .value = { .integer_value = TEXTURE_MATRIX_STACK_LIMIT } };
  96. case GL_MAX_TEXTURE_UNITS:
  97. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_texture_units.size()) } };
  98. case GL_NORMAL_ARRAY_TYPE:
  99. return ContextParameter { .type = GL_INT, .value = { .integer_value = GL_FLOAT } };
  100. case GL_NORMALIZE:
  101. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_normalize } };
  102. case GL_PACK_ALIGNMENT:
  103. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.pack_alignment } };
  104. case GL_PACK_IMAGE_HEIGHT:
  105. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.image_height } };
  106. case GL_PACK_LSB_FIRST:
  107. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_packing_parameters.least_significant_bit_first } };
  108. case GL_PACK_ROW_LENGTH:
  109. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.row_length } };
  110. case GL_PACK_SKIP_IMAGES:
  111. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.skip_images } };
  112. case GL_PACK_SKIP_PIXELS:
  113. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.skip_pixels } };
  114. case GL_PACK_SKIP_ROWS:
  115. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.skip_rows } };
  116. case GL_PACK_SWAP_BYTES:
  117. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_packing_parameters.swap_bytes } };
  118. case GL_POINT_SMOOTH:
  119. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_point_smooth } };
  120. case GL_POINT_SIZE:
  121. return ContextParameter { .type = GL_DOUBLE, .value = { .double_value = static_cast<GLdouble>(m_point_size) } };
  122. case GL_POLYGON_OFFSET_FILL:
  123. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_depth_offset_enabled } };
  124. case GL_RED_BITS:
  125. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(u8) * 8 } };
  126. case GL_SAMPLE_BUFFERS:
  127. return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
  128. case GL_SAMPLES:
  129. return ContextParameter { .type = GL_INT, .value = { .integer_value = 1 } };
  130. case GL_SCISSOR_BOX: {
  131. auto scissor_box = m_rasterizer->options().scissor_box;
  132. return ContextParameter {
  133. .type = GL_INT,
  134. .count = 4,
  135. .value = {
  136. .integer_list = {
  137. scissor_box.x(),
  138. scissor_box.y(),
  139. scissor_box.width(),
  140. scissor_box.height(),
  141. } }
  142. };
  143. }
  144. case GL_SCISSOR_TEST: {
  145. auto scissor_enabled = m_rasterizer->options().scissor_enabled;
  146. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = scissor_enabled } };
  147. }
  148. case GL_STENCIL_BITS:
  149. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_device_info.stencil_bits } };
  150. case GL_STENCIL_CLEAR_VALUE:
  151. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_clear_stencil } };
  152. case GL_STENCIL_TEST:
  153. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_stencil_test_enabled } };
  154. case GL_TEXTURE_1D:
  155. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_1d_enabled() } };
  156. case GL_TEXTURE_2D:
  157. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_2d_enabled() } };
  158. case GL_TEXTURE_3D:
  159. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_3d_enabled() } };
  160. case GL_TEXTURE_CUBE_MAP:
  161. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_cube_map_enabled() } };
  162. case GL_TEXTURE_GEN_Q:
  163. case GL_TEXTURE_GEN_R:
  164. case GL_TEXTURE_GEN_S:
  165. case GL_TEXTURE_GEN_T: {
  166. auto generation_enabled = texture_coordinate_generation(m_active_texture_unit_index, name).enabled;
  167. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = generation_enabled } };
  168. }
  169. case GL_UNPACK_ALIGNMENT:
  170. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.pack_alignment } };
  171. case GL_UNPACK_IMAGE_HEIGHT:
  172. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.image_height } };
  173. case GL_UNPACK_LSB_FIRST:
  174. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_unpacking_parameters.least_significant_bit_first } };
  175. case GL_UNPACK_ROW_LENGTH:
  176. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.row_length } };
  177. case GL_UNPACK_SKIP_IMAGES:
  178. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.skip_images } };
  179. case GL_UNPACK_SKIP_PIXELS:
  180. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.skip_pixels } };
  181. case GL_UNPACK_SKIP_ROWS:
  182. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.skip_rows } };
  183. case GL_UNPACK_SWAP_BYTES:
  184. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_unpacking_parameters.swap_bytes } };
  185. case GL_VIEWPORT:
  186. return ContextParameter {
  187. .type = GL_INT,
  188. .count = 4,
  189. .value = {
  190. .integer_list = {
  191. m_viewport.x(),
  192. m_viewport.y(),
  193. m_viewport.width(),
  194. m_viewport.height(),
  195. } }
  196. };
  197. default:
  198. dbgln_if(GL_DEBUG, "get_context_parameter({:#x}): unknown context parameter", name);
  199. return {};
  200. }
  201. }
  202. void GLContext::gl_disable(GLenum capability)
  203. {
  204. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_disable, capability);
  205. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  206. auto rasterizer_options = m_rasterizer->options();
  207. bool update_rasterizer_options = false;
  208. switch (capability) {
  209. case GL_CLIP_PLANE0:
  210. case GL_CLIP_PLANE1:
  211. case GL_CLIP_PLANE2:
  212. case GL_CLIP_PLANE3:
  213. case GL_CLIP_PLANE4:
  214. case GL_CLIP_PLANE5: {
  215. auto plane_idx = static_cast<size_t>(capability) - GL_CLIP_PLANE0;
  216. m_clip_plane_attributes.enabled &= ~(1 << plane_idx);
  217. m_clip_planes_dirty = true;
  218. break;
  219. }
  220. case GL_COLOR_MATERIAL:
  221. m_color_material_enabled = false;
  222. break;
  223. case GL_CULL_FACE:
  224. m_cull_faces = false;
  225. rasterizer_options.enable_culling = false;
  226. update_rasterizer_options = true;
  227. break;
  228. case GL_DEPTH_TEST:
  229. m_depth_test_enabled = false;
  230. rasterizer_options.enable_depth_test = false;
  231. update_rasterizer_options = true;
  232. break;
  233. case GL_BLEND:
  234. m_blend_enabled = false;
  235. rasterizer_options.enable_blending = false;
  236. update_rasterizer_options = true;
  237. break;
  238. case GL_ALPHA_TEST:
  239. m_alpha_test_enabled = false;
  240. rasterizer_options.enable_alpha_test = false;
  241. update_rasterizer_options = true;
  242. break;
  243. case GL_DITHER:
  244. m_dither_enabled = false;
  245. break;
  246. case GL_FOG:
  247. rasterizer_options.fog_enabled = false;
  248. update_rasterizer_options = true;
  249. break;
  250. case GL_LIGHTING:
  251. m_lighting_enabled = false;
  252. rasterizer_options.lighting_enabled = false;
  253. update_rasterizer_options = true;
  254. break;
  255. case GL_LIGHT0:
  256. case GL_LIGHT1:
  257. case GL_LIGHT2:
  258. case GL_LIGHT3:
  259. case GL_LIGHT4:
  260. case GL_LIGHT5:
  261. case GL_LIGHT6:
  262. case GL_LIGHT7:
  263. m_light_states.at(capability - GL_LIGHT0).is_enabled = false;
  264. m_light_state_is_dirty = true;
  265. break;
  266. case GL_LINE_SMOOTH:
  267. m_line_smooth = false;
  268. rasterizer_options.line_smooth = false;
  269. update_rasterizer_options = true;
  270. break;
  271. case GL_NORMALIZE:
  272. m_normalize = false;
  273. rasterizer_options.normalization_enabled = false;
  274. update_rasterizer_options = true;
  275. break;
  276. case GL_POINT_SMOOTH:
  277. m_point_smooth = false;
  278. rasterizer_options.point_smooth = false;
  279. update_rasterizer_options = true;
  280. break;
  281. case GL_POLYGON_OFFSET_FILL:
  282. m_depth_offset_enabled = false;
  283. rasterizer_options.depth_offset_enabled = false;
  284. update_rasterizer_options = true;
  285. break;
  286. case GL_SCISSOR_TEST:
  287. rasterizer_options.scissor_enabled = false;
  288. update_rasterizer_options = true;
  289. break;
  290. case GL_STENCIL_TEST:
  291. m_stencil_test_enabled = false;
  292. rasterizer_options.enable_stencil_test = false;
  293. update_rasterizer_options = true;
  294. break;
  295. case GL_TEXTURE_1D:
  296. m_active_texture_unit->set_texture_1d_enabled(false);
  297. m_sampler_config_is_dirty = true;
  298. m_texture_units_dirty = true;
  299. break;
  300. case GL_TEXTURE_2D:
  301. m_active_texture_unit->set_texture_2d_enabled(false);
  302. m_sampler_config_is_dirty = true;
  303. m_texture_units_dirty = true;
  304. break;
  305. case GL_TEXTURE_3D:
  306. m_active_texture_unit->set_texture_3d_enabled(false);
  307. m_sampler_config_is_dirty = true;
  308. m_texture_units_dirty = true;
  309. break;
  310. case GL_TEXTURE_CUBE_MAP:
  311. m_active_texture_unit->set_texture_cube_map_enabled(false);
  312. m_sampler_config_is_dirty = true;
  313. m_texture_units_dirty = true;
  314. break;
  315. case GL_TEXTURE_GEN_Q:
  316. case GL_TEXTURE_GEN_R:
  317. case GL_TEXTURE_GEN_S:
  318. case GL_TEXTURE_GEN_T:
  319. texture_coordinate_generation(m_active_texture_unit_index, capability).enabled = false;
  320. m_texture_units_dirty = true;
  321. break;
  322. default:
  323. dbgln_if(GL_DEBUG, "gl_disable({:#x}): unknown parameter", capability);
  324. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  325. }
  326. if (update_rasterizer_options)
  327. m_rasterizer->set_options(rasterizer_options);
  328. }
  329. void GLContext::gl_disable_client_state(GLenum cap)
  330. {
  331. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  332. switch (cap) {
  333. case GL_COLOR_ARRAY:
  334. m_client_side_color_array_enabled = false;
  335. break;
  336. case GL_NORMAL_ARRAY:
  337. m_client_side_normal_array_enabled = false;
  338. break;
  339. case GL_TEXTURE_COORD_ARRAY:
  340. m_client_side_texture_coord_array_enabled[m_client_active_texture] = false;
  341. break;
  342. case GL_VERTEX_ARRAY:
  343. m_client_side_vertex_array_enabled = false;
  344. break;
  345. default:
  346. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  347. }
  348. }
  349. void GLContext::gl_enable(GLenum capability)
  350. {
  351. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_enable, capability);
  352. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  353. auto rasterizer_options = m_rasterizer->options();
  354. bool update_rasterizer_options = false;
  355. switch (capability) {
  356. case GL_CLIP_PLANE0:
  357. case GL_CLIP_PLANE1:
  358. case GL_CLIP_PLANE2:
  359. case GL_CLIP_PLANE3:
  360. case GL_CLIP_PLANE4:
  361. case GL_CLIP_PLANE5: {
  362. auto plane_idx = static_cast<size_t>(capability) - GL_CLIP_PLANE0;
  363. m_clip_plane_attributes.enabled |= (1 << plane_idx);
  364. m_clip_planes_dirty = true;
  365. break;
  366. }
  367. case GL_COLOR_MATERIAL:
  368. m_color_material_enabled = true;
  369. break;
  370. case GL_CULL_FACE:
  371. m_cull_faces = true;
  372. rasterizer_options.enable_culling = true;
  373. update_rasterizer_options = true;
  374. break;
  375. case GL_DEPTH_TEST:
  376. m_depth_test_enabled = true;
  377. rasterizer_options.enable_depth_test = true;
  378. update_rasterizer_options = true;
  379. break;
  380. case GL_BLEND:
  381. m_blend_enabled = true;
  382. rasterizer_options.enable_blending = true;
  383. update_rasterizer_options = true;
  384. break;
  385. case GL_ALPHA_TEST:
  386. m_alpha_test_enabled = true;
  387. rasterizer_options.enable_alpha_test = true;
  388. update_rasterizer_options = true;
  389. break;
  390. case GL_DITHER:
  391. m_dither_enabled = true;
  392. break;
  393. case GL_FOG:
  394. rasterizer_options.fog_enabled = true;
  395. update_rasterizer_options = true;
  396. break;
  397. case GL_LIGHTING:
  398. m_lighting_enabled = true;
  399. rasterizer_options.lighting_enabled = true;
  400. update_rasterizer_options = true;
  401. break;
  402. case GL_LIGHT0:
  403. case GL_LIGHT1:
  404. case GL_LIGHT2:
  405. case GL_LIGHT3:
  406. case GL_LIGHT4:
  407. case GL_LIGHT5:
  408. case GL_LIGHT6:
  409. case GL_LIGHT7:
  410. m_light_states.at(capability - GL_LIGHT0).is_enabled = true;
  411. m_light_state_is_dirty = true;
  412. break;
  413. case GL_LINE_SMOOTH:
  414. m_line_smooth = true;
  415. rasterizer_options.line_smooth = true;
  416. update_rasterizer_options = true;
  417. break;
  418. case GL_NORMALIZE:
  419. m_normalize = true;
  420. rasterizer_options.normalization_enabled = true;
  421. update_rasterizer_options = true;
  422. break;
  423. case GL_POINT_SMOOTH:
  424. m_point_smooth = true;
  425. rasterizer_options.point_smooth = true;
  426. update_rasterizer_options = true;
  427. break;
  428. case GL_POLYGON_OFFSET_FILL:
  429. m_depth_offset_enabled = true;
  430. rasterizer_options.depth_offset_enabled = true;
  431. update_rasterizer_options = true;
  432. break;
  433. case GL_SCISSOR_TEST:
  434. rasterizer_options.scissor_enabled = true;
  435. update_rasterizer_options = true;
  436. break;
  437. case GL_STENCIL_TEST:
  438. m_stencil_test_enabled = true;
  439. rasterizer_options.enable_stencil_test = true;
  440. update_rasterizer_options = true;
  441. break;
  442. case GL_TEXTURE_1D:
  443. m_active_texture_unit->set_texture_1d_enabled(true);
  444. m_sampler_config_is_dirty = true;
  445. m_texture_units_dirty = true;
  446. break;
  447. case GL_TEXTURE_2D:
  448. m_active_texture_unit->set_texture_2d_enabled(true);
  449. m_sampler_config_is_dirty = true;
  450. m_texture_units_dirty = true;
  451. break;
  452. case GL_TEXTURE_3D:
  453. m_active_texture_unit->set_texture_3d_enabled(true);
  454. m_sampler_config_is_dirty = true;
  455. m_texture_units_dirty = true;
  456. break;
  457. case GL_TEXTURE_CUBE_MAP:
  458. m_active_texture_unit->set_texture_cube_map_enabled(true);
  459. m_sampler_config_is_dirty = true;
  460. m_texture_units_dirty = true;
  461. break;
  462. case GL_TEXTURE_GEN_Q:
  463. case GL_TEXTURE_GEN_R:
  464. case GL_TEXTURE_GEN_S:
  465. case GL_TEXTURE_GEN_T:
  466. texture_coordinate_generation(m_active_texture_unit_index, capability).enabled = true;
  467. m_texture_units_dirty = true;
  468. break;
  469. default:
  470. dbgln_if(GL_DEBUG, "gl_enable({:#x}): unknown parameter", capability);
  471. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  472. }
  473. if (update_rasterizer_options)
  474. m_rasterizer->set_options(rasterizer_options);
  475. }
  476. void GLContext::gl_enable_client_state(GLenum cap)
  477. {
  478. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  479. switch (cap) {
  480. case GL_COLOR_ARRAY:
  481. m_client_side_color_array_enabled = true;
  482. break;
  483. case GL_NORMAL_ARRAY:
  484. m_client_side_normal_array_enabled = true;
  485. break;
  486. case GL_TEXTURE_COORD_ARRAY:
  487. m_client_side_texture_coord_array_enabled[m_client_active_texture] = true;
  488. break;
  489. case GL_VERTEX_ARRAY:
  490. m_client_side_vertex_array_enabled = true;
  491. break;
  492. default:
  493. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  494. }
  495. }
  496. void GLContext::gl_get_booleanv(GLenum pname, GLboolean* data)
  497. {
  498. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  499. auto optional_parameter = get_context_parameter(pname);
  500. RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
  501. auto parameter = optional_parameter.release_value();
  502. switch (parameter.type) {
  503. case GL_BOOL:
  504. *data = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
  505. break;
  506. case GL_DOUBLE:
  507. *data = (parameter.value.double_value == 0.0) ? GL_FALSE : GL_TRUE;
  508. break;
  509. case GL_INT:
  510. *data = (parameter.value.integer_value == 0) ? GL_FALSE : GL_TRUE;
  511. break;
  512. default:
  513. VERIFY_NOT_REACHED();
  514. }
  515. }
  516. void GLContext::gl_get_doublev(GLenum pname, GLdouble* params)
  517. {
  518. get_floating_point(pname, params);
  519. }
  520. template<typename T>
  521. void GLContext::get_floating_point(GLenum pname, T* params)
  522. {
  523. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  524. // Handle matrix retrieval first
  525. auto flatten_and_assign_matrix = [&params](FloatMatrix4x4 const& matrix) {
  526. auto elements = matrix.elements();
  527. for (size_t i = 0; i < 4; ++i) {
  528. for (size_t j = 0; j < 4; ++j) {
  529. // Return transposed matrix since OpenGL defines them as column-major
  530. params[i * 4 + j] = static_cast<T>(elements[j][i]);
  531. }
  532. }
  533. };
  534. switch (pname) {
  535. case GL_MODELVIEW_MATRIX:
  536. flatten_and_assign_matrix(model_view_matrix());
  537. return;
  538. case GL_PROJECTION_MATRIX:
  539. flatten_and_assign_matrix(projection_matrix());
  540. return;
  541. }
  542. // Regular parameters
  543. auto optional_parameter = get_context_parameter(pname);
  544. RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
  545. auto parameter = optional_parameter.release_value();
  546. switch (parameter.type) {
  547. case GL_BOOL:
  548. *params = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
  549. break;
  550. case GL_DOUBLE:
  551. for (size_t i = 0; i < parameter.count; ++i)
  552. params[i] = parameter.value.double_list[i];
  553. break;
  554. case GL_INT:
  555. for (size_t i = 0; i < parameter.count; ++i)
  556. params[i] = parameter.value.integer_list[i];
  557. break;
  558. default:
  559. VERIFY_NOT_REACHED();
  560. }
  561. }
  562. void GLContext::gl_get_floatv(GLenum pname, GLfloat* params)
  563. {
  564. get_floating_point(pname, params);
  565. }
  566. void GLContext::gl_get_integerv(GLenum pname, GLint* data)
  567. {
  568. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  569. auto optional_parameter = get_context_parameter(pname);
  570. RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
  571. auto parameter = optional_parameter.release_value();
  572. switch (parameter.type) {
  573. case GL_BOOL:
  574. *data = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
  575. break;
  576. case GL_DOUBLE: {
  577. double const int_range = static_cast<double>(NumericLimits<GLint>::max()) - NumericLimits<GLint>::min();
  578. for (size_t i = 0; i < parameter.count; ++i) {
  579. double const result_factor = (clamp(parameter.value.double_list[i], -1.0, 1.0) + 1.0) / 2.0;
  580. data[i] = static_cast<GLint>(NumericLimits<GLint>::min() + result_factor * int_range);
  581. }
  582. break;
  583. }
  584. case GL_INT:
  585. for (size_t i = 0; i < parameter.count; ++i)
  586. data[i] = parameter.value.integer_list[i];
  587. break;
  588. default:
  589. VERIFY_NOT_REACHED();
  590. }
  591. }
  592. GLboolean GLContext::gl_is_enabled(GLenum capability)
  593. {
  594. RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, 0);
  595. auto optional_parameter = get_context_parameter(capability);
  596. RETURN_VALUE_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM, 0);
  597. auto parameter = optional_parameter.release_value();
  598. RETURN_VALUE_WITH_ERROR_IF(!parameter.is_capability, GL_INVALID_ENUM, 0);
  599. return parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
  600. }
  601. GPU::PackingSpecification GLContext::get_packing_specification(PackingType packing_type)
  602. {
  603. // FIXME: add support for .least_significant_bit_first, .skip_images, .skip_pixels and .skip_rows
  604. auto const& pixel_parameters = (packing_type == PackingType::Pack) ? m_packing_parameters : m_unpacking_parameters;
  605. return {
  606. .depth_stride = static_cast<u32>(pixel_parameters.image_height),
  607. .row_stride = static_cast<u32>(pixel_parameters.row_length),
  608. .byte_alignment = pixel_parameters.pack_alignment,
  609. .component_bytes_order = pixel_parameters.swap_bytes ? GPU::ComponentBytesOrder::Reversed : GPU::ComponentBytesOrder::Normal,
  610. };
  611. }
  612. }