Serenity Operating System
at master 557 lines 22 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 <LibGL/GLContext.h> 10 11namespace GL { 12 13template<typename T> 14void GLContext::get_light_param(GLenum light, GLenum pname, T* params) 15{ 16 auto const& light_state = m_light_states[light - GL_LIGHT0]; 17 switch (pname) { 18 case GL_AMBIENT: 19 params[0] = light_state.ambient_intensity.x(); 20 params[1] = light_state.ambient_intensity.y(); 21 params[2] = light_state.ambient_intensity.z(); 22 params[3] = light_state.ambient_intensity.w(); 23 break; 24 case GL_DIFFUSE: 25 params[0] = light_state.diffuse_intensity.x(); 26 params[1] = light_state.diffuse_intensity.y(); 27 params[2] = light_state.diffuse_intensity.z(); 28 params[3] = light_state.diffuse_intensity.w(); 29 break; 30 case GL_SPECULAR: 31 params[0] = light_state.specular_intensity.x(); 32 params[1] = light_state.specular_intensity.y(); 33 params[2] = light_state.specular_intensity.z(); 34 params[3] = light_state.specular_intensity.w(); 35 break; 36 case GL_SPOT_DIRECTION: 37 params[0] = light_state.spotlight_direction.x(); 38 params[1] = light_state.spotlight_direction.y(); 39 params[2] = light_state.spotlight_direction.z(); 40 break; 41 case GL_SPOT_EXPONENT: 42 *params = light_state.spotlight_exponent; 43 break; 44 case GL_SPOT_CUTOFF: 45 *params = light_state.spotlight_cutoff_angle; 46 break; 47 case GL_CONSTANT_ATTENUATION: 48 *params = light_state.constant_attenuation; 49 break; 50 case GL_LINEAR_ATTENUATION: 51 *params = light_state.linear_attenuation; 52 break; 53 case GL_QUADRATIC_ATTENUATION: 54 *params = light_state.quadratic_attenuation; 55 break; 56 } 57} 58 59template<typename T> 60void GLContext::get_material_param(Face face, GLenum pname, T* params) 61{ 62 auto const& material = m_material_states[face]; 63 switch (pname) { 64 case GL_AMBIENT: 65 params[0] = static_cast<T>(material.ambient.x()); 66 params[1] = static_cast<T>(material.ambient.y()); 67 params[2] = static_cast<T>(material.ambient.z()); 68 params[3] = static_cast<T>(material.ambient.w()); 69 break; 70 case GL_DIFFUSE: 71 params[0] = static_cast<T>(material.diffuse.x()); 72 params[1] = static_cast<T>(material.diffuse.y()); 73 params[2] = static_cast<T>(material.diffuse.z()); 74 params[3] = static_cast<T>(material.diffuse.w()); 75 break; 76 case GL_SPECULAR: 77 params[0] = static_cast<T>(material.specular.x()); 78 params[1] = static_cast<T>(material.specular.y()); 79 params[2] = static_cast<T>(material.specular.z()); 80 params[3] = static_cast<T>(material.specular.w()); 81 break; 82 case GL_EMISSION: 83 params[0] = static_cast<T>(material.emissive.x()); 84 params[1] = static_cast<T>(material.emissive.y()); 85 params[2] = static_cast<T>(material.emissive.z()); 86 params[3] = static_cast<T>(material.emissive.w()); 87 break; 88 case GL_SHININESS: 89 *params = material.shininess; 90 break; 91 } 92} 93 94void GLContext::gl_color_material(GLenum face, GLenum mode) 95{ 96 APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_color_material, face, mode); 97 RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); 98 99 RETURN_WITH_ERROR_IF(face != GL_FRONT 100 && face != GL_BACK 101 && face != GL_FRONT_AND_BACK, 102 GL_INVALID_ENUM); 103 RETURN_WITH_ERROR_IF(mode != GL_EMISSION 104 && mode != GL_AMBIENT 105 && mode != GL_DIFFUSE 106 && mode != GL_SPECULAR 107 && mode != GL_AMBIENT_AND_DIFFUSE, 108 GL_INVALID_ENUM); 109 110 m_color_material_face = face; 111 m_color_material_mode = mode; 112 113 m_light_state_is_dirty = true; 114} 115 116void GLContext::gl_get_light(GLenum light, GLenum pname, void* params, GLenum type) 117{ 118 APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_get_light, light, pname, params, type); 119 RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); 120 RETURN_WITH_ERROR_IF(light < GL_LIGHT0 || light > GL_LIGHT0 + m_device_info.num_lights, GL_INVALID_ENUM); 121 RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_SPOT_DIRECTION || pname == GL_SPOT_EXPONENT || pname == GL_SPOT_CUTOFF || pname == GL_CONSTANT_ATTENUATION || pname == GL_LINEAR_ATTENUATION || pname == GL_QUADRATIC_ATTENUATION), GL_INVALID_ENUM); 122 123 if (type == GL_FLOAT) 124 get_light_param<GLfloat>(light, pname, static_cast<GLfloat*>(params)); 125 else if (type == GL_INT) 126 get_light_param<GLint>(light, pname, static_cast<GLint*>(params)); 127 else 128 VERIFY_NOT_REACHED(); 129} 130 131void GLContext::gl_get_material(GLenum face, GLenum pname, void* params, GLenum type) 132{ 133 APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_get_material, face, pname, params, type); 134 RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); 135 RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_EMISSION), GL_INVALID_ENUM); 136 RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK), GL_INVALID_ENUM); 137 138 Face material_face = Front; 139 switch (face) { 140 case GL_FRONT: 141 material_face = Front; 142 break; 143 case GL_BACK: 144 material_face = Back; 145 break; 146 } 147 148 if (type == GL_FLOAT) 149 get_material_param<GLfloat>(material_face, pname, static_cast<GLfloat*>(params)); 150 else if (type == GL_INT) 151 get_material_param<GLint>(material_face, pname, static_cast<GLint*>(params)); 152 else 153 VERIFY_NOT_REACHED(); 154} 155 156void GLContext::gl_light_model(GLenum pname, GLfloat x, GLfloat y, GLfloat z, GLfloat w) 157{ 158 APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_light_model, pname, x, y, z, w); 159 160 RETURN_WITH_ERROR_IF(pname != GL_LIGHT_MODEL_AMBIENT 161 && pname != GL_LIGHT_MODEL_COLOR_CONTROL 162 && pname != GL_LIGHT_MODEL_LOCAL_VIEWER 163 && pname != GL_LIGHT_MODEL_TWO_SIDE, 164 GL_INVALID_ENUM); 165 166 auto lighting_params = m_rasterizer->light_model(); 167 168 switch (pname) { 169 case GL_LIGHT_MODEL_AMBIENT: 170 lighting_params.scene_ambient_color = { x, y, z, w }; 171 break; 172 case GL_LIGHT_MODEL_COLOR_CONTROL: { 173 auto color_control = static_cast<GLenum>(x); 174 RETURN_WITH_ERROR_IF(color_control != GL_SINGLE_COLOR && color_control != GL_SEPARATE_SPECULAR_COLOR, GL_INVALID_ENUM); 175 lighting_params.color_control = (color_control == GL_SINGLE_COLOR) ? GPU::ColorControl::SingleColor : GPU::ColorControl::SeparateSpecularColor; 176 break; 177 } 178 case GL_LIGHT_MODEL_LOCAL_VIEWER: 179 // 0 means the viewer is at infinity 180 // 1 means they're in local (eye) space 181 lighting_params.viewer_at_infinity = (x == 0.f); 182 break; 183 case GL_LIGHT_MODEL_TWO_SIDE: 184 lighting_params.two_sided_lighting = (x != 0.f); 185 break; 186 default: 187 VERIFY_NOT_REACHED(); 188 } 189 190 m_rasterizer->set_light_model_params(lighting_params); 191} 192 193void GLContext::gl_light_modelv(GLenum pname, void const* params, GLenum type) 194{ 195 VERIFY(type == GL_FLOAT || type == GL_INT); 196 197 auto parameters_to_vector = [&]<typename T>(T const* params) -> FloatVector4 { 198 return (pname == GL_LIGHT_MODEL_AMBIENT) 199 ? Vector4<T> { params[0], params[1], params[2], params[3] }.template to_type<float>() 200 : Vector4<T> { params[0], 0, 0, 0 }.template to_type<float>(); 201 }; 202 203 auto light_model_parameters = (type == GL_FLOAT) 204 ? parameters_to_vector(reinterpret_cast<GLfloat const*>(params)) 205 : parameters_to_vector(reinterpret_cast<GLint const*>(params)); 206 207 // Normalize integers to -1..1 208 if (pname == GL_LIGHT_MODEL_AMBIENT && type == GL_INT) 209 light_model_parameters = (light_model_parameters + 2147483648.f) / 2147483647.5f - 1.f; 210 211 gl_light_model(pname, light_model_parameters[0], light_model_parameters[1], light_model_parameters[2], light_model_parameters[3]); 212} 213 214void GLContext::gl_lightf(GLenum light, GLenum pname, GLfloat param) 215{ 216 APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_lightf, light, pname, param); 217 218 RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); 219 RETURN_WITH_ERROR_IF(light < GL_LIGHT0 || light >= (GL_LIGHT0 + m_device_info.num_lights), GL_INVALID_ENUM); 220 RETURN_WITH_ERROR_IF(!(pname == GL_CONSTANT_ATTENUATION || pname == GL_LINEAR_ATTENUATION || pname == GL_QUADRATIC_ATTENUATION || pname != GL_SPOT_EXPONENT || pname != GL_SPOT_CUTOFF), GL_INVALID_ENUM); 221 RETURN_WITH_ERROR_IF(param < 0.f, GL_INVALID_VALUE); 222 223 auto& light_state = m_light_states.at(light - GL_LIGHT0); 224 225 switch (pname) { 226 case GL_CONSTANT_ATTENUATION: 227 light_state.constant_attenuation = param; 228 break; 229 case GL_LINEAR_ATTENUATION: 230 light_state.linear_attenuation = param; 231 break; 232 case GL_QUADRATIC_ATTENUATION: 233 light_state.quadratic_attenuation = param; 234 break; 235 case GL_SPOT_EXPONENT: 236 RETURN_WITH_ERROR_IF(param > 128.f, GL_INVALID_VALUE); 237 light_state.spotlight_exponent = param; 238 break; 239 case GL_SPOT_CUTOFF: 240 RETURN_WITH_ERROR_IF(param > 90.f && param != 180.f, GL_INVALID_VALUE); 241 light_state.spotlight_cutoff_angle = param; 242 break; 243 default: 244 VERIFY_NOT_REACHED(); 245 } 246 247 m_light_state_is_dirty = true; 248} 249 250void GLContext::gl_lightfv(GLenum light, GLenum pname, GLfloat const* params) 251{ 252 APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_lightfv, light, pname, params); 253 RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); 254 RETURN_WITH_ERROR_IF(light < GL_LIGHT0 || light >= (GL_LIGHT0 + m_device_info.num_lights), GL_INVALID_ENUM); 255 RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_POSITION || pname == GL_CONSTANT_ATTENUATION || pname == GL_LINEAR_ATTENUATION || pname == GL_QUADRATIC_ATTENUATION || pname == GL_SPOT_CUTOFF || pname == GL_SPOT_EXPONENT || pname == GL_SPOT_DIRECTION), GL_INVALID_ENUM); 256 257 auto& light_state = m_light_states.at(light - GL_LIGHT0); 258 259 switch (pname) { 260 case GL_AMBIENT: 261 light_state.ambient_intensity = { params[0], params[1], params[2], params[3] }; 262 break; 263 case GL_DIFFUSE: 264 light_state.diffuse_intensity = { params[0], params[1], params[2], params[3] }; 265 break; 266 case GL_SPECULAR: 267 light_state.specular_intensity = { params[0], params[1], params[2], params[3] }; 268 break; 269 case GL_POSITION: 270 light_state.position = { params[0], params[1], params[2], params[3] }; 271 light_state.position = model_view_matrix() * light_state.position; 272 break; 273 case GL_CONSTANT_ATTENUATION: 274 RETURN_WITH_ERROR_IF(params[0] < 0.f, GL_INVALID_VALUE); 275 light_state.constant_attenuation = params[0]; 276 break; 277 case GL_LINEAR_ATTENUATION: 278 RETURN_WITH_ERROR_IF(params[0] < 0.f, GL_INVALID_VALUE); 279 light_state.linear_attenuation = params[0]; 280 break; 281 case GL_QUADRATIC_ATTENUATION: 282 RETURN_WITH_ERROR_IF(params[0] < 0.f, GL_INVALID_VALUE); 283 light_state.quadratic_attenuation = params[0]; 284 break; 285 case GL_SPOT_EXPONENT: { 286 auto exponent = params[0]; 287 RETURN_WITH_ERROR_IF(exponent < 0.f || exponent > 128.f, GL_INVALID_VALUE); 288 light_state.spotlight_exponent = exponent; 289 break; 290 } 291 case GL_SPOT_CUTOFF: { 292 auto cutoff = params[0]; 293 RETURN_WITH_ERROR_IF((cutoff < 0.f || cutoff > 90.f) && cutoff != 180.f, GL_INVALID_VALUE); 294 light_state.spotlight_cutoff_angle = cutoff; 295 break; 296 } 297 case GL_SPOT_DIRECTION: { 298 FloatVector4 direction_vector = { params[0], params[1], params[2], 0.f }; 299 direction_vector = model_view_matrix() * direction_vector; 300 light_state.spotlight_direction = direction_vector.xyz(); 301 break; 302 } 303 default: 304 VERIFY_NOT_REACHED(); 305 } 306 307 m_light_state_is_dirty = true; 308} 309 310void GLContext::gl_lightiv(GLenum light, GLenum pname, GLint const* params) 311{ 312 APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_lightiv, light, pname, params); 313 RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); 314 RETURN_WITH_ERROR_IF(light < GL_LIGHT0 || light >= (GL_LIGHT0 + m_device_info.num_lights), GL_INVALID_ENUM); 315 RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_POSITION || pname == GL_CONSTANT_ATTENUATION || pname == GL_LINEAR_ATTENUATION || pname == GL_QUADRATIC_ATTENUATION || pname == GL_SPOT_CUTOFF || pname == GL_SPOT_EXPONENT || pname == GL_SPOT_DIRECTION), GL_INVALID_ENUM); 316 317 auto& light_state = m_light_states[light - GL_LIGHT0]; 318 319 auto const to_float_vector = [](GLfloat x, GLfloat y, GLfloat z, GLfloat w) { 320 return FloatVector4(x, y, z, w); 321 }; 322 323 switch (pname) { 324 case GL_AMBIENT: 325 light_state.ambient_intensity = to_float_vector(params[0], params[1], params[2], params[3]); 326 break; 327 case GL_DIFFUSE: 328 light_state.diffuse_intensity = to_float_vector(params[0], params[1], params[2], params[3]); 329 break; 330 case GL_SPECULAR: 331 light_state.specular_intensity = to_float_vector(params[0], params[1], params[2], params[3]); 332 break; 333 case GL_POSITION: 334 light_state.position = to_float_vector(params[0], params[1], params[2], params[3]); 335 light_state.position = model_view_matrix() * light_state.position; 336 break; 337 case GL_CONSTANT_ATTENUATION: 338 RETURN_WITH_ERROR_IF(params[0] < 0, GL_INVALID_VALUE); 339 light_state.constant_attenuation = static_cast<float>(params[0]); 340 break; 341 case GL_LINEAR_ATTENUATION: 342 RETURN_WITH_ERROR_IF(params[0] < 0, GL_INVALID_VALUE); 343 light_state.linear_attenuation = static_cast<float>(params[0]); 344 break; 345 case GL_QUADRATIC_ATTENUATION: 346 RETURN_WITH_ERROR_IF(params[0] < 0, GL_INVALID_VALUE); 347 light_state.quadratic_attenuation = static_cast<float>(params[0]); 348 break; 349 case GL_SPOT_EXPONENT: { 350 auto exponent = static_cast<float>(params[0]); 351 RETURN_WITH_ERROR_IF(exponent < 0.f || exponent > 128.f, GL_INVALID_VALUE); 352 light_state.spotlight_exponent = exponent; 353 break; 354 } 355 case GL_SPOT_CUTOFF: { 356 auto cutoff = static_cast<float>(params[0]); 357 RETURN_WITH_ERROR_IF((cutoff < 0.f || cutoff > 90.f) && cutoff != 180.f, GL_INVALID_VALUE); 358 light_state.spotlight_cutoff_angle = cutoff; 359 break; 360 } 361 case GL_SPOT_DIRECTION: { 362 auto direction_vector = to_float_vector(params[0], params[1], params[2], 0.0f); 363 direction_vector = model_view_matrix() * direction_vector; 364 light_state.spotlight_direction = direction_vector.xyz(); 365 break; 366 } 367 default: 368 VERIFY_NOT_REACHED(); 369 } 370 371 m_light_state_is_dirty = true; 372} 373 374void GLContext::gl_materialf(GLenum face, GLenum pname, GLfloat param) 375{ 376 APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_materialf, face, pname, param); 377 RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM); 378 RETURN_WITH_ERROR_IF(pname != GL_SHININESS, GL_INVALID_ENUM); 379 RETURN_WITH_ERROR_IF(param > 128.0f, GL_INVALID_VALUE); 380 381 switch (face) { 382 case GL_FRONT: 383 m_material_states[Face::Front].shininess = param; 384 break; 385 case GL_BACK: 386 m_material_states[Face::Back].shininess = param; 387 break; 388 case GL_FRONT_AND_BACK: 389 m_material_states[Face::Front].shininess = param; 390 m_material_states[Face::Back].shininess = param; 391 break; 392 default: 393 VERIFY_NOT_REACHED(); 394 } 395 396 m_light_state_is_dirty = true; 397} 398 399void GLContext::gl_materialfv(GLenum face, GLenum pname, GLfloat const* params) 400{ 401 APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_materialfv, face, pname, params); 402 RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM); 403 RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_EMISSION || pname == GL_SHININESS || pname == GL_AMBIENT_AND_DIFFUSE), GL_INVALID_ENUM); 404 RETURN_WITH_ERROR_IF((pname == GL_SHININESS && *params > 128.0f), GL_INVALID_VALUE); 405 406 auto update_material = [](GPU::Material& material, GLenum pname, GLfloat const* params) { 407 switch (pname) { 408 case GL_AMBIENT: 409 material.ambient = { params[0], params[1], params[2], params[3] }; 410 break; 411 case GL_DIFFUSE: 412 material.diffuse = { params[0], params[1], params[2], params[3] }; 413 break; 414 case GL_SPECULAR: 415 material.specular = { params[0], params[1], params[2], params[3] }; 416 break; 417 case GL_EMISSION: 418 material.emissive = { params[0], params[1], params[2], params[3] }; 419 break; 420 case GL_SHININESS: 421 material.shininess = params[0]; 422 break; 423 case GL_AMBIENT_AND_DIFFUSE: 424 material.ambient = { params[0], params[1], params[2], params[3] }; 425 material.diffuse = { params[0], params[1], params[2], params[3] }; 426 break; 427 } 428 }; 429 430 switch (face) { 431 case GL_FRONT: 432 update_material(m_material_states[Face::Front], pname, params); 433 break; 434 case GL_BACK: 435 update_material(m_material_states[Face::Back], pname, params); 436 break; 437 case GL_FRONT_AND_BACK: 438 update_material(m_material_states[Face::Front], pname, params); 439 update_material(m_material_states[Face::Back], pname, params); 440 break; 441 } 442 443 m_light_state_is_dirty = true; 444} 445 446void GLContext::gl_materialiv(GLenum face, GLenum pname, GLint const* params) 447{ 448 APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_materialiv, face, pname, params); 449 RETURN_WITH_ERROR_IF(!(face == GL_FRONT || face == GL_BACK || face == GL_FRONT_AND_BACK), GL_INVALID_ENUM); 450 RETURN_WITH_ERROR_IF(!(pname == GL_AMBIENT || pname == GL_DIFFUSE || pname == GL_SPECULAR || pname == GL_EMISSION || pname == GL_SHININESS || pname == GL_AMBIENT_AND_DIFFUSE), GL_INVALID_ENUM); 451 RETURN_WITH_ERROR_IF((pname == GL_SHININESS && *params > 128), GL_INVALID_VALUE); 452 453 auto update_material = [](GPU::Material& material, GLenum pname, GLint const* params) { 454 switch (pname) { 455 case GL_AMBIENT: 456 material.ambient = { static_cast<float>(params[0]), static_cast<float>(params[1]), static_cast<float>(params[2]), static_cast<float>(params[3]) }; 457 break; 458 case GL_DIFFUSE: 459 material.diffuse = { static_cast<float>(params[0]), static_cast<float>(params[1]), static_cast<float>(params[2]), static_cast<float>(params[3]) }; 460 break; 461 case GL_SPECULAR: 462 material.specular = { static_cast<float>(params[0]), static_cast<float>(params[1]), static_cast<float>(params[2]), static_cast<float>(params[3]) }; 463 break; 464 case GL_EMISSION: 465 material.emissive = { static_cast<float>(params[0]), static_cast<float>(params[1]), static_cast<float>(params[2]), static_cast<float>(params[3]) }; 466 break; 467 case GL_SHININESS: 468 material.shininess = static_cast<float>(params[0]); 469 break; 470 case GL_AMBIENT_AND_DIFFUSE: 471 material.ambient = { static_cast<float>(params[0]), static_cast<float>(params[1]), static_cast<float>(params[2]), static_cast<float>(params[3]) }; 472 material.diffuse = { static_cast<float>(params[0]), static_cast<float>(params[1]), static_cast<float>(params[2]), static_cast<float>(params[3]) }; 473 break; 474 } 475 }; 476 477 switch (face) { 478 case GL_FRONT: 479 update_material(m_material_states[Face::Front], pname, params); 480 break; 481 case GL_BACK: 482 update_material(m_material_states[Face::Back], pname, params); 483 break; 484 case GL_FRONT_AND_BACK: 485 update_material(m_material_states[Face::Front], pname, params); 486 update_material(m_material_states[Face::Back], pname, params); 487 break; 488 } 489 490 m_light_state_is_dirty = true; 491} 492 493void GLContext::gl_shade_model(GLenum mode) 494{ 495 APPEND_TO_CALL_LIST_AND_RETURN_IF_NEEDED(gl_shade_model, mode); 496 497 RETURN_WITH_ERROR_IF(m_in_draw_state, GL_INVALID_OPERATION); 498 RETURN_WITH_ERROR_IF(mode != GL_FLAT && mode != GL_SMOOTH, GL_INVALID_ENUM); 499 500 auto options = m_rasterizer->options(); 501 options.shade_smooth = (mode == GL_SMOOTH); 502 m_rasterizer->set_options(options); 503} 504 505void GLContext::sync_light_state() 506{ 507 if (!m_light_state_is_dirty) 508 return; 509 510 m_light_state_is_dirty = false; 511 512 auto options = m_rasterizer->options(); 513 options.color_material_enabled = m_color_material_enabled; 514 switch (m_color_material_face) { 515 case GL_BACK: 516 options.color_material_face = GPU::ColorMaterialFace::Back; 517 break; 518 case GL_FRONT: 519 options.color_material_face = GPU::ColorMaterialFace::Front; 520 break; 521 case GL_FRONT_AND_BACK: 522 options.color_material_face = GPU::ColorMaterialFace::FrontAndBack; 523 break; 524 default: 525 VERIFY_NOT_REACHED(); 526 } 527 switch (m_color_material_mode) { 528 case GL_AMBIENT: 529 options.color_material_mode = GPU::ColorMaterialMode::Ambient; 530 break; 531 case GL_AMBIENT_AND_DIFFUSE: 532 options.color_material_mode = GPU::ColorMaterialMode::AmbientAndDiffuse; 533 break; 534 case GL_DIFFUSE: 535 options.color_material_mode = GPU::ColorMaterialMode::Diffuse; 536 break; 537 case GL_EMISSION: 538 options.color_material_mode = GPU::ColorMaterialMode::Emissive; 539 break; 540 case GL_SPECULAR: 541 options.color_material_mode = GPU::ColorMaterialMode::Specular; 542 break; 543 default: 544 VERIFY_NOT_REACHED(); 545 } 546 m_rasterizer->set_options(options); 547 548 for (auto light_id = 0u; light_id < m_device_info.num_lights; light_id++) { 549 auto const& current_light_state = m_light_states.at(light_id); 550 m_rasterizer->set_light_state(light_id, current_light_state); 551 } 552 553 m_rasterizer->set_material_state(GPU::Face::Front, m_material_states[Face::Front]); 554 m_rasterizer->set_material_state(GPU::Face::Back, m_material_states[Face::Back]); 555} 556 557}