ContextParameter.cpp 20 KB

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