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