// Copyright (c) FIRST and other WPILib contributors. // Open Source Software; you can modify and/or share it under the terms of // the WPILib BSD license file in the root directory of this project. #include #include #include #include #include #include #include "wpigui.h" #include "wpigui_internal.h" using namespace wpi::gui; static bool gPlatformValid = false; namespace wpi { void gui::PlatformCreateContext() {} void gui::PlatformDestroyContext() {} void gui::PlatformGlfwInitHints() {} void gui::PlatformGlfwWindowHints() { // Decide GL versions #if __APPLE__ // GL 3.2 + GLSL 150 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ only glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac glfwWindowHint(GLFW_COCOA_GRAPHICS_SWITCHING, GLFW_TRUE); #else // GL 3.0 + GLSL 130 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); // glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // 3.2+ // glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // 3.0+ #endif // enable 4xMSAA glfwWindowHint(GLFW_SAMPLES, 4); } bool gui::PlatformInitRenderer() { glfwMakeContextCurrent(gContext->window); glfwSwapInterval(1); // Enable vsync // Initialize OpenGL loader if (gl3wInit() != 0) { std::fprintf(stderr, "Failed to initialize OpenGL loader!\n"); return false; } // Turn on multisampling glEnable(GL_MULTISAMPLE); // Setup Platform/Renderer bindings ImGui_ImplGlfw_InitForOpenGL(gContext->window, true); // Decide GLSL versions #if __APPLE__ const char* glsl_version = "#version 150"; #else const char* glsl_version = "#version 130"; #endif ImGui_ImplOpenGL3_Init(glsl_version); gPlatformValid = true; return true; } void gui::PlatformRenderFrame() { if (gContext->reloadFonts) { ImGui_ImplOpenGL3_DestroyFontsTexture(); ImGui_ImplOpenGL3_CreateFontsTexture(); gContext->reloadFonts = false; } ImGui_ImplOpenGL3_NewFrame(); CommonRenderFrame(); int display_w, display_h; glfwGetFramebufferSize(gContext->window, &display_w, &display_h); glViewport(0, 0, display_w, display_h); glClearColor(gContext->clearColor.x, gContext->clearColor.y, gContext->clearColor.z, gContext->clearColor.w); glClear(GL_COLOR_BUFFER_BIT); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); glfwSwapBuffers(gContext->window); } void gui::PlatformShutdown() { gPlatformValid = false; ImGui_ImplOpenGL3_Shutdown(); } void gui::PlatformFramebufferSizeChanged(int width, int height) {} static inline GLenum GLPixelFormat(PixelFormat format) { switch (format) { case kPixelRGBA: return GL_RGBA; case kPixelBGRA: return GL_BGRA; default: return GL_RGBA; } } ImTextureID gui::CreateTexture(PixelFormat format, int width, int height, const unsigned char* data) { if (!gPlatformValid) { return nullptr; } // Create a OpenGL texture identifier GLuint texture; glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); // Setup filtering parameters for display glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); // Upload pixels into texture glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GLPixelFormat(format), GL_UNSIGNED_BYTE, data); return reinterpret_cast(static_cast(texture)); } void gui::UpdateTexture(ImTextureID texture, PixelFormat format, int width, int height, const unsigned char* data) { GLuint glTexture = static_cast(reinterpret_cast(texture)); if (glTexture == 0) { return; } glBindTexture(GL_TEXTURE_2D, glTexture); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GLPixelFormat(format), GL_UNSIGNED_BYTE, data); } void gui::DeleteTexture(ImTextureID texture) { if (!gPlatformValid) { return; } GLuint glTexture = static_cast(reinterpret_cast(texture)); if (glTexture != 0) { glDeleteTextures(1, &glTexture); } } } // namespace wpi