* Check for the needed OpenGL functionality and allocate all resources. * @param screen_res Current display resolution. * @return Error string or std::nullopt if successful. */
| 528 | * @return Error string or std::nullopt if successful. |
| 529 | */ |
| 530 | std::optional<std::string_view> OpenGLBackend::Init(const Dimension &screen_res) |
| 531 | { |
| 532 | if (!BindBasicInfoProcs()) return "OpenGL not supported"; |
| 533 | |
| 534 | /* Always query the supported OpenGL version as the current context might have changed. */ |
| 535 | auto ver = GlGetString(GL_VERSION); |
| 536 | auto vend = GlGetString(GL_VENDOR); |
| 537 | auto renderer = GlGetString(GL_RENDERER); |
| 538 | |
| 539 | if (!ver.has_value() || !vend.has_value() || !renderer.has_value()) return "OpenGL not supported"; |
| 540 | |
| 541 | Debug(driver, 1, "OpenGL driver: {} - {} ({})", *vend, *renderer, *ver); |
| 542 | |
| 543 | #ifndef GL_ALLOW_SOFTWARE_RENDERER |
| 544 | /* Don't use MESA software rendering backends as they are slower than |
| 545 | * just using a non-OpenGL video driver. */ |
| 546 | if (renderer->starts_with("llvmpipe") || renderer->starts_with("softpipe")) return "Software renderer detected, not using OpenGL"; |
| 547 | #endif |
| 548 | |
| 549 | std::tie(_gl_major_ver, _gl_minor_ver) = DecodeVersion(*ver); |
| 550 | |
| 551 | #ifdef _WIN32 |
| 552 | /* Old drivers on Windows (especially if made by Intel) seem to be |
| 553 | * unstable, so cull the oldest stuff here. */ |
| 554 | if (!IsOpenGLVersionAtLeast(3, 2)) return "Need at least OpenGL version 3.2 on Windows"; |
| 555 | #endif |
| 556 | |
| 557 | if (!BindBasicOpenGLProcs()) return "Failed to bind basic OpenGL functions."; |
| 558 | |
| 559 | SetupDebugOutput(); |
| 560 | |
| 561 | /* OpenGL 1.3 is the absolute minimum. */ |
| 562 | if (!IsOpenGLVersionAtLeast(1, 3)) return "OpenGL version >= 1.3 required"; |
| 563 | /* Check for non-power-of-two texture support. */ |
| 564 | if (!IsOpenGLVersionAtLeast(2, 0) && !IsOpenGLExtensionSupported("GL_ARB_texture_non_power_of_two")) return "Non-power-of-two textures not supported"; |
| 565 | /* Check for single element texture formats. */ |
| 566 | if (!IsOpenGLVersionAtLeast(3, 0) && !IsOpenGLExtensionSupported("GL_ARB_texture_rg")) return "Single element texture formats not supported"; |
| 567 | if (!BindTextureExtensions()) return "Failed to bind texture extension functions"; |
| 568 | /* Check for vertex buffer objects. */ |
| 569 | if (!IsOpenGLVersionAtLeast(1, 5) && !IsOpenGLExtensionSupported("ARB_vertex_buffer_object")) return "Vertex buffer objects not supported"; |
| 570 | if (!BindVBOExtension()) return "Failed to bind VBO extension functions"; |
| 571 | /* Check for pixel buffer objects. */ |
| 572 | if (!IsOpenGLVersionAtLeast(2, 1) && !IsOpenGLExtensionSupported("GL_ARB_pixel_buffer_object")) return "Pixel buffer objects not supported"; |
| 573 | /* Check for vertex array objects. */ |
| 574 | if (!IsOpenGLVersionAtLeast(3, 0) && (!IsOpenGLExtensionSupported("GL_ARB_vertex_array_object") || !IsOpenGLExtensionSupported("GL_APPLE_vertex_array_object"))) return "Vertex array objects not supported"; |
| 575 | if (!BindVBAExtension()) return "Failed to bind VBA extension functions"; |
| 576 | /* Check for shader objects. */ |
| 577 | if (!IsOpenGLVersionAtLeast(2, 0) && (!IsOpenGLExtensionSupported("GL_ARB_shader_objects") || !IsOpenGLExtensionSupported("GL_ARB_fragment_shader") || !IsOpenGLExtensionSupported("GL_ARB_vertex_shader"))) return "No shader support"; |
| 578 | if (!BindShaderExtensions()) return "Failed to bind shader extension functions"; |
| 579 | if (IsOpenGLVersionAtLeast(3, 2) && _glBindFragDataLocation == nullptr) return "OpenGL claims to support version 3.2 but doesn't have glBindFragDataLocation"; |
| 580 | |
| 581 | this->persistent_mapping_supported = IsOpenGLVersionAtLeast(3, 0) && (IsOpenGLVersionAtLeast(4, 4) || IsOpenGLExtensionSupported("GL_ARB_buffer_storage")); |
| 582 | #ifndef NO_GL_BUFFER_SYNC |
| 583 | this->persistent_mapping_supported = this->persistent_mapping_supported && (IsOpenGLVersionAtLeast(3, 2) || IsOpenGLExtensionSupported("GL_ARB_sync")); |
| 584 | #endif |
| 585 | |
| 586 | if (this->persistent_mapping_supported && !BindPersistentBufferExtensions()) { |
| 587 | Debug(driver, 1, "OpenGL claims to support persistent buffer mapping but doesn't export all functions, not using persistent mapping."); |
no test coverage detected