| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
|
| 9 |
|
| 10 |
|
| 11 |
|
| 12 |
|
| 13 |
|
| 14 |
|
| 15 |
|
| 16 |
|
| 17 |
|
| 18 |
|
| 19 |
|
| 20 |
|
| 21 |
|
| 22 |
|
| 23 |
|
| 24 |
|
| 25 |
|
| 26 |
|
| 27 |
|
| 28 |
|
| 29 |
|
| 30 |
|
| 31 |
|
| 32 |
|
| 33 |
|
| 34 |
|
| 35 |
|
| 36 |
|
| 37 |
|
| 38 |
|
| 39 |
|
| 40 |
|
| 41 |
|
| 42 |
|
| 43 |
|
| 44 |
|
| 45 |
|
| 46 |
|
| 47 |
|
| 48 |
|
| 49 |
|
| 50 |
|
| 51 |
|
| 52 |
|
| 53 |
|
| 54 |
|
| 55 |
|
| 56 |
|
| 57 |
|
| 58 |
|
| 59 |
|
| 60 |
|
| 61 |
|
| 62 |
|
| 63 |
|
| 64 |
|
| 65 |
|
| 66 |
|
| 67 |
|
| 68 |
|
| 69 |
|
| 70 |
|
| 71 |
|
| 72 |
|
| 73 |
|
| 74 |
|
| 75 |
|
| 76 |
|
| 77 |
|
| 78 |
|
| 79 |
|
| 80 |
|
| 81 |
|
| 82 |
|
| 83 |
|
| 84 |
|
| 85 |
|
| 86 |
|
| 87 |
|
| 88 |
|
| 89 |
|
| 90 |
|
| 91 |
|
| 92 |
|
| 93 |
|
| 94 |
|
| 95 |
|
| 96 |
|
| 97 |
|
| 98 |
|
| 99 |
|
| 100 |
|
| 101 |
|
| 102 |
|
| 103 |
|
| 104 |
|
| 105 |
|
| 106 |
|
| 107 |
|
| 108 |
|
| 109 |
|
| 110 |
|
| 111 |
|
| 112 |
|
| 113 |
|
| 114 |
|
| 115 |
|
| 116 |
|
| 117 |
|
| 118 |
|
| 119 |
|
| 120 |
|
| 121 |
|
| 122 |
|
| 123 |
|
| 124 |
|
| 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> |
| 136 |
#if defined(__APPLE__) |
| 137 |
#include <TargetConditionals.h> |
| 138 |
#endif |
| 139 |
|
| 140 |
|
| 141 |
#if defined(__clang__) |
| 142 |
#pragma clang diagnostic push |
| 143 |
#pragma clang diagnostic ignored "-Wunknown-warning-option" |
| 144 |
#pragma clang diagnostic ignored "-Wold-style-cast" |
| 145 |
#pragma clang diagnostic ignored "-Wsign-conversion" |
| 146 |
#pragma clang diagnostic ignored "-Wunused-macros" |
| 147 |
#pragma clang diagnostic ignored "-Wnonportable-system-include-path" |
| 148 |
#pragma clang diagnostic ignored "-Wcast-function-type" |
| 149 |
#endif |
| 150 |
#if defined(__GNUC__) |
| 151 |
#pragma GCC diagnostic push |
| 152 |
#pragma GCC diagnostic ignored "-Wpragmas" |
| 153 |
#pragma GCC diagnostic ignored "-Wunknown-warning-option" |
| 154 |
#pragma GCC diagnostic ignored "-Wcast-function-type" |
| 155 |
#pragma GCC diagnostic ignored "-Wstrict-overflow" |
| 156 |
#endif |
| 157 |
|
| 158 |
|
| 159 |
#if defined(IMGUI_IMPL_OPENGL_ES2) |
| 160 |
#if (defined(__APPLE__) && (TARGET_OS_IOS || TARGET_OS_TV)) |
| 161 |
#include <OpenGLES/ES2/gl.h> |
| 162 |
#else |
| 163 |
#include <GLES2/gl2.h> |
| 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> |
| 174 |
#else |
| 175 |
#include <GLES3/gl3.h> |
| 176 |
#endif |
| 177 |
#elif !defined(IMGUI_IMPL_OPENGL_LOADER_CUSTOM) |
| 178 |
|
| 179 |
|
| 180 |
|
| 181 |
|
| 182 |
|
| 183 |
|
| 184 |
|
| 185 |
|
| 186 |
#define IMGL3W_IMPL |
| 187 |
#define IMGUI_IMPL_OPENGL_LOADER_IMGL3W |
| 188 |
#include "imgui_impl_opengl3_loader.h" |
| 189 |
#endif |
| 190 |
|
| 191 |
|
| 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 |
|
| 203 |
|
| 204 |
#if !defined(IMGUI_IMPL_OPENGL_ES2) && !defined(IMGUI_IMPL_OPENGL_ES3) |
| 205 |
#define IMGUI_IMPL_OPENGL_HAS_EXTENSIONS |
| 206 |
#define IMGUI_IMPL_OPENGL_MAY_HAVE_POLYGON_MODE |
| 207 |
#endif |
| 208 |
|
| 209 |
|
| 210 |
#if !defined(IMGUI_IMPL_OPENGL_ES2) |
| 211 |
#define IMGUI_IMPL_OPENGL_MAY_HAVE_BIND_BUFFER_PIXEL_UNPACK |
| 212 |
#endif |
| 213 |
|
| 214 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 230 |
|
| 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) |
| 234 |
#else |
| 235 |
#define GL_CALL(_CALL) _CALL |
| 236 |
#endif |
| 237 |
|
| 238 |
|
| 239 |
struct ImGui_ImplOpenGL3_Data |
| 240 |
{ |
| 241 |
GLuint GlVersion; |
| 242 |
char GlslVersionString[32]; |
| 243 |
bool GlProfileIsES2; |
| 244 |
bool GlProfileIsES3; |
| 245 |
bool GlProfileIsCompat; |
| 246 |
GLint GlProfileMask; |
| 247 |
GLint MaxTextureSize; |
| 248 |
GLuint ShaderHandle; |
| 249 |
GLint AttribLocationTex; |
| 250 |
GLint AttribLocationProjMtx; |
| 251 |
GLuint AttribLocationVtxPos; |
| 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]; |
| 263 |
#endif |
| 264 |
|
| 265 |
ImVector<char> TempBuffer; |
| 266 |
|
| 267 |
ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); } |
| 268 |
}; |
| 269 |
|
| 270 |
|
| 271 |
|
| 272 |
static ImGui_ImplOpenGL3_Data* ImGui_ImplOpenGL3_GetBackendData() |
| 273 |
{ |
| 274 |
return ImGui::GetCurrentContext() ? (ImGui_ImplOpenGL3_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; |
| 275 |
} |
| 276 |
|
| 277 |
|
| 278 |
static void ImGui_ImplOpenGL3_InitMultiViewportSupport(); |
| 279 |
static void ImGui_ImplOpenGL3_ShutdownMultiViewportSupport(); |
| 280 |
|
| 281 |
|
| 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 |
|
| 306 |
bool ImGui_ImplOpenGL3_InitLoader(); |
| 307 |
bool ImGui_ImplOpenGL3_InitLoader() |
| 308 |
{ |
| 309 |
|
| 310 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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*)¤t_clip_origin); |
| 367 |
if (current_clip_origin == GL_UPPER_LEFT) |
| 368 |
clip_origin_lower_left = false; |
| 369 |
} |
| 370 |
#endif |
| 371 |
|
| 372 |
|
| 373 |
|
| 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; } |
| 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); |
| 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 |
|
| 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 |
|
| 418 |
static void ImGui_ImplOpenGL3_DrawCallback_ResetRenderState(const ImDrawList*, const ImDrawCmd*) {} |
| 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 |
|
| 457 |
|
| 458 |
|
| 459 |
void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) |
| 460 |
{ |
| 461 |
|
| 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 |
|
| 472 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 518 |
|
| 519 |
|
| 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 |
|
| 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 |
|
| 537 |
ImVec2 clip_off = draw_data->DisplayPos; |
| 538 |
ImVec2 clip_scale = draw_data->FramebufferScale; |
| 539 |
|
| 540 |
|
| 541 |
for (const ImDrawList* draw_list : draw_data->CmdLists) |
| 542 |
{ |
| 543 |
|
| 544 |
|
| 545 |
|
| 546 |
|
| 547 |
|
| 548 |
|
| 549 |
|
| 550 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 597 |
GL_CALL(glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->GetTexID())); |
| 598 |
|
| 599 |
|
| 600 |
|
| 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 |
|
| 619 |
#ifdef IMGUI_IMPL_OPENGL_USE_VERTEX_ARRAY |
| 620 |
GL_CALL(glDeleteVertexArrays(1, &vertex_array_object)); |
| 621 |
#endif |
| 622 |
|
| 623 |
|
| 624 |
|
| 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 |
|
| 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 |
| 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; |
| 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 |
|
| 669 |
tex->SetTexID(ImTextureID_Invalid); |
| 670 |
tex->SetStatus(ImTextureStatus_Destroyed); |
| 671 |
} |
| 672 |
|
| 673 |
void ImGui_ImplOpenGL3_UpdateTexture(ImTextureData* tex) |
| 674 |
{ |
| 675 |
|
| 676 |
if (tex->Status == ImTextureStatus_WantCreate || tex->Status == ImTextureStatus_WantUpdates) |
| 677 |
{ |
| 678 |
#ifdef GL_UNPACK_ROW_LENGTH |
| 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 |
|
| 689 |
|
| 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 |
|
| 696 |
|
| 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 |
|
| 708 |
tex->SetTexID((ImTextureID)(intptr_t)gl_texture_id); |
| 709 |
tex->SetStatus(ImTextureStatus_OK); |
| 710 |
|
| 711 |
|
| 712 |
GL_CALL(glBindTexture(GL_TEXTURE_2D, last_texture)); |
| 713 |
} |
| 714 |
else if (tex->Status == ImTextureStatus_WantUpdates) |
| 715 |
{ |
| 716 |
|
| 717 |
|
| 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 |
| 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 |
|
| 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)); |
| 744 |
} |
| 745 |
else if (tex->Status == ImTextureStatus_WantDestroy && tex->UnusedFrames > 0) |
| 746 |
ImGui_ImplOpenGL3_DestroyTexture(tex); |
| 747 |
} |
| 748 |
|
| 749 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 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 |
|
| 1024 |
if (!ImGui_ImplOpenGL3_InitLoader()) |
| 1025 |
return false; |
| 1026 |
|
| 1027 |
|
| 1028 |
ImGui_ImplOpenGL3_Data* bd = IM_NEW(ImGui_ImplOpenGL3_Data)(); |
| 1029 |
io.BackendRendererUserData = (void*)bd; |
| 1030 |
io.BackendRendererName = "imgui_impl_opengl3"; |
| 1031 |
|
| 1032 |
|
| 1033 |
const char* gl_version_str = (const char*)glGetString(GL_VERSION); |
| 1034 |
#if defined(IMGUI_IMPL_OPENGL_ES2) |
| 1035 |
|
| 1036 |
bd->GlVersion = 200; |
| 1037 |
bd->GlProfileIsES2 = true; |
| 1038 |
IM_UNUSED(gl_version_str); |
| 1039 |
#else |
| 1040 |
|
| 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); |
| 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 |
|
| 1066 |
|
| 1067 |
|
| 1068 |
|
| 1069 |
|
| 1070 |
|
| 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)); |
| 1076 |
#endif |
| 1077 |
|
| 1078 |
#ifdef IMGUI_IMPL_OPENGL_MAY_HAVE_VTX_OFFSET |
| 1079 |
if (bd->GlVersion >= 320) |
| 1080 |
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; |
| 1081 |
#endif |
| 1082 |
io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; |
| 1083 |
io.BackendFlags |= ImGuiBackendFlags_RendererHasViewports; |
| 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 |
|
| 1092 |
|
| 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 |
|
| 1113 |
|
| 1114 |
GLint current_texture; |
| 1115 |
glGetIntegerv(GL_TEXTURE_BINDING_2D, ¤t_texture); |
| 1116 |
|
| 1117 |
|
| 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 |
|
| 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 |
|
| 1163 |
|
| 1164 |
|
| 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 |