/ source / imgui / src / imgui_impl_opengl3.cpp
imgui_impl_opengl3.cpp
  1  // dear imgui: Renderer Backend for modern OpenGL with shaders / programmatic pipeline
  2  // - Desktop GL: 2.x 3.x 4.x
  3  // - Embedded GL: ES 2.0 (WebGL 1.0), ES 3.0 (WebGL 2.0)
  4  // This needs to be used along with a Platform Backend (e.g. GLFW, SDL, Win32, custom..)
  5  
  6  // Implemented features:
  7  //  [X] Renderer: User texture binding. Use 'GLuint' OpenGL texture identifier as void*/ImTextureID. Read the FAQ about ImTextureID!
  8  //  [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices (Desktop OpenGL only).
  9  //  [X] Renderer: Multi-viewport support (multiple windows). Enable with 'io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable'.
 10  
 11  // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this.
 12  // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need.
 13  // If you are new to Dear ImGui, read documentation from the docs/ folder + read the top of imgui.cpp.
 14  // Read online: https://github.com/ocornut/imgui/tree/master/docs
 15  
 16  // CHANGELOG
 17  // (minor and older changes stripped away, please see git history for details)
 18  //  2023-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
 19  //  2023-03-06: OpenGL: Fixed restoration of a potentially deleted OpenGL program, by calling glIsProgram(). (#6220, #6224)
 20  //  2022-11-09: OpenGL: Reverted use of glBufferSubData(), too many corruptions issues + old issues seemingly can't be reproed with Intel drivers nowadays (revert 2021-12-15 and 2022-05-23 changes).
 21  //  2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
 22  //  2022-09-27: OpenGL: Added ability to '#define IMGUI_IMPL_OPENGL_DEBUG'.
 23  //  2022-05-23: OpenGL: Reworking 2021-12-15 "Using buffer orphaning" so it only happens on Intel GPU, seems to cause problems otherwise. (#4468, #4825, #4832, #5127).
 24  //  2022-05-13: OpenGL: Fixed state corruption on OpenGL ES 2.0 due to not preserving GL_ELEMENT_ARRAY_BUFFER_BINDING and vertex attribute states.
 25  //  2021-12-15: OpenGL: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers.
 26  //  2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions.
 27  //  2021-08-19: OpenGL: Embed and use our own minimal GL loader (imgui_impl_opengl3_loader.h), removing requirement and support for third-party loader.
 28  //  2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
 29  //  2021-06-25: OpenGL: Use OES_vertex_array extension on Emscripten + backup/restore current state.
 30  //  2021-06-21: OpenGL: Destroy individual vertex/fragment shader objects right after they are linked into the main shader.
 31  //  2021-05-24: OpenGL: Access GL_CLIP_ORIGIN when "GL_ARB_clip_control" extension is detected, inside of just OpenGL 4.5 version.
 32  //  2021-05-19: OpenGL: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
 33  //  2021-04-06: OpenGL: Don't try to read GL_CLIP_ORIGIN unless we're OpenGL 4.5 or greater.
 34  //  2021-02-18: OpenGL: Change blending equation to preserve alpha in output buffer.
 35  //  2021-01-03: OpenGL: Backup, setup and restore GL_STENCIL_TEST state.
 36  //  2020-10-23: OpenGL: Backup, setup and restore GL_PRIMITIVE_RESTART state.
 37  //  2020-10-15: OpenGL: Use glGetString(GL_VERSION) instead of glGetIntegerv(GL_MAJOR_VERSION, ...) when the later returns zero (e.g. Desktop GL 2.x)
 38  //  2020-09-17: OpenGL: Fix to avoid compiling/calling glBindSampler() on ES or pre 3.3 context which have the defines set by a loader.
 39  //  2020-07-10: OpenGL: Added support for glad2 OpenGL loader.
 40  //  2020-05-08: OpenGL: Made default GLSL version 150 (instead of 130) on OSX.
 41  //  2020-04-21: OpenGL: Fixed handling of glClipControl(GL_UPPER_LEFT) by inverting projection matrix.
 42  //  2020-04-12: OpenGL: Fixed context version check mistakenly testing for 4.0+ instead of 3.2+ to enable ImGuiBackendFlags_RendererHasVtxOffset.
 43  //  2020-03-24: OpenGL: Added support for glbinding 2.x OpenGL loader.
 44  //  2020-01-07: OpenGL: Added support for glbinding 3.x OpenGL loader.
 45  //  2019-10-25: OpenGL: Using a combination of GL define and runtime GL version to decide whether to use glDrawElementsBaseVertex(). Fix building with pre-3.2 GL loaders.
 46  //  2019-09-22: OpenGL: Detect default GL loader using __has_include compiler facility.
 47  //  2019-09-16: OpenGL: Tweak initialization code to allow application calling ImGui_ImplOpenGL3_CreateFontsTexture() before the first NewFrame() call.
 48  //  2019-05-29: OpenGL: Desktop GL only: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag.
 49  //  2019-04-30: OpenGL: Added support for special ImDrawCallback_ResetRenderState callback to reset render state.
 50  //  2019-03-29: OpenGL: Not calling glBindBuffer more than necessary in the render loop.
 51  //  2019-03-15: OpenGL: Added a GL call + comments in ImGui_ImplOpenGL3_Init() to detect uninitialized GL function loaders early.
 52  //  2019-03-03: OpenGL: Fix support for ES 2.0 (WebGL 1.0).
 53  //  2019-02-20: OpenGL: Fix for OSX not supporting OpenGL 4.5, we don't try to read GL_CLIP_ORIGIN even if defined by the headers/loader.
 54  //  2019-02-11: OpenGL: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display.
 55  //  2019-02-01: OpenGL: Using GLSL 410 shaders for any version over 410 (e.g. 430, 450).
 56  //  2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window.
 57  //  2018-11-13: OpenGL: Support for GL 4.5's glClipControl(GL_UPPER_LEFT) / GL_CLIP_ORIGIN.
 58  //  2018-08-29: OpenGL: Added support for more OpenGL loaders: glew and glad, with comments indicative that any loader can be used.
 59  //  2018-08-09: OpenGL: Default to OpenGL ES 3 on iOS and Android. GLSL version default to "#version 300 ES".
 60  //  2018-07-30: OpenGL: Support for GLSL 300 ES and 410 core. Fixes for Emscripten compilation.
 61  //  2018-07-10: OpenGL: Support for more GLSL versions (based on the GLSL version string). Added error output when shaders fail to compile/link.
 62  //  2018-06-08: Misc: Extracted imgui_impl_opengl3.cpp/.h away from the old combined GLFW/SDL+OpenGL3 examples.
 63  //  2018-06-08: OpenGL: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle.
 64  //  2018-05-25: OpenGL: Removed unnecessary backup/restore of GL_ELEMENT_ARRAY_BUFFER_BINDING since this is part of the VAO state.
 65  //  2018-05-14: OpenGL: Making the call to glBindSampler() optional so 3.2 context won't fail if the function is a nullptr pointer.
 66  //  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".
 67  //  2018-02-23: OpenGL: Create the VAO in the render function so the setup can more easily be used with multiple shared GL context.
 68  //  2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplSdlGL3_RenderDrawData() in the .h file so you can call it yourself.
 69  //  2018-01-07: OpenGL: Changed GLSL shader version from 330 to 150.
 70  //  2017-09-01: OpenGL: Save and restore current bound sampler. Save and restore current polygon mode.
 71  //  2017-05-01: OpenGL: Fixed save and restore of current blend func state.
 72  //  2017-05-01: OpenGL: Fixed save and restore of current GL_ACTIVE_TEXTURE.
 73  //  2016-09-05: OpenGL: Fixed save and restore of current scissor rectangle.
 74  //  2016-07-29: OpenGL: Explicitly setting GL_UNPACK_ROW_LENGTH to reduce issues because SDL changes it. (#752)
 75  
 76  //----------------------------------------
 77  // OpenGL    GLSL      GLSL
 78  // version   version   string
 79  //----------------------------------------
 80  //  2.0       110       "#version 110"
 81  //  2.1       120       "#version 120"
 82  //  3.0       130       "#version 130"
 83  //  3.1       140       "#version 140"
 84  //  3.2       150       "#version 150"
 85  //  3.3       330       "#version 330 core"
 86  //  4.0       400       "#version 400 core"
 87  //  4.1       410       "#version 410 core"
 88  //  4.2       420       "#version 410 core"
 89  //  4.3       430       "#version 430 core"
 90  //  ES 2.0    100       "#version 100"      = WebGL 1.0
 91  //  ES 3.0    300       "#version 300 es"   = WebGL 2.0
 92  //----------------------------------------
 93  
 94  #if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS)
 95  #define _CRT_SECURE_NO_WARNINGS
 96  #endif
 97  
 98  #include "imgui.h"
 99  #include "imgui_impl_opengl3.h"
