ContextParameter.cpp 26 KB

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