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