100  #include <stdio.h>
101  #if defined(_MSC_VER) && _MSC_VER <= 1500 // MSVC 2008 or earlier
102  #include <stddef.h>     // intptr_t
103  #else
104  #include <stdint.h>     // intptr_t
105  #endif
106  #if defined(__APPLE__)
107  #include <TargetConditionals.h>
108  #endif
109  
110  // Clang warnings with -Weverything
111  #if defined(__clang__)
112  #pragma clang diagnostic push
113  #pragma clang diagnostic ignored "-Wold-style-cast"         // warning: use of old-style cast
114  #pragma clang diagnostic ignored "-Wsign-conversion"        // warning: implicit conversion changes signedness
115  #endif
116  #if defined(__GNUC__)
117  #pragma GCC diagnostic push
118  #pragma GCC diagnostic ignored "-Wpragmas"                  // warning: unknown option after '#pragma GCC diagnostic' kind
119  #pragma GCC diagnostic ignored "-Wunknown-warning-option"   // warning: unknown warning group 'xxx'
120  #pragma GCC diagnostic ignored "-Wcast-function-type"       // warning: cast between incompatible function types
121  #endif
122  
123  // GL includes
124  #if defined(IMGUI_IMPL_OPENGL_ES2)
125  #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV))
126  #include <OpenGLES/ES2/gl.h>    // Use GL ES 2
127  #else
128  #include <GLES2/gl2.h>          // Use GL ES 2
129  #endif
130  #if defined(__EMSCRIPTEN__)
131  #ifndef GL_GLEXT_PROTOTYPES
132  #define GL_GLEXT_PROTOTYPES
133  #endif
134  #include <GLES2/gl2ext.h>
135  #endif
136  #elif defined(IMGUI_IMPL_OPENGL_ES3)
137  #if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV))
138  #include <OpenGLES/ES3/gl.h>    // Use GL ES 3
139  #else
140  #include <GLES3/gl3.h>          // Use GL ES 3
141  #endif
142  #elif !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)
143  // Modern desktop OpenGL doesn't have a standard portable header file to load OpenGL function pointers.
144  // Helper libraries are often used for this purpose! Here we are using our own minimal custom loader based on gl3w.
145  // In the rest of your app/engine, you can use another loader of your choice (gl3w, glew, glad, glbinding, glext, glLoadGen, etc.).
146  // If you happen to be developing a new feature for this backend (imgui_impl_opengl3.cpp):
147  // - You may need to regenerate imgui_impl_opengl3_loader.h to add new symbols. See https://github.com/dearimgui/gl3w_stripped
148  // - You can temporarily use an unstripped version. See https://github.com/dearimgui/gl3w_stripped/releases
149  // Changes to this backend using new APIs should be accompanied by a regenerated stripped loader version.
150  #define IMGL3W_IMPL
151  #include "imgui_impl_opengl3_loader.h"
152  #endif
153  
154  // Vertex arrays are not supported on ES2/WebGL1 unless Emscripten which uses an extension
155  #ifndef IMGUI_IMPL_OPENGL_ES2
156  #define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
157  #elif defined(__EMSCRIPTEN__)
158  #define IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
159  #define glBindVertexArray       glBindVertexArrayOES
160  #define glGenVertexArrays       glGenVertexArraysOES
161  #define glDeleteVertexArrays    glDeleteVertexArraysOES
162  #define GL_VERTEX_ARRAY_BINDING GL_VERTEX_ARRAY_BINDING_OES
163  #endif
164  
165  // Desktop GL 2.0+ has glPolygonMode() which GL ES and WebGL don't have.
166  #ifdef GL_POLYGON_MODE
167  #define IMGUI_IMPL_HAS_POLYGON_MODE
168  #endif
169  
170  // Desktop GL 3.2+ has glDrawElementsBaseVertex() which GL ES and WebGL don't have.
171  #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_2)
172  #define IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
173  #endif
174  
175  // Desktop GL 3.3+ has glBindSampler()
176  #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_3)
177  #define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
178  #endif
179  
180  // Desktop GL 3.1+ has GL_PRIMITIVE_RESTART state
181  #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && defined(GL_VERSION_3_1)
182  #define IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
183  #endif
184  
185  // Desktop GL use extension detection
186  #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3)
187  #define IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS
188  #endif
189  
190  // [Debugging]
191  //#define IMGUI_IMPL_OPENGL_DEBUG
192  #ifdef IMGUI_IMPL_OPENGL_DEBUG
193  #include <stdio.h>
194  #define GL_CALL(_CALL)      do { _CALL; GLenum gl_err = glGetError(); if (gl_err != 0) fprintf(stderr, "GL error 0x%x returned from '%s'.\n", gl_err, #_CALL); } while (0)  // Call with error check
195  #else
196  #define GL_CALL(_CALL)      _CALL   // Call without error check
197  #endif
198  
199  // OpenGL Data
200  struct ImGui_ImplOpenGL3_Data
201  {
202      GLuint          GlVersion;               // Extracted at runtime using GL_MAJOR_VERSION, GL_MINOR_VERSION queries (e.g. 320 for GL 3.2)
203      char            GlslVersionString[32];   // Specified by user or detected based on compile time GL settings.
204      GLuint          FontTexture;
205      GLuint          ShaderHandle;
206      GLint           AttribLocationTex;       // Uniforms location
207      GLint           AttribLocationProjMtx;
208      GLuint          AttribLocationVtxPos;    // Vertex attributes location
209      GLuint          AttribLocationVtxUV;
210      GLuint          AttribLocationVtxColor;
211      unsigned int    VboHandle, ElementsHandle;
212      GLsizeiptr      VertexBufferSize;
213      GLsizeiptr      IndexBufferSize;
214      bool            HasClipOrigin;
215      bool            UseBufferSubData;
216  
217      ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); }
218  };
219  
220  // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts
221  // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts.
222  static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData()
223  {
224      return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr;
225  }
226  
227  // Forward Declarations
228  static void ImGui_ImplOpenGL3_InitPlatformInterface();
229  static void ImGui_ImplOpenGL3_ShutdownPlatformInterface();
230  
231  // OpenGL vertex attribute state (for ES 1.0 and ES 2.0 only)
232  #ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
233  struct ImGui_ImplOpenGL3_VtxAttribState
234  {
235      GLint   Enabled, Size, Type, Normalized, Stride;
236      GLvoid* Ptr;
237  
238      void GetState(GLint index)
239      {
240          glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &Enabled);
241          glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_SIZE, &Size);
242          glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_TYPE, &Type);
243          glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &Normalized);
244          glGetVertexAttribiv(index, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &Stride);
245          glGetVertexAttribPointerv(index, GL_VERTEX_ATTRIB_ARRAY_POINTER, &Ptr);
246      }
247      void SetState(GLint index)
248      {
249          glVertexAttribPointer(index, Size, Type, (GLboolean)Normalized, Stride, Ptr);
250          if (Enabled) glEnableVertexAttribArray(index); else glDisableVertexAttribArray(index);
251      }
252  };
253  #endif
254  
255  // Functions
256  bool    ImGui_ImplOpenGL3_Init(const char* glsl_version)
257  {
258      ImGuiIO& io = ImGui::GetIO();
259      IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");
260  
261      // Initialize our loader
262  #if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) && !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM)
263      if (imgl3wInit() != 0)
264      {
265          fprintf(stderr, "Failed to initialize OpenGL loader!\n");
266          return false;
267      }
268  #endif
269  
270      // Setup backend capabilities flags
271      ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)();
272      io.BackendRendererUserData = (void*)bd;
273      io.BackendRendererName = "imgui_impl_opengl3";
274  
275      // Query for GL version (e.g. 320 for GL 3.2)
276  #if !defined(IMGUI_IMPL_OPENGL_ES2)
277      GLint major = 0;
278      GLint minor = 0;
279      glGetIntegerv(GL_MAJOR_VERSION, &major);
280      glGetIntegerv(GL_MINOR_VERSION, &minor);
281      if (major == 0 && minor == 0)
282      {
283          // Query GL_VERSION in desktop GL 2.x, the string will start with "<major>.<minor>"
284          const char* gl_version = (const char*)glGetString(GL_VERSION);
285          sscanf(gl_version, "%d.%d", &major, &minor);
286      }
287      bd->GlVersion = (GLuint)(major * 100 + minor * 10);
288  
289      bd->UseBufferSubData = false;
290      /*
291      // Query vendor to enable glBufferSubData kludge
292  #ifdef _WIN32
293      if (const char* vendor = (const char*)glGetString(GL_VENDOR))
294          if (strncmp(vendor, "Intel", 5) == 0)
295              bd->UseBufferSubData = true;
296  #endif
297      */
298  #else
299      bd->GlVersion = 200; // GLES 2
300  #endif
301  
302  #ifdef IMGUI_IMPL_OPENGL_DEBUG
303      printf("GL_MAJOR_VERSION = %d\nGL_MINOR_VERSION = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", major, minor, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG]
304  #endif
305  
306  #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
307      if (bd->GlVersion >= 320)
308          io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset;  // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
309  #endif
310      io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports;  // We can create multi-viewports on the Renderer side (optional)
311  
312      // Store GLSL version string so we can refer to it later in case we recreate shaders.
313      // Note: GLSL version is NOT the same as GL version. Leave this to nullptr if unsure.
314      if (glsl_version == nullptr)
315      {
316  #if defined(IMGUI_IMPL_OPENGL_ES2)
317          glsl_version = "#version 100";
318  #elif defined(IMGUI_IMPL_OPENGL_ES3)
319          glsl_version = "#version 300 es";
320  #elif defined(__APPLE__)
321          glsl_version = "#version 150";
322  #else
323          glsl_version = "#version 130";
324  #endif
325      }
326      IM_ASSERT((int)strlen(glsl_version) + 2 < IM_ARRAYSIZE(bd->GlslVersionString));
327      strcpy(bd->GlslVersionString, glsl_version);
328      strcat(bd->GlslVersionString, "\n");
329  
330      // Make an arbitrary GL call (we don't actually need the result)
331      // IF YOU GET A CRASH HERE: it probably means the OpenGL function loader didn't do its job. Let us know!
332      GLint current_texture;
333      glGetIntegerv(GL_TEXTURE_BINDING_2D, &current_texture);
334  
335      // Detect extensions we support
336      bd->HasClipOrigin = (bd->GlVersion >= 450);
337  #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_EXTENSIONS
338      GLint num_extensions = 0;
339      glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions);
340      for (GLint i = 0; i < num_extensions; i++)
341      {
342          const char* extension = (const char*)glGetStringi(GL_EXTENSIONS, i);
343          if (extension != nullptr && strcmp(extension, "GL_ARB_clip_control") == 0)
344              bd->HasClipOrigin = true;
345      }
346  #endif
347  
348      if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
349          ImGui_ImplOpenGL3_InitPlatformInterface();
350  
351      return true;
352  }
353  
354  void    ImGui_ImplOpenGL3_Shutdown()
355  {
356      ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
357      IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?");
358      ImGuiIO& io = ImGui::GetIO();
359  
360      ImGui_ImplOpenGL3_ShutdownPlatformInterface();
361      ImGui_ImplOpenGL3_DestroyDeviceObjects();
362      io.BackendRendererName = nullptr;
363      io.BackendRendererUserData = nullptr;
364      IM_DELETE(bd);
365  }
366  
367  void    ImGui_ImplOpenGL3_NewFrame()
368  {
369      ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
370      IM_ASSERT(bd != nullptr && "Did you call ImGui_ImplOpenGL3_Init()?");
371  
372      if (!bd->ShaderHandle)
373          ImGui_ImplOpenGL3_CreateDeviceObjects();
374  }
375  
376  static void ImGui_ImplOpenGL3_SetupRenderState(ImDrawData* draw_data, int fb_width, int fb_height, GLuint vertex_array_object)
377  {
378      ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
379  
380      // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill
381      glEnable(GL_BLEND);
382      glBlendEquation(GL_FUNC_ADD);
383      glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
384      glDisable(GL_CULL_FACE);
385      glDisable(GL_DEPTH_TEST);
386      glDisable(GL_STENCIL_TEST);
387      glEnable(GL_SCISSOR_TEST);
388  #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
389      if (bd->GlVersion >= 310)
390          glDisable(GL_PRIMITIVE_RESTART);
391  #endif
392  #ifdef IMGUI_IMPL_HAS_POLYGON_MODE
393      glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
394  #endif
395  
396      // Support for GL 4.5 rarely used glClipControl(GL_UPPER_LEFT)
397  #if defined(GL_CLIP_ORIGIN)
398      bool clip_origin_lower_left = true;
399      if (bd->HasClipOrigin)
400      {
401          GLenum current_clip_origin = 0; glGetIntegerv(GL_CLIP_ORIGIN, (GLint*)&current_clip_origin);
402          if (current_clip_origin == GL_UPPER_LEFT)
403              clip_origin_lower_left = false;
404      }
405  #endif
406  
407      // Setup viewport, orthographic projection matrix
408      // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps.
409      GL_CALL(glViewport(0, 0, (GLsizei)fb_width, (GLsizei)fb_height));
410      float L = draw_data->DisplayPos.x;
411      float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x;
412      float T = draw_data->DisplayPos.y;
413      float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y;
414  #if defined(GL_CLIP_ORIGIN)
415      if (!clip_origin_lower_left) { float tmp = T; T = B; B = tmp; } // Swap top and bottom if origin is upper left
416  #endif
417      const float ortho_projection[4][4] =
418      {
419          { 2.0f/(R-L),   0.0f,         0.0f,   0.0f },
420          { 0.0f,         2.0f/(T-B),   0.0f,   0.0f },
421          { 0.0f,         0.0f,        -1.0f,   0.0f },
422          { (R+L)/(L-R),  (T+B)/(B-T),  0.0f,   1.0f },
423      };
424      glUseProgram(bd->ShaderHandle);
425      glUniform1i(bd->AttribLocationTex, 0);
426      glUniformMatrix4fv(bd->AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]);
427  
428  #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
429      if (bd->GlVersion >= 330)
430          glBindSampler(0, 0); // We use combined texture/sampler state. Applications using GL 3.3 may set that otherwise.
431  #endif
432  
433      (void)vertex_array_object;
434  #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
435      glBindVertexArray(vertex_array_object);
436  #endif
437  
438      // Bind vertex/index buffers and setup attributes for ImDrawVert
439      GL_CALL(glBindBuffer(GL_ARRAY_BUFFER, bd->VboHandle));
440      GL_CALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bd->ElementsHandle));
441      GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxPos));
442      GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxUV));
443      GL_CALL(glEnableVertexAttribArray(bd->AttribLocationVtxColor));
444      GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxPos,   2, GL_FLOAT,         GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)));
445      GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxUV,    2, GL_FLOAT,         GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)));
446      GL_CALL(glVertexAttribPointer(bd->AttribLocationVtxColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)));
447  }
448  
449  // OpenGL3 Render function.
450  // Note that this implementation is little overcomplicated because we are saving/setting up/restoring every OpenGL state explicitly.
451  // This is in order to be able to run within an OpenGL engine that doesn't do so.
452  void    ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data)
453  {
454      // Avoid rendering when minimized, scale coordinates for retina displays (screen coordinates != framebuffer coordinates)
455      int fb_width = (int)(draw_data->DisplaySize.x * draw_data->FramebufferScale.x);
456      int fb_height = (int)(draw_data->DisplaySize.y * draw_data->FramebufferScale.y);
457      if (fb_width <= 0 || fb_height <= 0)
458          return;
459  
460      ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
461  
462      // Backup GL state
463      GLenum last_active_texture; glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint*)&last_active_texture);
464      glActiveTexture(GL_TEXTURE0);
465      GLuint last_program; glGetIntegerv(GL_CURRENT_PROGRAM, (GLint*)&last_program);
466      GLuint last_texture; glGetIntegerv(GL_TEXTURE_BINDING_2D, (GLint*)&last_texture);
467  #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
468      GLuint last_sampler; if (bd->GlVersion >= 330) { glGetIntegerv(GL_SAMPLER_BINDING, (GLint*)&last_sampler); } else { last_sampler = 0; }
469  #endif
470      GLuint last_array_buffer; glGetIntegerv(GL_ARRAY_BUFFER_BINDING, (GLint*)&last_array_buffer);
471  #ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
472      // This is part of VAO on OpenGL 3.0+ and OpenGL ES 3.0+.
473      GLint last_element_array_buffer; glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &last_element_array_buffer);
474      ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_pos; last_vtx_attrib_state_pos.GetState(bd->AttribLocationVtxPos);
475      ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_uv; last_vtx_attrib_state_uv.GetState(bd->AttribLocationVtxUV);
476      ImGui_ImplOpenGL3_VtxAttribState last_vtx_attrib_state_color; last_vtx_attrib_state_color.GetState(bd->AttribLocationVtxColor);
477  #endif
478  #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
479      GLuint last_vertex_array_object; glGetIntegerv(GL_VERTEX_ARRAY_BINDING, (GLint*)&last_vertex_array_object);
480  #endif
481  #ifdef IMGUI_IMPL_HAS_POLYGON_MODE
482      GLint last_polygon_mode[2]; glGetIntegerv(GL_POLYGON_MODE, last_polygon_mode);
483  #endif
484      GLint last_viewport[4]; glGetIntegerv(GL_VIEWPORT, last_viewport);
485      GLint last_scissor_box[4]; glGetIntegerv(GL_SCISSOR_BOX, last_scissor_box);
486      GLenum last_blend_src_rgb; glGetIntegerv(GL_BLEND_SRC_RGB, (GLint*)&last_blend_src_rgb);
487      GLenum last_blend_dst_rgb; glGetIntegerv(GL_BLEND_DST_RGB, (GLint*)&last_blend_dst_rgb);
488      GLenum last_blend_src_alpha; glGetIntegerv(GL_BLEND_SRC_ALPHA, (GLint*)&last_blend_src_alpha);
489      GLenum last_blend_dst_alpha; glGetIntegerv(GL_BLEND_DST_ALPHA, (GLint*)&last_blend_dst_alpha);
490      GLenum last_blend_equation_rgb; glGetIntegerv(GL_BLEND_EQUATION_RGB, (GLint*)&last_blend_equation_rgb);
491      GLenum last_blend_equation_alpha; glGetIntegerv(GL_BLEND_EQUATION_ALPHA, (GLint*)&last_blend_equation_alpha);
492      GLboolean last_enable_blend = glIsEnabled(GL_BLEND);
493      GLboolean last_enable_cull_face = glIsEnabled(GL_CULL_FACE);
494      GLboolean last_enable_depth_test = glIsEnabled(GL_DEPTH_TEST);
495      GLboolean last_enable_stencil_test = glIsEnabled(GL_STENCIL_TEST);
496      GLboolean last_enable_scissor_test = glIsEnabled(GL_SCISSOR_TEST);
497  #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
498      GLboolean last_enable_primitive_restart = (bd->GlVersion >= 310) ? glIsEnabled(GL_PRIMITIVE_RESTART) : GL_FALSE;
499  #endif
500  
501      // Setup desired GL state
502      // Recreate the VAO every time (this is to easily allow multiple GL contexts to be rendered to. VAO are not shared among GL contexts)
503      // The renderer would actually work without any VAO bound, but then our VertexAttrib calls would overwrite the default one currently bound.
504      GLuint vertex_array_object = 0;
505  #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
506      GL_CALL(glGenVertexArrays(1, &vertex_array_object));
507  #endif
508      ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
509  
510      // Will project scissor/clipping rectangles into framebuffer space
511      ImVec2 clip_off = draw_data->DisplayPos;         // (0,0) unless using multi-viewports
512      ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2)
513  
514      // Render command lists
515      for (int n = 0; n < draw_data->CmdListsCount; n++)
516      {
517          const ImDrawList* cmd_list = draw_data->CmdLists[n];
518  
519          // Upload vertex/index buffers
520          // - OpenGL drivers are in a very sorry state nowadays....
521          //   During 2021 we attempted to switch from glBufferData() to orphaning+glBufferSubData() following reports
522          //   of leaks on Intel GPU when using multi-viewports on Windows.
523          // - After this we kept hearing of various display corruptions issues. We started disabling on non-Intel GPU, but issues still got reported on Intel.
524          // - We are now back to using exclusively glBufferData(). So bd->UseBufferSubData IS ALWAYS FALSE in this code.
525          //   We are keeping the old code path for a while in case people finding new issues may want to test the bd->UseBufferSubData path.
526          // - See https://github.com/ocornut/imgui/issues/4468 and please report any corruption issues.
527          const GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert);
528          const GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx);
529          if (bd->UseBufferSubData)
530          {
531              if (bd->VertexBufferSize < vtx_buffer_size)
532              {
533                  bd->VertexBufferSize = vtx_buffer_size;
534                  GL_CALL(glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, nullptr, GL_STREAM_DRAW));
535              }
536              if (bd->IndexBufferSize < idx_buffer_size)
537              {
538                  bd->IndexBufferSize = idx_buffer_size;
539                  GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, nullptr, GL_STREAM_DRAW));
540              }
541              GL_CALL(glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data));
542              GL_CALL(glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data));
543          }
544          else
545          {
546              GL_CALL(glBufferData(GL_ARRAY_BUFFER, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW));
547              GL_CALL(glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW));
548          }
549  
550          for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++)
551          {
552              const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i];
553              if (pcmd->UserCallback != nullptr)
554              {
555                  // User callback, registered via ImDrawList::AddCallback()
556                  // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.)
557                  if (pcmd->UserCallback == ImDrawCallback_ResetRenderState)
558                      ImGui_ImplOpenGL3_SetupRenderState(draw_data, fb_width, fb_height, vertex_array_object);
559                  else
560                      pcmd->UserCallback(cmd_list, pcmd);
561              }
562              else
563              {
564                  // Project scissor/clipping rectangles into framebuffer space
565                  ImVec2 clip_min((pcmd->ClipRect.x - clip_off.x) * clip_scale.x, (pcmd->ClipRect.y - clip_off.y) * clip_scale.y);
566                  ImVec2 clip_max((pcmd->ClipRect.z - clip_off.x) * clip_scale.x, (pcmd->ClipRect.w - clip_off.y) * clip_scale.y);
567                  if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y)
568                      continue;
569  
570                  // Apply scissor/clipping rectangle (Y is inverted in OpenGL)
571                  GL_CALL(glScissor((int)clip_min.x, (int)((float)fb_height - clip_max.y), (int)(clip_max.x - clip_min.x), (int)(clip_max.y - clip_min.y)));
572  
573                  // Bind texture, Draw
574                  GL_CALL(glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID()));
575  #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET
576                  if (bd->GlVersion >= 320)
577                      GL_CALL(glDrawElementsBaseVertex(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx)), (GLint)pcmd->VtxOffset));
578                  else
579  #endif
580                  GL_CALL(glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, (void*)(intptr_t)(pcmd->IdxOffset * sizeof(ImDrawIdx))));
581              }
582          }
583      }
584  
585      // Destroy the temporary VAO
586  #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
587      GL_CALL(glDeleteVertexArrays(1, &vertex_array_object));
588  #endif
589  
590      // Restore modified GL state
591      // This "glIsProgram()" check is required because if the program is "pending deletion" at the time of binding backup, it will have been deleted by now and will cause an OpenGL error. See #6220.
592      if (glIsProgram(last_program)) glUseProgram(last_program);
593      glBindTexture(GL_TEXTURE_2D, last_texture);
594  #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_SAMPLER
595      if (bd->GlVersion >= 330)
596          glBindSampler(0, last_sampler);
597  #endif
598      glActiveTexture(last_active_texture);
599  #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
600      glBindVertexArray(last_vertex_array_object);
601  #endif
602      glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
603  #ifndef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
604      glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, last_element_array_buffer);
605      last_vtx_attrib_state_pos.SetState(bd->AttribLocationVtxPos);
606      last_vtx_attrib_state_uv.SetState(bd->AttribLocationVtxUV);
607      last_vtx_attrib_state_color.SetState(bd->AttribLocationVtxColor);
608  #endif
609      glBlendEquationSeparate(last_blend_equation_rgb, last_blend_equation_alpha);
610      glBlendFuncSeparate(last_blend_src_rgb, last_blend_dst_rgb, last_blend_src_alpha, last_blend_dst_alpha);
611      if (last_enable_blend) glEnable(GL_BLEND); else glDisable(GL_BLEND);
612      if (last_enable_cull_face) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE);
613      if (last_enable_depth_test) glEnable(GL_DEPTH_TEST); else glDisable(GL_DEPTH_TEST);
614      if (last_enable_stencil_test) glEnable(GL_STENCIL_TEST); else glDisable(GL_STENCIL_TEST);
615      if (last_enable_scissor_test) glEnable(GL_SCISSOR_TEST); else glDisable(GL_SCISSOR_TEST);
616  #ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_PRIMITIVE_RESTART
617      if (bd->GlVersion >= 310) { if (last_enable_primitive_restart) glEnable(GL_PRIMITIVE_RESTART); else glDisable(GL_PRIMITIVE_RESTART); }
618  #endif
619  
620  #ifdef IMGUI_IMPL_HAS_POLYGON_MODE
621      glPolygonMode(GL_FRONT_AND_BACK, (GLenum)last_polygon_mode[0]);
622  #endif
623      glViewport(last_viewport[0], last_viewport[1], (GLsizei)last_viewport[2], (GLsizei)last_viewport[3]);
624      glScissor(last_scissor_box[0], last_scissor_box[1], (GLsizei)last_scissor_box[2], (GLsizei)last_scissor_box[3]);
625      (void)bd; // Not all compilation paths use this
626  }
627  
628  bool ImGui_ImplOpenGL3_CreateFontsTexture()
629  {
630      ImGuiIO& io = ImGui::GetIO();
631      ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
632  
633      // Build texture atlas
634      unsigned char* pixels;
635      int width, height;
636      io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);   // Load as RGBA 32-bit (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.
637  
638      // Upload texture to graphics system
639      // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
640      GLint last_texture;
641      GL_CALL(glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture));
642      GL_CALL(glGenTextures(1, &bd->FontTexture));
643      GL_CALL(glBindTexture(GL_TEXTURE_2D, bd->FontTexture));
644      GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
645      GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
646  #ifdef GL_UNPACK_ROW_LENGTH // Not on WebGL/ES
647      GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH, 0));
648  #endif
649      GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
650  
651      // Store our identifier
652      io.Fonts->SetTexID((ImTextureID)(intptr_t)bd->FontTexture);
653  
654      // Restore state
655      GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture));
656  
657      return true;
658  }
659  
660  void ImGui_ImplOpenGL3_DestroyFontsTexture()
661  {
662      ImGuiIO& io = ImGui::GetIO();
663      ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
664      if (bd->FontTexture)
665      {
666          glDeleteTextures(1, &bd->FontTexture);
667          io.Fonts->SetTexID(0);
668          bd->FontTexture = 0;
669      }
670  }
671  
672  // If you get an error please report on github. You may try different GL context version or GLSL version. See GL<>GLSL version table at the top of this file.
673  static bool CheckShader(GLuint handle, const char* desc)
674  {
675      ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
676      GLint status = 0, log_length = 0;
677      glGetShaderiv(handle, GL_COMPILE_STATUS, &status);
678      glGetShaderiv(handle, GL_INFO_LOG_LENGTH, &log_length);
679      if ((GLboolean)status == GL_FALSE)
680          fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile %s! With GLSL: %s\n", desc, bd->GlslVersionString);
681      if (log_length > 1)
682      {
683          ImVector<char> buf;
684          buf.resize((int)(log_length + 1));
685          glGetShaderInfoLog(handle, log_length, nullptr, (GLchar*)buf.begin());
686          fprintf(stderr, "%s\n", buf.begin());
687      }
688      return (GLboolean)status == GL_TRUE;
689  }
690  
691  // If you get an error please report on GitHub. You may try different GL context version or GLSL version.
692  static bool CheckProgram(GLuint handle, const char* desc)
693  {
694      ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
695      GLint status = 0, log_length = 0;
696      glGetProgramiv(handle, GL_LINK_STATUS, &status);
697      glGetProgramiv(handle, GL_INFO_LOG_LENGTH, &log_length);
698      if ((GLboolean)status == GL_FALSE)
699          fprintf(stderr, "ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link %s! With GLSL %s\n", desc, bd->GlslVersionString);
700      if (log_length > 1)
701      {
702          ImVector<char> buf;
703          buf.resize((int)(log_length + 1));
704          glGetProgramInfoLog(handle, log_length, nullptr, (GLchar*)buf.begin());
705          fprintf(stderr, "%s\n", buf.begin());
706      }
707      return (GLboolean)status == GL_TRUE;
708  }
709  
710  bool    ImGui_ImplOpenGL3_CreateDeviceObjects()
711  {
712      ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
713  
714      // Backup GL state
715      GLint last_texture, last_array_buffer;
716      glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture);
717      glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &last_array_buffer);
718  #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
719      GLint last_vertex_array;
720      glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &last_vertex_array);
721  #endif
722  
723      // Parse GLSL version string
724      int glsl_version = 130;
725      sscanf(bd->GlslVersionString, "#version %d", &glsl_version);
726  
727      const GLchar* vertex_shader_glsl_120 =
728          "uniform mat4 ProjMtx;\n"
729          "attribute vec2 Position;\n"
730          "attribute vec2 UV;\n"
731          "attribute vec4 Color;\n"
732          "varying vec2 Frag_UV;\n"
733          "varying vec4 Frag_Color;\n"
734          "void main()\n"
735          "{\n"
736          "    Frag_UV = UV;\n"
737          "    Frag_Color = Color;\n"
738          "    gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
739          "}\n";
740  
741      const GLchar* vertex_shader_glsl_130 =
742          "uniform mat4 ProjMtx;\n"
743          "in vec2 Position;\n"
744          "in vec2 UV;\n"
745          "in vec4 Color;\n"
746          "out vec2 Frag_UV;\n"
747          "out vec4 Frag_Color;\n"
748          "void main()\n"
749          "{\n"
750          "    Frag_UV = UV;\n"
751          "    Frag_Color = Color;\n"
752          "    gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
753          "}\n";
754  
755      const GLchar* vertex_shader_glsl_300_es =
756          "precision highp float;\n"
757          "layout (location = 0) in vec2 Position;\n"
758          "layout (location = 1) in vec2 UV;\n"
759          "layout (location = 2) in vec4 Color;\n"
760          "uniform mat4 ProjMtx;\n"
761          "out vec2 Frag_UV;\n"
762          "out vec4 Frag_Color;\n"
763          "void main()\n"
764          "{\n"
765          "    Frag_UV = UV;\n"
766          "    Frag_Color = Color;\n"
767          "    gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
768          "}\n";
769  
770      const GLchar* vertex_shader_glsl_410_core =
771          "layout (location = 0) in vec2 Position;\n"
772          "layout (location = 1) in vec2 UV;\n"
773          "layout (location = 2) in vec4 Color;\n"
774          "uniform mat4 ProjMtx;\n"
775          "out vec2 Frag_UV;\n"
776          "out vec4 Frag_Color;\n"
777          "void main()\n"
778          "{\n"
779          "    Frag_UV = UV;\n"
780          "    Frag_Color = Color;\n"
781          "    gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
782          "}\n";
783  
784      const GLchar* fragment_shader_glsl_120 =
785          "#ifdef GL_ES\n"
786          "    precision mediump float;\n"
787          "#endif\n"
788          "uniform sampler2D Texture;\n"
789          "varying vec2 Frag_UV;\n"
790          "varying vec4 Frag_Color;\n"
791          "void main()\n"
792          "{\n"
793          "    gl_FragColor = Frag_Color * texture2D(Texture, Frag_UV.st);\n"
794          "}\n";
795  
796      const GLchar* fragment_shader_glsl_130 =
797          "uniform sampler2D Texture;\n"
798          "in vec2 Frag_UV;\n"
799          "in vec4 Frag_Color;\n"
800          "out vec4 Out_Color;\n"
801          "void main()\n"
802          "{\n"
803          "    Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
804          "}\n";
805  
806      const GLchar* fragment_shader_glsl_300_es =
807          "precision mediump float;\n"
808          "uniform sampler2D Texture;\n"
809          "in vec2 Frag_UV;\n"
810          "in vec4 Frag_Color;\n"
811          "layout (location = 0) out vec4 Out_Color;\n"
812          "void main()\n"
813          "{\n"
814          "    Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
815          "}\n";
816  
817      const GLchar* fragment_shader_glsl_410_core =
818          "in vec2 Frag_UV;\n"
819          "in vec4 Frag_Color;\n"
820          "uniform sampler2D Texture;\n"
821          "layout (location = 0) out vec4 Out_Color;\n"
822          "void main()\n"
823          "{\n"
824          "    Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n"
825          "}\n";
826  
827      // Select shaders matching our GLSL versions
828      const GLchar* vertex_shader = nullptr;
829      const GLchar* fragment_shader = nullptr;
830      if (glsl_version < 130)
831      {
832          vertex_shader = vertex_shader_glsl_120;
833          fragment_shader = fragment_shader_glsl_120;
834      }
835      else if (glsl_version >= 410)
836      {
837          vertex_shader = vertex_shader_glsl_410_core;
838          fragment_shader = fragment_shader_glsl_410_core;
839      }
840      else if (glsl_version == 300)
841      {
842          vertex_shader = vertex_shader_glsl_300_es;
843          fragment_shader = fragment_shader_glsl_300_es;
844      }
845      else
846      {
847          vertex_shader = vertex_shader_glsl_130;
848          fragment_shader = fragment_shader_glsl_130;
849      }
850  
851      // Create shaders
852      const GLchar* vertex_shader_with_version[2] = { bd->GlslVersionString, vertex_shader };
853      GLuint vert_handle = glCreateShader(GL_VERTEX_SHADER);
854      glShaderSource(vert_handle, 2, vertex_shader_with_version, nullptr);
855      glCompileShader(vert_handle);
856      CheckShader(vert_handle, "vertex shader");
857  
858      const GLchar* fragment_shader_with_version[2] = { bd->GlslVersionString, fragment_shader };
859      GLuint frag_handle = glCreateShader(GL_FRAGMENT_SHADER);
860      glShaderSource(frag_handle, 2, fragment_shader_with_version, nullptr);
861      glCompileShader(frag_handle);
862      CheckShader(frag_handle, "fragment shader");
863  
864      // Link
865      bd->ShaderHandle = glCreateProgram();
866      glAttachShader(bd->ShaderHandle, vert_handle);
867      glAttachShader(bd->ShaderHandle, frag_handle);
868      glLinkProgram(bd->ShaderHandle);
869      CheckProgram(bd->ShaderHandle, "shader program");
870  
871      glDetachShader(bd->ShaderHandle, vert_handle);
872      glDetachShader(bd->ShaderHandle, frag_handle);
873      glDeleteShader(vert_handle);
874      glDeleteShader(frag_handle);
875  
876      bd->AttribLocationTex = glGetUniformLocation(bd->ShaderHandle, "Texture");
877      bd->AttribLocationProjMtx = glGetUniformLocation(bd->ShaderHandle, "ProjMtx");
878      bd->AttribLocationVtxPos = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Position");
879      bd->AttribLocationVtxUV = (GLuint)glGetAttribLocation(bd->ShaderHandle, "UV");
880      bd->AttribLocationVtxColor = (GLuint)glGetAttribLocation(bd->ShaderHandle, "Color");
881  
882      // Create buffers
883      glGenBuffers(1, &bd->VboHandle);
884      glGenBuffers(1, &bd->ElementsHandle);
885  
886      ImGui_ImplOpenGL3_CreateFontsTexture();
887  
888      // Restore modified GL state
889      glBindTexture(GL_TEXTURE_2D, last_texture);
890      glBindBuffer(GL_ARRAY_BUFFER, last_array_buffer);
891  #ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY
892      glBindVertexArray(last_vertex_array);
893  #endif
894  
895      return true;
896  }
897  
898  void    ImGui_ImplOpenGL3_DestroyDeviceObjects()
899  {
900      ImGui_ImplOpenGL3_Data* bd = ImGui_ImplOpenGL3_GetBackendData();
901      if (bd->VboHandle)      { glDeleteBuffers(1, &bd->VboHandle); bd->VboHandle = 0; }
902      if (bd->ElementsHandle) { glDeleteBuffers(1, &bd->ElementsHandle); bd->ElementsHandle = 0; }
903      if (bd->ShaderHandle)   { glDeleteProgram(bd->ShaderHandle); bd->ShaderHandle = 0; }
904      ImGui_ImplOpenGL3_DestroyFontsTexture();
905  }
906  
907  //--------------------------------------------------------------------------------------------------------
908  // MULTI-VIEWPORT / PLATFORM INTERFACE SUPPORT
909  // This is an _advanced_ and _optional_ feature, allowing the backend to create and handle multiple viewports simultaneously.
910  // If you are new to dear imgui or creating a new binding for dear imgui, it is recommended that you completely ignore this section first..
911  //--------------------------------------------------------------------------------------------------------
912  
913  static void ImGui_ImplOpenGL3_RenderWindow(ImGuiViewport* viewport, void*)
914  {
915      if (!(viewport->Flags & ImGuiViewportFlags_NoRendererClear))
916      {
917          ImVec4 clear_color = ImVec4(0.0f, 0.0f, 0.0f, 1.0f);
918          glClearColor(clear_color.x, clear_color.y, clear_color.z, clear_color.w);
919          glClear(GL_COLOR_BUFFER_BIT);
920      }
921      ImGui_ImplOpenGL3_RenderDrawData(viewport->DrawData);
922  }
923  
924  static void ImGui_ImplOpenGL3_InitPlatformInterface()
925  {
926      ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO();
927      platform_io.Renderer_RenderWindow = ImGui_ImplOpenGL3_RenderWindow;
928  }
929  
930  static void ImGui_ImplOpenGL3_ShutdownPlatformInterface()
931  {
932      ImGui::DestroyPlatformWindows();
933  }
934  
935  #if defined(__GNUC__)
936  #pragma GCC diagnostic pop
937  #endif
938  #if defined(__clang__)
939  #pragma clang diagnostic pop
940  #endif