ContextParameter.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549
  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_ALPHA_BITS:
  15. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  16. case GL_ALPHA_TEST:
  17. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_alpha_test_enabled } };
  18. case GL_BLEND:
  19. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_blend_enabled } };
  20. case GL_BLEND_DST_ALPHA:
  21. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_destination_factor) } };
  22. case GL_BLEND_SRC_ALPHA:
  23. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_source_factor) } };
  24. case GL_BLUE_BITS:
  25. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  26. case GL_COLOR_MATERIAL:
  27. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_color_material_enabled } };
  28. case GL_COLOR_MATERIAL_FACE:
  29. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_color_material_face) } };
  30. case GL_COLOR_MATERIAL_MODE:
  31. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_color_material_mode) } };
  32. case GL_CULL_FACE:
  33. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_cull_faces } };
  34. case GL_DEPTH_BITS:
  35. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  36. case GL_DEPTH_TEST:
  37. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_depth_test_enabled } };
  38. case GL_DITHER:
  39. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_dither_enabled } };
  40. case GL_DOUBLEBUFFER:
  41. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = true } };
  42. case GL_FOG: {
  43. auto fog_enabled = m_rasterizer->options().fog_enabled;
  44. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = fog_enabled } };
  45. }
  46. case GL_GREEN_BITS:
  47. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  48. case GL_LIGHTING:
  49. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_lighting_enabled } };
  50. case GL_MAX_LIGHTS:
  51. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_device_info.num_lights) } };
  52. case GL_MAX_MODELVIEW_STACK_DEPTH:
  53. return ContextParameter { .type = GL_INT, .value = { .integer_value = MODELVIEW_MATRIX_STACK_LIMIT } };
  54. case GL_MAX_PROJECTION_STACK_DEPTH:
  55. return ContextParameter { .type = GL_INT, .value = { .integer_value = PROJECTION_MATRIX_STACK_LIMIT } };
  56. case GL_MAX_TEXTURE_SIZE:
  57. return ContextParameter { .type = GL_INT, .value = { .integer_value = 4096 } };
  58. case GL_MAX_TEXTURE_STACK_DEPTH:
  59. return ContextParameter { .type = GL_INT, .value = { .integer_value = TEXTURE_MATRIX_STACK_LIMIT } };
  60. case GL_MAX_TEXTURE_UNITS:
  61. return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_texture_units.size()) } };
  62. case GL_NORMALIZE:
  63. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_normalize } };
  64. case GL_PACK_ALIGNMENT:
  65. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_pack_alignment } };
  66. case GL_PACK_IMAGE_HEIGHT:
  67. return ContextParameter { .type = GL_BOOL, .value = { .integer_value = 0 } };
  68. case GL_PACK_LSB_FIRST:
  69. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = false } };
  70. case GL_PACK_ROW_LENGTH:
  71. return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
  72. case GL_PACK_SKIP_PIXELS:
  73. return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
  74. case GL_PACK_SKIP_ROWS:
  75. return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
  76. case GL_PACK_SWAP_BYTES:
  77. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = false } };
  78. case GL_POINT_SMOOTH:
  79. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_point_smooth } };
  80. case GL_POINT_SIZE:
  81. return ContextParameter { .type = GL_DOUBLE, .value = { .double_value = static_cast<GLdouble>(m_point_size) } };
  82. case GL_POLYGON_OFFSET_FILL:
  83. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_depth_offset_enabled } };
  84. case GL_RED_BITS:
  85. return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
  86. case GL_SCISSOR_BOX: {
  87. auto scissor_box = m_rasterizer->options().scissor_box;
  88. return ContextParameter {
  89. .type = GL_INT,
  90. .count = 4,
  91. .value = {
  92. .integer_list = {
  93. scissor_box.x(),
  94. scissor_box.y(),
  95. scissor_box.width(),
  96. scissor_box.height(),
  97. } }
  98. };
  99. }
  100. case GL_SCISSOR_TEST: {
  101. auto scissor_enabled = m_rasterizer->options().scissor_enabled;
  102. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = scissor_enabled } };
  103. }
  104. case GL_STENCIL_BITS:
  105. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_device_info.stencil_bits } };
  106. case GL_STENCIL_CLEAR_VALUE:
  107. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_clear_stencil } };
  108. case GL_STENCIL_TEST:
  109. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_stencil_test_enabled } };
  110. case GL_TEXTURE_1D:
  111. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_1d_enabled() } };
  112. case GL_TEXTURE_2D:
  113. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_2d_enabled() } };
  114. case GL_TEXTURE_3D:
  115. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_3d_enabled() } };
  116. case GL_TEXTURE_CUBE_MAP:
  117. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_cube_map_enabled() } };
  118. case GL_TEXTURE_GEN_Q:
  119. case GL_TEXTURE_GEN_R:
  120. case GL_TEXTURE_GEN_S:
  121. case GL_TEXTURE_GEN_T: {
  122. auto generation_enabled = texture_coordinate_generation(m_active_texture_unit_index, name).enabled;
  123. return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = generation_enabled } };
  124. }
  125. case GL_UNPACK_ALIGNMENT:
  126. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpack_alignment } };
  127. case GL_UNPACK_IMAGE_HEIGHT:
  128. return ContextParameter { .type = GL_BOOL, .value = { .integer_value = 0 } };
  129. case GL_UNPACK_LSB_FIRST:
  130. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = false } };
  131. case GL_UNPACK_ROW_LENGTH:
  132. return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpack_row_length } };
  133. case GL_UNPACK_SKIP_PIXELS:
  134. return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
  135. case GL_UNPACK_SKIP_ROWS:
  136. return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
  137. case GL_UNPACK_SWAP_BYTES:
  138. return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = false } };
  139. case GL_VIEWPORT:
  140. return ContextParameter {
  141. .type = GL_INT,
  142. .count = 4,
  143. .value = {
  144. .integer_list = {
  145. m_viewport.x(),
  146. m_viewport.y(),
  147. m_viewport.width(),
  148. m_viewport.height(),
  149. } }
  150. };
  151. default:
  152. dbgln_if(GL_DEBUG, "get_context_parameter({:#x}): unknown context parameter", name);
  153. return {};
  154. }
  155. }
  156. void GLContext::gl_disable(GLenum capability)
  157. {
  158. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_disable, capability);
  159. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  160. auto rasterizer_options = m_rasterizer->options();
  161. bool update_rasterizer_options = false;
  162. switch (capability) {
  163. case GL_COLOR_MATERIAL:
  164. m_color_material_enabled = false;
  165. break;
  166. case GL_CULL_FACE:
  167. m_cull_faces = false;
  168. rasterizer_options.enable_culling = false;
  169. update_rasterizer_options = true;
  170. break;
  171. case GL_DEPTH_TEST:
  172. m_depth_test_enabled = false;
  173. rasterizer_options.enable_depth_test = false;
  174. update_rasterizer_options = true;
  175. break;
  176. case GL_BLEND:
  177. m_blend_enabled = false;
  178. rasterizer_options.enable_blending = false;
  179. update_rasterizer_options = true;
  180. break;
  181. case GL_ALPHA_TEST:
  182. m_alpha_test_enabled = false;
  183. rasterizer_options.enable_alpha_test = false;
  184. update_rasterizer_options = true;
  185. break;
  186. case GL_DITHER:
  187. m_dither_enabled = false;
  188. break;
  189. case GL_FOG:
  190. rasterizer_options.fog_enabled = false;
  191. update_rasterizer_options = true;
  192. break;
  193. case GL_LIGHTING:
  194. m_lighting_enabled = false;
  195. rasterizer_options.lighting_enabled = false;
  196. update_rasterizer_options = true;
  197. break;
  198. case GL_LIGHT0:
  199. case GL_LIGHT1:
  200. case GL_LIGHT2:
  201. case GL_LIGHT3:
  202. case GL_LIGHT4:
  203. case GL_LIGHT5:
  204. case GL_LIGHT6:
  205. case GL_LIGHT7:
  206. m_light_states.at(capability - GL_LIGHT0).is_enabled = false;
  207. m_light_state_is_dirty = true;
  208. break;
  209. case GL_NORMALIZE:
  210. m_normalize = false;
  211. rasterizer_options.normalization_enabled = false;
  212. update_rasterizer_options = true;
  213. break;
  214. case GL_POINT_SMOOTH:
  215. m_point_smooth = false;
  216. rasterizer_options.point_smooth = false;
  217. update_rasterizer_options = true;
  218. break;
  219. case GL_POLYGON_OFFSET_FILL:
  220. m_depth_offset_enabled = false;
  221. rasterizer_options.depth_offset_enabled = false;
  222. update_rasterizer_options = true;
  223. break;
  224. case GL_SCISSOR_TEST:
  225. rasterizer_options.scissor_enabled = false;
  226. update_rasterizer_options = true;
  227. break;
  228. case GL_STENCIL_TEST:
  229. m_stencil_test_enabled = false;
  230. rasterizer_options.enable_stencil_test = false;
  231. update_rasterizer_options = true;
  232. break;
  233. case GL_TEXTURE_1D:
  234. m_active_texture_unit->set_texture_1d_enabled(false);
  235. m_sampler_config_is_dirty = true;
  236. break;
  237. case GL_TEXTURE_2D:
  238. m_active_texture_unit->set_texture_2d_enabled(false);
  239. m_sampler_config_is_dirty = true;
  240. break;
  241. case GL_TEXTURE_3D:
  242. m_active_texture_unit->set_texture_3d_enabled(false);
  243. m_sampler_config_is_dirty = true;
  244. break;
  245. case GL_TEXTURE_CUBE_MAP:
  246. m_active_texture_unit->set_texture_cube_map_enabled(false);
  247. m_sampler_config_is_dirty = true;
  248. break;
  249. case GL_TEXTURE_GEN_Q:
  250. case GL_TEXTURE_GEN_R:
  251. case GL_TEXTURE_GEN_S:
  252. case GL_TEXTURE_GEN_T:
  253. texture_coordinate_generation(m_active_texture_unit_index, capability).enabled = false;
  254. m_texcoord_generation_dirty = true;
  255. break;
  256. default:
  257. dbgln_if(GL_DEBUG, "gl_disable({:#x}): unknown parameter", capability);
  258. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  259. }
  260. if (update_rasterizer_options)
  261. m_rasterizer->set_options(rasterizer_options);
  262. }
  263. void GLContext::gl_disable_client_state(GLenum cap)
  264. {
  265. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  266. switch (cap) {
  267. case GL_COLOR_ARRAY:
  268. m_client_side_color_array_enabled = false;
  269. break;
  270. case GL_NORMAL_ARRAY:
  271. m_client_side_normal_array_enabled = false;
  272. break;
  273. case GL_TEXTURE_COORD_ARRAY:
  274. m_client_side_texture_coord_array_enabled[m_client_active_texture] = false;
  275. break;
  276. case GL_VERTEX_ARRAY:
  277. m_client_side_vertex_array_enabled = false;
  278. break;
  279. default:
  280. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  281. }
  282. }
  283. void GLContext::gl_enable(GLenum capability)
  284. {
  285. APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_enable, capability);
  286. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  287. auto rasterizer_options = m_rasterizer->options();
  288. bool update_rasterizer_options = false;
  289. switch (capability) {
  290. case GL_COLOR_MATERIAL:
  291. m_color_material_enabled = true;
  292. break;
  293. case GL_CULL_FACE:
  294. m_cull_faces = true;
  295. rasterizer_options.enable_culling = true;
  296. update_rasterizer_options = true;
  297. break;
  298. case GL_DEPTH_TEST:
  299. m_depth_test_enabled = true;
  300. rasterizer_options.enable_depth_test = true;
  301. update_rasterizer_options = true;
  302. break;
  303. case GL_BLEND:
  304. m_blend_enabled = true;
  305. rasterizer_options.enable_blending = true;
  306. update_rasterizer_options = true;
  307. break;
  308. case GL_ALPHA_TEST:
  309. m_alpha_test_enabled = true;
  310. rasterizer_options.enable_alpha_test = true;
  311. update_rasterizer_options = true;
  312. break;
  313. case GL_DITHER:
  314. m_dither_enabled = true;
  315. break;
  316. case GL_FOG:
  317. rasterizer_options.fog_enabled = true;
  318. update_rasterizer_options = true;
  319. break;
  320. case GL_LIGHTING:
  321. m_lighting_enabled = true;
  322. rasterizer_options.lighting_enabled = true;
  323. update_rasterizer_options = true;
  324. break;
  325. case GL_LIGHT0:
  326. case GL_LIGHT1:
  327. case GL_LIGHT2:
  328. case GL_LIGHT3:
  329. case GL_LIGHT4:
  330. case GL_LIGHT5:
  331. case GL_LIGHT6:
  332. case GL_LIGHT7:
  333. m_light_states.at(capability - GL_LIGHT0).is_enabled = true;
  334. m_light_state_is_dirty = true;
  335. break;
  336. case GL_NORMALIZE:
  337. m_normalize = true;
  338. rasterizer_options.normalization_enabled = true;
  339. update_rasterizer_options = true;
  340. break;
  341. case GL_POINT_SMOOTH:
  342. m_point_smooth = true;
  343. rasterizer_options.point_smooth = true;
  344. update_rasterizer_options = true;
  345. break;
  346. case GL_POLYGON_OFFSET_FILL:
  347. m_depth_offset_enabled = true;
  348. rasterizer_options.depth_offset_enabled = true;
  349. update_rasterizer_options = true;
  350. break;
  351. case GL_SCISSOR_TEST:
  352. rasterizer_options.scissor_enabled = true;
  353. update_rasterizer_options = true;
  354. break;
  355. case GL_STENCIL_TEST:
  356. m_stencil_test_enabled = true;
  357. rasterizer_options.enable_stencil_test = true;
  358. update_rasterizer_options = true;
  359. break;
  360. case GL_TEXTURE_1D:
  361. m_active_texture_unit->set_texture_1d_enabled(true);
  362. m_sampler_config_is_dirty = true;
  363. break;
  364. case GL_TEXTURE_2D:
  365. m_active_texture_unit->set_texture_2d_enabled(true);
  366. m_sampler_config_is_dirty = true;
  367. break;
  368. case GL_TEXTURE_3D:
  369. m_active_texture_unit->set_texture_3d_enabled(true);
  370. m_sampler_config_is_dirty = true;
  371. break;
  372. case GL_TEXTURE_CUBE_MAP:
  373. m_active_texture_unit->set_texture_cube_map_enabled(true);
  374. m_sampler_config_is_dirty = true;
  375. break;
  376. case GL_TEXTURE_GEN_Q:
  377. case GL_TEXTURE_GEN_R:
  378. case GL_TEXTURE_GEN_S:
  379. case GL_TEXTURE_GEN_T:
  380. texture_coordinate_generation(m_active_texture_unit_index, capability).enabled = true;
  381. m_texcoord_generation_dirty = true;
  382. break;
  383. default:
  384. dbgln_if(GL_DEBUG, "gl_enable({:#x}): unknown parameter", capability);
  385. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  386. }
  387. if (update_rasterizer_options)
  388. m_rasterizer->set_options(rasterizer_options);
  389. }
  390. void GLContext::gl_enable_client_state(GLenum cap)
  391. {
  392. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  393. switch (cap) {
  394. case GL_COLOR_ARRAY:
  395. m_client_side_color_array_enabled = true;
  396. break;
  397. case GL_NORMAL_ARRAY:
  398. m_client_side_normal_array_enabled = true;
  399. break;
  400. case GL_TEXTURE_COORD_ARRAY:
  401. m_client_side_texture_coord_array_enabled[m_client_active_texture] = true;
  402. break;
  403. case GL_VERTEX_ARRAY:
  404. m_client_side_vertex_array_enabled = true;
  405. break;
  406. default:
  407. RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
  408. }
  409. }
  410. void GLContext::gl_get_booleanv(GLenum pname, GLboolean* data)
  411. {
  412. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  413. auto optional_parameter = get_context_parameter(pname);
  414. RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
  415. auto parameter = optional_parameter.release_value();
  416. switch (parameter.type) {
  417. case GL_BOOL:
  418. *data = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
  419. break;
  420. case GL_DOUBLE:
  421. *data = (parameter.value.double_value == 0.0) ? GL_FALSE : GL_TRUE;
  422. break;
  423. case GL_INT:
  424. *data = (parameter.value.integer_value == 0) ? GL_FALSE : GL_TRUE;
  425. break;
  426. default:
  427. VERIFY_NOT_REACHED();
  428. }
  429. }
  430. void GLContext::gl_get_doublev(GLenum pname, GLdouble* params)
  431. {
  432. get_floating_point(pname, params);
  433. }
  434. template<typename T>
  435. void GLContext::get_floating_point(GLenum pname, T* params)
  436. {
  437. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  438. // Handle matrix retrieval first
  439. auto flatten_and_assign_matrix = [&params](FloatMatrix4x4 const& matrix) {
  440. auto elements = matrix.elements();
  441. for (size_t i = 0; i < 4; ++i) {
  442. for (size_t j = 0; j < 4; ++j) {
  443. // Return transposed matrix since OpenGL defines them as column-major
  444. params[i * 4 + j] = static_cast<T>(elements[j][i]);
  445. }
  446. }
  447. };
  448. switch (pname) {
  449. case GL_MODELVIEW_MATRIX:
  450. flatten_and_assign_matrix(m_model_view_matrix);
  451. return;
  452. case GL_PROJECTION_MATRIX:
  453. flatten_and_assign_matrix(m_projection_matrix);
  454. return;
  455. }
  456. // Regular parameters
  457. auto optional_parameter = get_context_parameter(pname);
  458. RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
  459. auto parameter = optional_parameter.release_value();
  460. switch (parameter.type) {
  461. case GL_BOOL:
  462. *params = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
  463. break;
  464. case GL_DOUBLE:
  465. for (size_t i = 0; i < parameter.count; ++i)
  466. params[i] = parameter.value.double_list[i];
  467. break;
  468. case GL_INT:
  469. for (size_t i = 0; i < parameter.count; ++i)
  470. params[i] = parameter.value.integer_list[i];
  471. break;
  472. default:
  473. VERIFY_NOT_REACHED();
  474. }
  475. }
  476. void GLContext::gl_get_floatv(GLenum pname, GLfloat* params)
  477. {
  478. get_floating_point(pname, params);
  479. }
  480. void GLContext::gl_get_integerv(GLenum pname, GLint* data)
  481. {
  482. RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
  483. auto optional_parameter = get_context_parameter(pname);
  484. RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
  485. auto parameter = optional_parameter.release_value();
  486. switch (parameter.type) {
  487. case GL_BOOL:
  488. *data = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
  489. break;
  490. case GL_DOUBLE: {
  491. double const int_range = static_cast<double>(NumericLimits<GLint>::max()) - NumericLimits<GLint>::min();
  492. for (size_t i = 0; i < parameter.count; ++i) {
  493. double const result_factor = (clamp(parameter.value.double_list[i], -1.0, 1.0) + 1.0) / 2.0;
  494. data[i] = static_cast<GLint>(NumericLimits<GLint>::min() + result_factor * int_range);
  495. }
  496. break;
  497. }
  498. case GL_INT:
  499. for (size_t i = 0; i < parameter.count; ++i)
  500. data[i] = parameter.value.integer_list[i];
  501. break;
  502. default:
  503. VERIFY_NOT_REACHED();
  504. }
  505. }
  506. GLboolean GLContext::gl_is_enabled(GLenum capability)
  507. {
  508. RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, 0);
  509. auto optional_parameter = get_context_parameter(capability);
  510. RETURN_VALUE_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM, 0);
  511. auto parameter = optional_parameter.release_value();
  512. RETURN_VALUE_WITH_ERROR_IF(!parameter.is_capability, GL_INVALID_ENUM, 0);
  513. return parameter.value.boolean_value;
  514. }
  515. }