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