123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647 |
- /*
- * Copyright (c) 2021, Jesse Buhagiar <jooster669@gmail.com>
- * Copyright (c) 2021, Stephan Unverwerth <s.unverwerth@serenityos.org>
- * Copyright (c) 2022, Jelle Raaijmakers <jelle@gmta.nl>
- *
- * SPDX-License-Identifier: BSD-2-Clause
- */
- #include <AK/Debug.h>
- #include <LibGL/GLContext.h>
- namespace GL {
- Optional<ContextParameter> GLContext::get_context_parameter(GLenum name)
- {
- switch (name) {
- case GL_ACTIVE_TEXTURE:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(GL_TEXTURE0 + m_active_texture_unit_index) } };
- case GL_ALPHA_BITS:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(u8) * 8 } };
- case GL_ALPHA_TEST:
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_alpha_test_enabled } };
- case GL_BLEND:
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_blend_enabled } };
- case GL_BLEND_DST_ALPHA:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_destination_factor) } };
- case GL_BLEND_SRC_ALPHA:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_blend_source_factor) } };
- case GL_BLUE_BITS:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(u8) * 8 } };
- case GL_CLIENT_ACTIVE_TEXTURE:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(GL_TEXTURE0 + m_client_active_texture) } };
- case GL_COLOR_CLEAR_VALUE:
- return ContextParameter {
- .type = GL_DOUBLE,
- .count = 4,
- .value = {
- .double_list = {
- static_cast<GLdouble>(m_clear_color.x()),
- static_cast<GLdouble>(m_clear_color.y()),
- static_cast<GLdouble>(m_clear_color.z()),
- static_cast<GLdouble>(m_clear_color.w()),
- } }
- };
- case GL_COLOR_MATERIAL:
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_color_material_enabled } };
- case GL_COLOR_MATERIAL_FACE:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_color_material_face) } };
- case GL_COLOR_MATERIAL_MODE:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_color_material_mode) } };
- case GL_CURRENT_COLOR:
- return ContextParameter {
- .type = GL_DOUBLE,
- .count = 4,
- .value = {
- .double_list = {
- static_cast<double>(m_current_vertex_color.x()),
- static_cast<double>(m_current_vertex_color.y()),
- static_cast<double>(m_current_vertex_color.z()),
- static_cast<double>(m_current_vertex_color.w()),
- } }
- };
- case GL_CULL_FACE:
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_cull_faces } };
- case GL_DEPTH_BITS:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(float) * 8 } };
- case GL_DEPTH_CLEAR_VALUE:
- return ContextParameter { .type = GL_DOUBLE, .value = { .double_value = static_cast<GLdouble>(m_clear_depth) } };
- case GL_DEPTH_TEST:
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_depth_test_enabled } };
- case GL_DITHER:
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_dither_enabled } };
- case GL_DOUBLEBUFFER:
- return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = true } };
- case GL_FOG: {
- auto fog_enabled = m_rasterizer->options().fog_enabled;
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = fog_enabled } };
- }
- case GL_GREEN_BITS:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(u8) * 8 } };
- case GL_LIGHTING:
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_lighting_enabled } };
- case GL_LINE_SMOOTH:
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_line_smooth } };
- case GL_MAX_CLIP_PLANES:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_device_info.max_clip_planes) } };
- case GL_MAX_LIGHTS:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_device_info.num_lights) } };
- case GL_MAX_MODELVIEW_STACK_DEPTH:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = MODELVIEW_MATRIX_STACK_LIMIT } };
- case GL_MAX_PROJECTION_STACK_DEPTH:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = PROJECTION_MATRIX_STACK_LIMIT } };
- case GL_MAX_TEXTURE_LOD_BIAS:
- return ContextParameter { .type = GL_DOUBLE, .value = { .double_value = static_cast<GLdouble>(m_device_info.max_texture_lod_bias) } };
- case GL_MAX_TEXTURE_SIZE:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_device_info.max_texture_size) } };
- case GL_MAX_TEXTURE_STACK_DEPTH:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = TEXTURE_MATRIX_STACK_LIMIT } };
- case GL_MAX_TEXTURE_UNITS:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = static_cast<GLint>(m_texture_units.size()) } };
- case GL_NORMAL_ARRAY_TYPE:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = GL_FLOAT } };
- case GL_NORMALIZE:
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_normalize } };
- case GL_PACK_ALIGNMENT:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.pack_alignment } };
- case GL_PACK_IMAGE_HEIGHT:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.image_height } };
- case GL_PACK_LSB_FIRST:
- return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_packing_parameters.least_significant_bit_first } };
- case GL_PACK_ROW_LENGTH:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.row_length } };
- case GL_PACK_SKIP_IMAGES:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.skip_images } };
- case GL_PACK_SKIP_PIXELS:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.skip_pixels } };
- case GL_PACK_SKIP_ROWS:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_packing_parameters.skip_rows } };
- case GL_PACK_SWAP_BYTES:
- return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_packing_parameters.swap_bytes } };
- case GL_POINT_SMOOTH:
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_point_smooth } };
- case GL_POINT_SIZE:
- return ContextParameter { .type = GL_DOUBLE, .value = { .double_value = static_cast<GLdouble>(m_point_size) } };
- case GL_POLYGON_OFFSET_FILL:
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_depth_offset_enabled } };
- case GL_RED_BITS:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = sizeof(u8) * 8 } };
- case GL_SAMPLE_BUFFERS:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = 0 } };
- case GL_SAMPLES:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = 1 } };
- case GL_SCISSOR_BOX: {
- auto scissor_box = m_rasterizer->options().scissor_box;
- return ContextParameter {
- .type = GL_INT,
- .count = 4,
- .value = {
- .integer_list = {
- scissor_box.x(),
- scissor_box.y(),
- scissor_box.width(),
- scissor_box.height(),
- } }
- };
- }
- case GL_SCISSOR_TEST: {
- auto scissor_enabled = m_rasterizer->options().scissor_enabled;
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = scissor_enabled } };
- }
- case GL_STENCIL_BITS:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_device_info.stencil_bits } };
- case GL_STENCIL_CLEAR_VALUE:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_clear_stencil } };
- case GL_STENCIL_TEST:
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = m_stencil_test_enabled } };
- case GL_TEXTURE_1D:
- return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_1d_enabled() } };
- case GL_TEXTURE_2D:
- return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_2d_enabled() } };
- case GL_TEXTURE_3D:
- return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_3d_enabled() } };
- case GL_TEXTURE_CUBE_MAP:
- return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_active_texture_unit->texture_cube_map_enabled() } };
- case GL_TEXTURE_GEN_Q:
- case GL_TEXTURE_GEN_R:
- case GL_TEXTURE_GEN_S:
- case GL_TEXTURE_GEN_T: {
- auto generation_enabled = texture_coordinate_generation(m_active_texture_unit_index, name).enabled;
- return ContextParameter { .type = GL_BOOL, .is_capability = true, .value = { .boolean_value = generation_enabled } };
- }
- case GL_UNPACK_ALIGNMENT:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.pack_alignment } };
- case GL_UNPACK_IMAGE_HEIGHT:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.image_height } };
- case GL_UNPACK_LSB_FIRST:
- return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_unpacking_parameters.least_significant_bit_first } };
- case GL_UNPACK_ROW_LENGTH:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.row_length } };
- case GL_UNPACK_SKIP_IMAGES:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.skip_images } };
- case GL_UNPACK_SKIP_PIXELS:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.skip_pixels } };
- case GL_UNPACK_SKIP_ROWS:
- return ContextParameter { .type = GL_INT, .value = { .integer_value = m_unpacking_parameters.skip_rows } };
- case GL_UNPACK_SWAP_BYTES:
- return ContextParameter { .type = GL_BOOL, .value = { .boolean_value = m_unpacking_parameters.swap_bytes } };
- case GL_VIEWPORT:
- return ContextParameter {
- .type = GL_INT,
- .count = 4,
- .value = {
- .integer_list = {
- m_viewport.x(),
- m_viewport.y(),
- m_viewport.width(),
- m_viewport.height(),
- } }
- };
- default:
- dbgln_if(GL_DEBUG, "get_context_parameter({:#x}): unknown context parameter", name);
- return {};
- }
- }
- void GLContext::gl_disable(GLenum capability)
- {
- APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_disable, capability);
- RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
- auto rasterizer_options = m_rasterizer->options();
- bool update_rasterizer_options = false;
- switch (capability) {
- case GL_CLIP_PLANE0:
- case GL_CLIP_PLANE1:
- case GL_CLIP_PLANE2:
- case GL_CLIP_PLANE3:
- case GL_CLIP_PLANE4:
- case GL_CLIP_PLANE5: {
- auto plane_idx = static_cast<size_t>(capability) - GL_CLIP_PLANE0;
- m_clip_plane_attributes.enabled &= ~(1 << plane_idx);
- m_clip_planes_dirty = true;
- break;
- }
- case GL_COLOR_MATERIAL:
- m_color_material_enabled = false;
- break;
- case GL_CULL_FACE:
- m_cull_faces = false;
- rasterizer_options.enable_culling = false;
- update_rasterizer_options = true;
- break;
- case GL_DEPTH_TEST:
- m_depth_test_enabled = false;
- rasterizer_options.enable_depth_test = false;
- update_rasterizer_options = true;
- break;
- case GL_BLEND:
- m_blend_enabled = false;
- rasterizer_options.enable_blending = false;
- update_rasterizer_options = true;
- break;
- case GL_ALPHA_TEST:
- m_alpha_test_enabled = false;
- rasterizer_options.enable_alpha_test = false;
- update_rasterizer_options = true;
- break;
- case GL_DITHER:
- m_dither_enabled = false;
- break;
- case GL_FOG:
- rasterizer_options.fog_enabled = false;
- update_rasterizer_options = true;
- break;
- case GL_LIGHTING:
- m_lighting_enabled = false;
- rasterizer_options.lighting_enabled = false;
- update_rasterizer_options = true;
- break;
- case GL_LIGHT0:
- case GL_LIGHT1:
- case GL_LIGHT2:
- case GL_LIGHT3:
- case GL_LIGHT4:
- case GL_LIGHT5:
- case GL_LIGHT6:
- case GL_LIGHT7:
- m_light_states.at(capability - GL_LIGHT0).is_enabled = false;
- m_light_state_is_dirty = true;
- break;
- case GL_LINE_SMOOTH:
- m_line_smooth = false;
- rasterizer_options.line_smooth = false;
- update_rasterizer_options = true;
- break;
- case GL_NORMALIZE:
- m_normalize = false;
- rasterizer_options.normalization_enabled = false;
- update_rasterizer_options = true;
- break;
- case GL_POINT_SMOOTH:
- m_point_smooth = false;
- rasterizer_options.point_smooth = false;
- update_rasterizer_options = true;
- break;
- case GL_POLYGON_OFFSET_FILL:
- m_depth_offset_enabled = false;
- rasterizer_options.depth_offset_enabled = false;
- update_rasterizer_options = true;
- break;
- case GL_SCISSOR_TEST:
- rasterizer_options.scissor_enabled = false;
- update_rasterizer_options = true;
- break;
- case GL_STENCIL_TEST:
- m_stencil_test_enabled = false;
- rasterizer_options.enable_stencil_test = false;
- update_rasterizer_options = true;
- break;
- case GL_TEXTURE_1D:
- m_active_texture_unit->set_texture_1d_enabled(false);
- m_sampler_config_is_dirty = true;
- m_texture_units_dirty = true;
- break;
- case GL_TEXTURE_2D:
- m_active_texture_unit->set_texture_2d_enabled(false);
- m_sampler_config_is_dirty = true;
- m_texture_units_dirty = true;
- break;
- case GL_TEXTURE_3D:
- m_active_texture_unit->set_texture_3d_enabled(false);
- m_sampler_config_is_dirty = true;
- m_texture_units_dirty = true;
- break;
- case GL_TEXTURE_CUBE_MAP:
- m_active_texture_unit->set_texture_cube_map_enabled(false);
- m_sampler_config_is_dirty = true;
- m_texture_units_dirty = true;
- break;
- case GL_TEXTURE_GEN_Q:
- case GL_TEXTURE_GEN_R:
- case GL_TEXTURE_GEN_S:
- case GL_TEXTURE_GEN_T:
- texture_coordinate_generation(m_active_texture_unit_index, capability).enabled = false;
- m_texture_units_dirty = true;
- break;
- default:
- dbgln_if(GL_DEBUG, "gl_disable({:#x}): unknown parameter", capability);
- RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
- }
- if (update_rasterizer_options)
- m_rasterizer->set_options(rasterizer_options);
- }
- void GLContext::gl_disable_client_state(GLenum cap)
- {
- RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
- switch (cap) {
- case GL_COLOR_ARRAY:
- m_client_side_color_array_enabled = false;
- break;
- case GL_NORMAL_ARRAY:
- m_client_side_normal_array_enabled = false;
- break;
- case GL_TEXTURE_COORD_ARRAY:
- m_client_side_texture_coord_array_enabled[m_client_active_texture] = false;
- break;
- case GL_VERTEX_ARRAY:
- m_client_side_vertex_array_enabled = false;
- break;
- default:
- RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
- }
- }
- void GLContext::gl_enable(GLenum capability)
- {
- APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_enable, capability);
- RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
- auto rasterizer_options = m_rasterizer->options();
- bool update_rasterizer_options = false;
- switch (capability) {
- case GL_CLIP_PLANE0:
- case GL_CLIP_PLANE1:
- case GL_CLIP_PLANE2:
- case GL_CLIP_PLANE3:
- case GL_CLIP_PLANE4:
- case GL_CLIP_PLANE5: {
- auto plane_idx = static_cast<size_t>(capability) - GL_CLIP_PLANE0;
- m_clip_plane_attributes.enabled |= (1 << plane_idx);
- m_clip_planes_dirty = true;
- break;
- }
- case GL_COLOR_MATERIAL:
- m_color_material_enabled = true;
- break;
- case GL_CULL_FACE:
- m_cull_faces = true;
- rasterizer_options.enable_culling = true;
- update_rasterizer_options = true;
- break;
- case GL_DEPTH_TEST:
- m_depth_test_enabled = true;
- rasterizer_options.enable_depth_test = true;
- update_rasterizer_options = true;
- break;
- case GL_BLEND:
- m_blend_enabled = true;
- rasterizer_options.enable_blending = true;
- update_rasterizer_options = true;
- break;
- case GL_ALPHA_TEST:
- m_alpha_test_enabled = true;
- rasterizer_options.enable_alpha_test = true;
- update_rasterizer_options = true;
- break;
- case GL_DITHER:
- m_dither_enabled = true;
- break;
- case GL_FOG:
- rasterizer_options.fog_enabled = true;
- update_rasterizer_options = true;
- break;
- case GL_LIGHTING:
- m_lighting_enabled = true;
- rasterizer_options.lighting_enabled = true;
- update_rasterizer_options = true;
- break;
- case GL_LIGHT0:
- case GL_LIGHT1:
- case GL_LIGHT2:
- case GL_LIGHT3:
- case GL_LIGHT4:
- case GL_LIGHT5:
- case GL_LIGHT6:
- case GL_LIGHT7:
- m_light_states.at(capability - GL_LIGHT0).is_enabled = true;
- m_light_state_is_dirty = true;
- break;
- case GL_LINE_SMOOTH:
- m_line_smooth = true;
- rasterizer_options.line_smooth = true;
- update_rasterizer_options = true;
- break;
- case GL_NORMALIZE:
- m_normalize = true;
- rasterizer_options.normalization_enabled = true;
- update_rasterizer_options = true;
- break;
- case GL_POINT_SMOOTH:
- m_point_smooth = true;
- rasterizer_options.point_smooth = true;
- update_rasterizer_options = true;
- break;
- case GL_POLYGON_OFFSET_FILL:
- m_depth_offset_enabled = true;
- rasterizer_options.depth_offset_enabled = true;
- update_rasterizer_options = true;
- break;
- case GL_SCISSOR_TEST:
- rasterizer_options.scissor_enabled = true;
- update_rasterizer_options = true;
- break;
- case GL_STENCIL_TEST:
- m_stencil_test_enabled = true;
- rasterizer_options.enable_stencil_test = true;
- update_rasterizer_options = true;
- break;
- case GL_TEXTURE_1D:
- m_active_texture_unit->set_texture_1d_enabled(true);
- m_sampler_config_is_dirty = true;
- m_texture_units_dirty = true;
- break;
- case GL_TEXTURE_2D:
- m_active_texture_unit->set_texture_2d_enabled(true);
- m_sampler_config_is_dirty = true;
- m_texture_units_dirty = true;
- break;
- case GL_TEXTURE_3D:
- m_active_texture_unit->set_texture_3d_enabled(true);
- m_sampler_config_is_dirty = true;
- m_texture_units_dirty = true;
- break;
- case GL_TEXTURE_CUBE_MAP:
- m_active_texture_unit->set_texture_cube_map_enabled(true);
- m_sampler_config_is_dirty = true;
- m_texture_units_dirty = true;
- break;
- case GL_TEXTURE_GEN_Q:
- case GL_TEXTURE_GEN_R:
- case GL_TEXTURE_GEN_S:
- case GL_TEXTURE_GEN_T:
- texture_coordinate_generation(m_active_texture_unit_index, capability).enabled = true;
- m_texture_units_dirty = true;
- break;
- default:
- dbgln_if(GL_DEBUG, "gl_enable({:#x}): unknown parameter", capability);
- RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
- }
- if (update_rasterizer_options)
- m_rasterizer->set_options(rasterizer_options);
- }
- void GLContext::gl_enable_client_state(GLenum cap)
- {
- RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
- switch (cap) {
- case GL_COLOR_ARRAY:
- m_client_side_color_array_enabled = true;
- break;
- case GL_NORMAL_ARRAY:
- m_client_side_normal_array_enabled = true;
- break;
- case GL_TEXTURE_COORD_ARRAY:
- m_client_side_texture_coord_array_enabled[m_client_active_texture] = true;
- break;
- case GL_VERTEX_ARRAY:
- m_client_side_vertex_array_enabled = true;
- break;
- default:
- RETURN_WITH_ERROR_IF(true, GL_INVALID_ENUM);
- }
- }
- void GLContext::gl_get_booleanv(GLenum pname, GLboolean* data)
- {
- RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
- auto optional_parameter = get_context_parameter(pname);
- RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
- auto parameter = optional_parameter.release_value();
- switch (parameter.type) {
- case GL_BOOL:
- *data = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
- break;
- case GL_DOUBLE:
- *data = (parameter.value.double_value == 0.0) ? GL_FALSE : GL_TRUE;
- break;
- case GL_INT:
- *data = (parameter.value.integer_value == 0) ? GL_FALSE : GL_TRUE;
- break;
- default:
- VERIFY_NOT_REACHED();
- }
- }
- void GLContext::gl_get_doublev(GLenum pname, GLdouble* params)
- {
- get_floating_point(pname, params);
- }
- template<typename T>
- void GLContext::get_floating_point(GLenum pname, T* params)
- {
- RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
- // Handle matrix retrieval first
- auto flatten_and_assign_matrix = [¶ms](FloatMatrix4x4 const& matrix) {
- auto elements = matrix.elements();
- for (size_t i = 0; i < 4; ++i) {
- for (size_t j = 0; j < 4; ++j) {
- // Return transposed matrix since OpenGL defines them as column-major
- params[i * 4 + j] = static_cast<T>(elements[j][i]);
- }
- }
- };
- switch (pname) {
- case GL_MODELVIEW_MATRIX:
- flatten_and_assign_matrix(model_view_matrix());
- return;
- case GL_PROJECTION_MATRIX:
- flatten_and_assign_matrix(projection_matrix());
- return;
- }
- // Regular parameters
- auto optional_parameter = get_context_parameter(pname);
- RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
- auto parameter = optional_parameter.release_value();
- switch (parameter.type) {
- case GL_BOOL:
- *params = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
- break;
- case GL_DOUBLE:
- for (size_t i = 0; i < parameter.count; ++i)
- params[i] = parameter.value.double_list[i];
- break;
- case GL_INT:
- for (size_t i = 0; i < parameter.count; ++i)
- params[i] = parameter.value.integer_list[i];
- break;
- default:
- VERIFY_NOT_REACHED();
- }
- }
- void GLContext::gl_get_floatv(GLenum pname, GLfloat* params)
- {
- get_floating_point(pname, params);
- }
- void GLContext::gl_get_integerv(GLenum pname, GLint* data)
- {
- RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION);
- auto optional_parameter = get_context_parameter(pname);
- RETURN_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM);
- auto parameter = optional_parameter.release_value();
- switch (parameter.type) {
- case GL_BOOL:
- *data = parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
- break;
- case GL_DOUBLE: {
- double const int_range = static_cast<double>(NumericLimits<GLint>::max()) - NumericLimits<GLint>::min();
- for (size_t i = 0; i < parameter.count; ++i) {
- double const result_factor = (clamp(parameter.value.double_list[i], -1.0, 1.0) + 1.0) / 2.0;
- data[i] = static_cast<GLint>(NumericLimits<GLint>::min() + result_factor * int_range);
- }
- break;
- }
- case GL_INT:
- for (size_t i = 0; i < parameter.count; ++i)
- data[i] = parameter.value.integer_list[i];
- break;
- default:
- VERIFY_NOT_REACHED();
- }
- }
- GLboolean GLContext::gl_is_enabled(GLenum capability)
- {
- RETURN_VALUE_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION, 0);
- auto optional_parameter = get_context_parameter(capability);
- RETURN_VALUE_WITH_ERROR_IF(!optional_parameter.has_value(), GL_INVALID_ENUM, 0);
- auto parameter = optional_parameter.release_value();
- RETURN_VALUE_WITH_ERROR_IF(!parameter.is_capability, GL_INVALID_ENUM, 0);
- return parameter.value.boolean_value ? GL_TRUE : GL_FALSE;
- }
- GPU::PackingSpecification GLContext::get_packing_specification(PackingType packing_type)
- {
- // FIXME: add support for .least_significant_bit_first, .skip_images, .skip_pixels and .skip_rows
- auto const& pixel_parameters = (packing_type == PackingType::Pack) ? m_packing_parameters : m_unpacking_parameters;
- return {
- .depth_stride = static_cast<u32>(pixel_parameters.image_height),
- .row_stride = static_cast<u32>(pixel_parameters.row_length),
- .byte_alignment = pixel_parameters.pack_alignment,
- .component_bytes_order = pixel_parameters.swap_bytes ? GPU::ComponentBytesOrder::Reversed : GPU::ComponentBytesOrder::Normal,
- };
- }
- }
|