Path: blob/21.2-virgl/src/intel/tools/imgui/imgui_impl_opengl3.cpp
4547 views
// ImGui Renderer for: OpenGL3 (modern OpenGL with shaders / programmatic pipeline)1// This needs to be used along with a Platform Binding (e.g. GLFW, SDL, Win32, custom..)2// (Note: We are using GL3W as a helper library to access OpenGL functions since there is no standard header to access modern OpenGL functions easily. Alternatives are GLEW, Glad, etc..)34// Implemented features:5// [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID in imgui.cpp.67// You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this.8// If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp.9// https://github.com/ocornut/imgui1011// CHANGELOG12// (minor and older changes stripped away, please see git history for details)13// 2018-07-10: OpenGL: Support for more GLSL versions (based on the GLSL version string). Added error output when shaders fail to compile/link.14// 2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples.15// 2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.16// 2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state.17// 2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a NULL pointer.18// 2018-03-06: OpenGL: Added const char* glsl_version parameter to ImGui_ImplOpenGL3_Init() so user can override the GLSL version e.g. "#version 150".19// 2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context.20// 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself.21// 2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150.22// 2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode.23// 2017-05-01: OpenGL: Fixed save and restore of current blend func state.24// 2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE.25// 2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.26// 2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752)2728//----------------------------------------29// OpenGL GLSL GLSL30// version version string31//----------------------------------------32// 2.0 110 "#version 110"33// 2.1 12034// 3.0 13035// 3.1 14036// 3.2 150 "#version 150"37// 3.3 33038// 4.0 40039// 4.1 41040// 4.2 42041// 4.3 43042// ES 2.0 100 "#version 100"43// ES 3.0 300 "#version 300 es"44//----------------------------------------4546#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)47#define _CRT_SECURE_NO_WARNINGS48#endif4950#include "imgui/imgui.h"51#include "imgui_impl_opengl3.h"52#include <stdio.h>53#if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier54#include <stddef.h> // intptr_t55#else56#include <stdint.h> // intptr_t57#endif5859#include <epoxy/gl.h>60//#include "gl3w.h" // This example is using gl3w to access OpenGL functions. You may use another OpenGL loader/header such as: glew, glext, glad, glLoadGen, etc.61//#include <glew.h>62//#include <glext.h>63//#include <glad/glad.h>6465// OpenGL Data66static char g_GlslVersionString[32] = "";67static GLuint g_FontTexture = 0;68static GLuint g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0;69static int g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0;70static int g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0;71static unsigned int g_VboHandle = 0, g_ElementsHandle = 0;7273// Functions74bool ImGui_ImplOpenGL3_Init(const char* glsl_version)75{76// Store GLSL version string so we can refer to it later in case we recreate shaders. Note: GLSL version is NOT the same as GL version. Leave this to NULL if unsure.77if (glsl_version == NULL)78glsl_version = "#version 130";79IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(g_GlslVersionString));80strcpy(g_GlslVersionString, glsl_version);81strcat(g_GlslVersionString, "\n");82return true;83}8485void ImGui_ImplOpenGL3_Shutdown()86{87ImGui_ImplOpenGL3_DestroyDeviceObjects();88}8990void ImGui_ImplOpenGL3_NewFrame()91{92if (!g_FontTexture)93ImGui_ImplOpenGL3_CreateDeviceObjects();94}9596// OpenGL3 Render function.97// (this used to be set in io.RenderDrawListsFn and called by ImGui::Render(), but you can now call this directly from your main loop)98// Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly, in order to be able to run within any OpenGL engine that doesn't do so.99void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)100{101// Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)102ImGuiIO& io = ImGui::GetIO();103int fb_width = (int)(draw_data->DisplaySize.x * io.DisplayFramebufferScale.x);104int fb_height = (int)(draw_data->DisplaySize.y * io.DisplayFramebufferScale.y);105if (fb_width <= 0 || fb_height <= 0)106return;107draw_data->ScaleClipRects(io.DisplayFramebufferScale);108109// Backup GL state110GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);111glActiveTexture(GL_TEXTURE0);112GLint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);113GLint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);114GLint last_sampler; glGetIntegerv(GL_SAMPLER_BINDING, &last_sampler);115GLint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);116GLint last_vertex_array; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);117GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);118GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);119GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);120GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb);121GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb);122GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha);123GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha);124GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb);125GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha);126GLboolean last_enable_blend = glIsEnabled(GL_BLEND);127GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);128GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);129GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);130131// Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill132glEnable(GL_BLEND);133glBlendEquation(GL_FUNC_ADD);134glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);135glDisable(GL_CULL_FACE);136glDisable(GL_DEPTH_TEST);137glEnable(GL_SCISSOR_TEST);138glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);139140// Setup viewport, orthographic projection matrix141// Our visible imgui space lies from draw_data->DisplayPps (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayMin is typically (0,0) for single viewport apps.142glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height);143float L = draw_data->DisplayPos.x;144float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;145float T = draw_data->DisplayPos.y;146float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;147const float ortho_projection[4][4] =148{149{ 2.0f/(R-L), 0.0f, 0.0f, 0.0f },150{ 0.0f, 2.0f/(T-B), 0.0f, 0.0f },151{ 0.0f, 0.0f, -1.0f, 0.0f },152{ (R+L)/(L-R), (T+B)/(B-T), 0.0f, 1.0f },153};154glUseProgram(g_ShaderHandle);155glUniform1i(g_AttribLocationTex, 0);156glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);157if (glBindSampler) glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.158159// Recreate the VAO every time160// (This is to easily allow multiple GL contexts. VAO are not shared among GL contexts, and we don't track creation/deletion of windows so we don't have an obvious key to use to cache them.)161GLuint vao_handle = 0;162glGenVertexArrays(1, &vao_handle);163glBindVertexArray(vao_handle);164glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);165glEnableVertexAttribArray(g_AttribLocationPosition);166glEnableVertexAttribArray(g_AttribLocationUV);167glEnableVertexAttribArray(g_AttribLocationColor);168glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos));169glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv));170glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col));171172// Draw173ImVec2 pos = draw_data->DisplayPos;174for (int n = 0; n < draw_data->CmdListsCount; n++)175{176const ImDrawList* cmd_list = draw_data->CmdLists[n];177const ImDrawIdx* idx_buffer_offset = 0;178179glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle);180glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)cmd_list->VtxBuffer.Size * sizeof(ImDrawVert), (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW);181182glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, g_ElementsHandle);183glBufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizeiptr)cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx), (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW);184185for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)186{187const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];188if (pcmd->UserCallback)189{190// User callback (registered via ImDrawList::AddCallback)191pcmd->UserCallback(cmd_list, pcmd);192}193else194{195ImVec4 clip_rect = ImVec4(pcmd->ClipRect.x - pos.x, pcmd->ClipRect.y - pos.y, pcmd->ClipRect.z - pos.x, pcmd->ClipRect.w - pos.y);196if (clip_rect.x < fb_width && clip_rect.y < fb_height && clip_rect.z >= 0.0f && clip_rect.w >= 0.0f)197{198// Apply scissor/clipping rectangle199glScissor((int)clip_rect.x, (int)(fb_height - clip_rect.w), (int)(clip_rect.z - clip_rect.x), (int)(clip_rect.w - clip_rect.y));200201// Bind texture, Draw202glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId);203glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset);204}205}206idx_buffer_offset += pcmd->ElemCount;207}208}209glDeleteVertexArrays(1, &vao_handle);210211// Restore modified GL state212glUseProgram(last_program);213glBindTexture(GL_TEXTURE_2D, last_texture);214if (glBindSampler) glBindSampler(0, last_sampler);215glActiveTexture(last_active_texture);216glBindVertexArray(last_vertex_array);217glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);218glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);219glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);220if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);221if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);222if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);223if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);224glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);225glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);226glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);227}228229bool ImGui_ImplOpenGL3_CreateFontsTexture()230{231// Build texture atlas232ImGuiIO& io = ImGui::GetIO();233unsigned char* pixels;234int width, height;235io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); // Load as RGBA 32-bits (75% of the memory is wasted, but default font is so small) because it is more likely to be compatible with user's existing shaders. If your ImTextureId represent a higher-level concept than just a GL texture id, consider calling GetTexDataAsAlpha8() instead to save on GPU memory.236237// Upload texture to graphics system238GLint last_texture;239glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);240glGenTextures(1, &g_FontTexture);241glBindTexture(GL_TEXTURE_2D, g_FontTexture);242glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);243glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);244glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);245glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);246247// Store our identifier248io.Fonts->TexID = (void *)(intptr_t)g_FontTexture;249250// Restore state251glBindTexture(GL_TEXTURE_2D, last_texture);252253return true;254}255256void ImGui_ImplOpenGL3_DestroyFontsTexture()257{258if (g_FontTexture)259{260ImGuiIO& io = ImGui::GetIO();261glDeleteTextures(1, &g_FontTexture);262io.Fonts->TexID = 0;263g_FontTexture = 0;264}265}266267// If you get an error please report on github. You may try different GL context version or GLSL version.268static bool CheckShader(GLuint handle, const char* desc)269{270GLint status = 0, log_length = 0;271glGetShaderiv(handle, GL_COMPILE_STATUS, &status);272glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length);273if (status == GL_FALSE)274fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s!\n", desc);275if (log_length > 0)276{277ImVector<char> buf;278buf.resize((int)(log_length + 1));279glGetShaderInfoLog(handle, log_length, NULL, (GLchar*)buf.begin());280fprintf(stderr, "%s\n", buf.begin());281}282return status == GL_TRUE;283}284285// If you get an error please report on github. You may try different GL context version or GLSL version.286static bool CheckProgram(GLuint handle, const char* desc)287{288GLint status = 0, log_length = 0;289glGetProgramiv(handle, GL_LINK_STATUS, &status);290glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length);291if (status == GL_FALSE)292fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s!\n", desc);293if (log_length > 0)294{295ImVector<char> buf;296buf.resize((int)(log_length + 1));297glGetProgramInfoLog(handle, log_length, NULL, (GLchar*)buf.begin());298fprintf(stderr, "%s\n", buf.begin());299}300return status == GL_TRUE;301}302303bool ImGui_ImplOpenGL3_CreateDeviceObjects()304{305// Backup GL state306GLint last_texture, last_array_buffer, last_vertex_array;307glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);308glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);309glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);310311// Parse GLSL version string312int glsl_version = 130;313sscanf(g_GlslVersionString, "#version %d", &glsl_version);314315const GLchar* vertex_shader_glsl_120 =316"uniform mat4 ProjMtx;\n"317"attribute vec2 Position;\n"318"attribute vec2 UV;\n"319"attribute vec4 Color;\n"320"varying vec2 Frag_UV;\n"321"varying vec4 Frag_Color;\n"322"void main()\n"323"{\n"324" Frag_UV = UV;\n"325" Frag_Color = Color;\n"326" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"327"}\n";328329const GLchar* vertex_shader_glsl_130 =330"uniform mat4 ProjMtx;\n"331"in vec2 Position;\n"332"in vec2 UV;\n"333"in vec4 Color;\n"334"out vec2 Frag_UV;\n"335"out vec4 Frag_Color;\n"336"void main()\n"337"{\n"338" Frag_UV = UV;\n"339" Frag_Color = Color;\n"340" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"341"}\n";342343const GLchar* fragment_shader_glsl_120 =344"#ifdef GL_ES\n"345" precision mediump float;\n"346"#endif\n"347"uniform sampler2D Texture;\n"348"varying vec2 Frag_UV;\n"349"varying vec4 Frag_Color;\n"350"void main()\n"351"{\n"352" gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n"353"}\n";354355const GLchar* fragment_shader_glsl_130 =356"uniform sampler2D Texture;\n"357"in vec2 Frag_UV;\n"358"in vec4 Frag_Color;\n"359"out vec4 Out_Color;\n"360"void main()\n"361"{\n"362" Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"363"}\n";364365// Select shaders matching our GLSL versions366const GLchar* vertex_shader = NULL;367const GLchar* fragment_shader = NULL;368if (glsl_version < 130)369{370vertex_shader = vertex_shader_glsl_120;371fragment_shader = fragment_shader_glsl_120;372}373else374{375vertex_shader = vertex_shader_glsl_130;376fragment_shader = fragment_shader_glsl_130;377}378379// Create shaders380const GLchar* vertex_shader_with_version[2] = { g_GlslVersionString, vertex_shader };381g_VertHandle = glCreateShader(GL_VERTEX_SHADER);382glShaderSource(g_VertHandle, 2, vertex_shader_with_version, NULL);383glCompileShader(g_VertHandle);384CheckShader(g_VertHandle, "vertex shader");385386const GLchar* fragment_shader_with_version[2] = { g_GlslVersionString, fragment_shader };387g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER);388glShaderSource(g_FragHandle, 2, fragment_shader_with_version, NULL);389glCompileShader(g_FragHandle);390CheckShader(g_FragHandle, "fragment shader");391392g_ShaderHandle = glCreateProgram();393glAttachShader(g_ShaderHandle, g_VertHandle);394glAttachShader(g_ShaderHandle, g_FragHandle);395glLinkProgram(g_ShaderHandle);396CheckProgram(g_ShaderHandle, "shader program");397398g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture");399g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx");400g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position");401g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV");402g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color");403404// Create buffers405glGenBuffers(1, &g_VboHandle);406glGenBuffers(1, &g_ElementsHandle);407408ImGui_ImplOpenGL3_CreateFontsTexture();409410// Restore modified GL state411glBindTexture(GL_TEXTURE_2D, last_texture);412glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);413glBindVertexArray(last_vertex_array);414415return true;416}417418void ImGui_ImplOpenGL3_DestroyDeviceObjects()419{420if (g_VboHandle) glDeleteBuffers(1, &g_VboHandle);421if (g_ElementsHandle) glDeleteBuffers(1, &g_ElementsHandle);422g_VboHandle = g_ElementsHandle = 0;423424if (g_ShaderHandle && g_VertHandle) glDetachShader(g_ShaderHandle, g_VertHandle);425if (g_VertHandle) glDeleteShader(g_VertHandle);426g_VertHandle = 0;427428if (g_ShaderHandle && g_FragHandle) glDetachShader(g_ShaderHandle, g_FragHandle);429if (g_FragHandle) glDeleteShader(g_FragHandle);430g_FragHandle = 0;431432if (g_ShaderHandle) glDeleteProgram(g_ShaderHandle);433g_ShaderHandle = 0;434435ImGui_ImplOpenGL3_DestroyFontsTexture();436}437438439