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