blob: d2539d077522de5a98e88a0d395568a6d496b9bb [file] [log] [blame]
Anthony Barbier7068f992017-10-26 15:23:08 +01001/*
2 * Copyright (c) 2017 ARM Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#include "arm_compute/core/GLES_COMPUTE/OpenGLES.h"
26
27#include <dlfcn.h>
28#include <iostream>
29#include <vector>
30
31using eglGetProcAddress_func = __eglMustCastToProperFunctionPointerType EGLAPIENTRY (*)(const char *procname);
32using eglBindAPI_func = EGLBoolean EGLAPIENTRY (*)(EGLenum api);
33using eglChooseConfig_func = EGLBoolean EGLAPIENTRY (*)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
34using eglCreateContext_func = EGLContext EGLAPIENTRY (*)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
35using eglDestroyContext_func = EGLBoolean EGLAPIENTRY (*)(EGLDisplay dpy, EGLContext ctx);
36using eglGetDisplay_func = EGLDisplay EGLAPIENTRY (*)(EGLNativeDisplayType display_id);
37using eglInitialize_func = EGLBoolean EGLAPIENTRY (*)(EGLDisplay dpy, EGLint *major, EGLint *minor);
38using eglMakeCurrent_func = EGLBoolean EGLAPIENTRY (*)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
39using eglTerminate_func = EGLBoolean EGLAPIENTRY (*)(EGLDisplay dpy);
40using eglGetError_func = EGLint EGLAPIENTRY (*)();
41using eglQueryString_func = char const * EGLAPIENTRY (*)(EGLDisplay dpy, EGLint name);
42using glAttachShader_func = void GL_APIENTRY (*)(GLuint program, GLuint shader);
43using glCompileShader_func = void GL_APIENTRY (*)(GLuint shader);
44using glCreateProgram_func = GLuint GL_APIENTRY (*)();
45using glCreateShader_func = GLuint GL_APIENTRY (*)(GLenum type);
46using glDeleteProgram_func = void GL_APIENTRY (*)(GLuint program);
47using glDeleteShader_func = void GL_APIENTRY (*)(GLuint shader);
48using glDetachShader_func = void GL_APIENTRY (*)(GLuint program, GLuint shader);
49using glGetProgramInfoLog_func = void GL_APIENTRY (*)(GLuint program, GLsizei bufsize, GLsizei *length, GLchar *infolog);
50using glGetProgramiv_func = void GL_APIENTRY (*)(GLuint program, GLenum pname, GLint *params);
51using glGetShaderInfoLog_func = void GL_APIENTRY (*)(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *infolog);
52using glGetShaderiv_func = void GL_APIENTRY (*)(GLuint shader, GLenum pname, GLint *params);
53using glLinkProgram_func = void GL_APIENTRY (*)(GLuint program);
54using glShaderSource_func = void GL_APIENTRY (*)(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length);
55using glUseProgram_func = void GL_APIENTRY (*)(GLuint program);
56using glBindBuffer_func = void GL_APIENTRY (*)(GLenum target, GLuint buffer);
57using glBindBufferBase_func = void GL_APIENTRY (*)(GLenum target, GLuint index, GLuint buffer);
58using glBufferData_func = void GL_APIENTRY (*)(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage);
59using glDeleteBuffers_func = void GL_APIENTRY (*)(GLsizei n, const GLuint *buffers);
60using glDispatchCompute_func = void GL_APIENTRY (*)(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z);
61using glFlush_func = void GL_APIENTRY (*)();
62using glGenBuffers_func = void GL_APIENTRY (*)(GLsizei n, GLuint *buffers);
63using glGetProgramResourceIndex_func = GLuint GL_APIENTRY (*)(GLuint program, GLenum programInterface, const GLchar *name);
64using glGetUniformLocation_func = GLint GL_APIENTRY (*)(GLuint program, const GLchar *name);
65using glMapBufferRange_func = void *GL_APIENTRY (*)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
66using glMemoryBarrier_func = void GL_APIENTRY (*)(GLbitfield barriers);
67using glUniform1ui_func = void GL_APIENTRY (*)(GLint location, GLuint v0);
68using glUnmapBuffer_func = GLboolean GL_APIENTRY (*)(GLenum target);
69using glGetError_func = GLenum GL_APIENTRY (*)();
70using glGetActiveUniformBlockiv_func = void GL_APIENTRY (*)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params);
71using glUniformBlockBinding_func = void GL_APIENTRY (*)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
72using glGetUniformBlockIndex_func = GLuint GL_APIENTRY (*)(GLuint program, const GLchar *uniformBlockName);
73using glGenTextures_func = void GL_APIENTRY (*)(GLsizei n, GLuint *textures);
74using glDeleteTextures_func = void GL_APIENTRY (*)(GLsizei n, const GLuint *textures);
75using glBindTexture_func = void GL_APIENTRY (*)(GLenum target, GLuint texture);
76using glTexImage2D_func = void GL_APIENTRY (*)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type,
77 const GLvoid *pixels);
78using glGenFramebuffers_func = void GL_APIENTRY (*)(GLsizei n, GLuint *framebuffers);
79using glDeleteFramebuffers_func = void GL_APIENTRY (*)(GLsizei n, const GLuint *framebuffers);
80using glBindFramebuffer_func = void GL_APIENTRY (*)(GLenum target, GLuint framebuffer);
81using glFramebufferTexture2D_func = void GL_APIENTRY (*)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
82
83class GLESSymbols
84{
85private:
86 void init()
87 {
88 void *egl_handle = dlopen("libEGL.so", RTLD_LAZY | RTLD_LOCAL);
89 void *glesv2_handle = dlopen("libGLESv2.so", RTLD_LAZY | RTLD_LOCAL);
90 void *glesv3_handle = dlopen("libGLESv3.so", RTLD_LAZY | RTLD_LOCAL);
91 if(egl_handle == nullptr)
92 {
93 std::cerr << "Can't load libEGL.so: " << dlerror() << std::endl;
94 }
95 else
96 {
97#undef EGL_ENTRY
98#define EGL_ENTRY(_api) _api = reinterpret_cast<_api##_func>(dlsym(egl_handle, #_api));
99#include "./egl_entries.in"
100#undef EGL_ENTRY
101
102 if(eglGetProcAddress != nullptr)
103 {
104#undef EGL_ENTRY
105#define EGL_ENTRY(_api) \
106 if((_api) == nullptr) \
107 (_api) = reinterpret_cast<_api##_func>(eglGetProcAddress(#_api));
108#include "./egl_entries.in"
109#undef EGL_ENTRY
110
111#undef GL_ENTRY
112#define GL_ENTRY(_api) _api = reinterpret_cast<_api##_func>(eglGetProcAddress(#_api));
113#include "./gl_entries.in"
114#undef GL_ENTRY
115 }
116
117 std::vector<void *> handles = { glesv3_handle, glesv2_handle };
118 for(auto &handle : handles)
119 {
120 if(handle != nullptr)
121 {
122#undef GL_ENTRY
123#define GL_ENTRY(_api) \
124 if((_api) == nullptr) \
125 (_api) = reinterpret_cast<_api##_func>(dlsym(handle, #_api));
126#include "./gl_entries.in"
127#undef GL_ENTRY
128 }
129 }
130
Anthony Barbier7b43d312017-12-14 10:58:47 +0000131 //Don't call dlclose(handle) or all the symbols will be unloaded !
Anthony Barbier7068f992017-10-26 15:23:08 +0100132 }
133 }
134 bool _initialized = false;
135
136public:
137 static GLESSymbols &get()
138 {
139 static GLESSymbols symbols = GLESSymbols();
140 if(!symbols._initialized)
141 {
142 symbols._initialized = true;
143 symbols.init();
144 }
145
146 return symbols;
147 }
148
149#undef EGL_ENTRY
150#undef GL_ENTRY
151#define EGL_ENTRY(_api) _api##_func _api = nullptr;
152#define GL_ENTRY(_api) EGL_ENTRY(_api)
153#include "./egl_entries.in"
154#include "./gl_entries.in"
155#undef EGL_ENTRY
156#undef GL_ENTRY
157};
158
159bool arm_compute::opengles31_is_available()
160{
161 return GLESSymbols::get().glDispatchCompute != nullptr;
162}
163
164__eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname)
165{
166 auto func = GLESSymbols::get().eglGetProcAddress;
167 if(func != nullptr)
168 {
169 return func(procname);
170 }
171 else
172 {
173 return nullptr;
174 }
175}
176
177EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api)
178{
179 auto func = GLESSymbols::get().eglBindAPI;
180 if(func != nullptr)
181 {
182 return func(api);
183 }
184 else
185 {
186 return EGL_FALSE;
187 }
188}
189
190EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
191{
192 auto func = GLESSymbols::get().eglChooseConfig;
193 if(func != nullptr)
194 {
195 return func(dpy, attrib_list, configs, config_size, num_config);
196 }
197 else
198 {
199 return EGL_FALSE;
200 }
201}
202
203EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
204{
205 auto func = GLESSymbols::get().eglCreateContext;
206 if(func != nullptr)
207 {
208 return func(dpy, config, share_context, attrib_list);
209 }
210 else
211 {
212 return nullptr;
213 }
214}
215
216EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
217{
218 auto func = GLESSymbols::get().eglDestroyContext;
219 if(func != nullptr)
220 {
221 return func(dpy, ctx);
222 }
223 else
224 {
225 return EGL_FALSE;
226 }
227}
228
229EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id)
230{
231 auto func = GLESSymbols::get().eglGetDisplay;
232 if(func != nullptr)
233 {
234 return func(display_id);
235 }
236 else
237 {
238 return nullptr;
239 }
240}
241
242EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
243{
244 auto func = GLESSymbols::get().eglInitialize;
245 if(func != nullptr)
246 {
247 return func(dpy, major, minor);
248 }
249 else
250 {
251 return EGL_FALSE;
252 }
253}
254
255EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
256{
257 auto func = GLESSymbols::get().eglMakeCurrent;
258 if(func != nullptr)
259 {
260 return func(dpy, draw, read, ctx);
261 }
262 else
263 {
264 return EGL_FALSE;
265 }
266}
267
268EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy)
269{
270 auto func = GLESSymbols::get().eglTerminate;
271 if(func != nullptr)
272 {
273 return func(dpy);
274 }
275 else
276 {
277 return EGL_FALSE;
278 }
279}
280
281EGLint EGLAPIENTRY eglGetError()
282{
283 auto func = GLESSymbols::get().eglGetError;
284 if(func != nullptr)
285 {
286 return func();
287 }
288 else
289 {
290 return GL_NO_ERROR;
291 }
292}
293
294char const *EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name)
295{
296 auto func = GLESSymbols::get().eglQueryString;
297 if(func != nullptr)
298 {
299 return func(dpy, name);
300 }
301 else
302 {
303 return nullptr;
304 }
305}
306
307void GL_APIENTRY glAttachShader(GLuint program, GLuint shader)
308{
309 auto func = GLESSymbols::get().glAttachShader;
310 if(func != nullptr)
311 {
312 return func(program, shader);
313 }
314 else
315 {
316 return;
317 }
318}
319
320void GL_APIENTRY glCompileShader(GLuint shader)
321{
322 auto func = GLESSymbols::get().glCompileShader;
323 if(func != nullptr)
324 {
325 return func(shader);
326 }
327 else
328 {
329 return;
330 }
331}
332
333GLuint GL_APIENTRY glCreateProgram()
334{
335 auto func = GLESSymbols::get().glCreateProgram;
336 if(func != nullptr)
337 {
338 return func();
339 }
340 else
341 {
342 return 0;
343 }
344}
345
346GLuint GL_APIENTRY glCreateShader(GLenum type)
347{
348 auto func = GLESSymbols::get().glCreateShader;
349 if(func != nullptr)
350 {
351 return func(type);
352 }
353 else
354 {
355 return 0;
356 }
357}
358
359void GL_APIENTRY glDeleteProgram(GLuint program)
360{
361 auto func = GLESSymbols::get().glDeleteProgram;
362 if(func != nullptr)
363 {
364 return func(program);
365 }
366 else
367 {
368 return;
369 }
370}
371
372void GL_APIENTRY glDeleteShader(GLuint shader)
373{
374 auto func = GLESSymbols::get().glDeleteShader;
375 if(func != nullptr)
376 {
377 return func(shader);
378 }
379 else
380 {
381 return;
382 }
383}
384
385void GL_APIENTRY glDetachShader(GLuint program, GLuint shader)
386{
387 auto func = GLESSymbols::get().glDetachShader;
388 if(func != nullptr)
389 {
390 return func(program, shader);
391 }
392 else
393 {
394 return;
395 }
396}
397
398void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
399{
400 auto func = GLESSymbols::get().glGetProgramInfoLog;
401 if(func != nullptr)
402 {
403 return func(program, bufSize, length, infoLog);
404 }
405 else
406 {
407 return;
408 }
409}
410
411void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint *params)
412{
413 auto func = GLESSymbols::get().glGetProgramiv;
414 if(func != nullptr)
415 {
416 return func(program, pname, params);
417 }
418 else
419 {
420 return;
421 }
422}
423
424void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog)
425{
426 auto func = GLESSymbols::get().glGetShaderInfoLog;
427 if(func != nullptr)
428 {
429 return func(shader, bufSize, length, infoLog);
430 }
431 else
432 {
433 return;
434 }
435}
436
437void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint *params)
438{
439 auto func = GLESSymbols::get().glGetShaderiv;
440 if(func != nullptr)
441 {
442 return func(shader, pname, params);
443 }
444 else
445 {
446 return;
447 }
448}
449
450void GL_APIENTRY glLinkProgram(GLuint program)
451{
452 auto func = GLESSymbols::get().glLinkProgram;
453 if(func != nullptr)
454 {
455 return func(program);
456 }
457 else
458 {
459 return;
460 }
461}
462
463void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length)
464{
465 auto func = GLESSymbols::get().glShaderSource;
466 if(func != nullptr)
467 {
468 return func(shader, count, string, length);
469 }
470 else
471 {
472 return;
473 }
474}
475
476void GL_APIENTRY glUseProgram(GLuint program)
477{
478 auto func = GLESSymbols::get().glUseProgram;
479 if(func != nullptr)
480 {
481 return func(program);
482 }
483 else
484 {
485 return;
486 }
487}
488
489void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer)
490{
491 auto func = GLESSymbols::get().glBindBuffer;
492 if(func != nullptr)
493 {
494 return func(target, buffer);
495 }
496 else
497 {
498 return;
499 }
500}
501
502void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
503{
504 auto func = GLESSymbols::get().glBindBufferBase;
505 if(func != nullptr)
506 {
507 return func(target, index, buffer);
508 }
509 else
510 {
511 return;
512 }
513}
514
515void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage)
516{
517 auto func = GLESSymbols::get().glBufferData;
518 if(func != nullptr)
519 {
520 return func(target, size, data, usage);
521 }
522 else
523 {
524 return;
525 }
526}
527
528void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint *buffers)
529{
530 auto func = GLESSymbols::get().glDeleteBuffers;
531 if(func != nullptr)
532 {
533 return func(n, buffers);
534 }
535 else
536 {
537 return;
538 }
539}
540
541void GL_APIENTRY glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z)
542{
543 auto func = GLESSymbols::get().glDispatchCompute;
544 if(func != nullptr)
545 {
546 return func(num_groups_x, num_groups_y, num_groups_z);
547 }
548 else
549 {
550 return;
551 }
552}
553
554void GL_APIENTRY glFlush(void)
555{
556 auto func = GLESSymbols::get().glFlush;
557 if(func != nullptr)
558 {
559 return func();
560 }
561 else
562 {
563 return;
564 }
565}
566
567void GL_APIENTRY glGenBuffers(GLsizei n, GLuint *buffers)
568{
569 auto func = GLESSymbols::get().glGenBuffers;
570 if(func != nullptr)
571 {
572 return func(n, buffers);
573 }
574 else
575 {
576 return;
577 }
578}
579
580GLuint GL_APIENTRY glGetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar *name)
581{
582 auto func = GLESSymbols::get().glGetProgramResourceIndex;
583 if(func != nullptr)
584 {
585 return func(program, programInterface, name);
586 }
587 else
588 {
589 return GL_INVALID_INDEX;
590 }
591}
592
593GLint GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar *name)
594{
595 auto func = GLESSymbols::get().glGetUniformLocation;
596 if(func != nullptr)
597 {
598 return func(program, name);
599 }
600 else
601 {
602 return -1;
603 }
604}
605
606void *GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
607{
608 auto func = GLESSymbols::get().glMapBufferRange;
609 if(func != nullptr)
610 {
611 return func(target, offset, length, access);
612 }
613 else
614 {
615 return nullptr;
616 }
617}
618
619void GL_APIENTRY glMemoryBarrier(GLbitfield barriers)
620{
621 auto func = GLESSymbols::get().glMemoryBarrier;
622 if(func != nullptr)
623 {
624 return func(barriers);
625 }
626 else
627 {
628 return;
629 }
630}
631
632void GL_APIENTRY glUniform1ui(GLint location, GLuint v0)
633{
634 auto func = GLESSymbols::get().glUniform1ui;
635 if(func != nullptr)
636 {
637 return func(location, v0);
638 }
639 else
640 {
641 return;
642 }
643}
644
645GLboolean GL_APIENTRY glUnmapBuffer(GLenum target)
646{
647 auto func = GLESSymbols::get().glUnmapBuffer;
648 if(func != nullptr)
649 {
650 return func(target);
651 }
652 else
653 {
654 return GL_FALSE;
655 }
656}
657
658GLenum GL_APIENTRY glGetError(void)
659{
660 auto func = GLESSymbols::get().glGetError;
661 if(func != nullptr)
662 {
663 return func();
664 }
665 else
666 {
667 return GL_NO_ERROR;
668 }
669}
670
671void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params)
672{
673 auto func = GLESSymbols::get().glGetActiveUniformBlockiv;
674 if(func != nullptr)
675 {
676 return func(program, uniformBlockIndex, pname, params);
677 }
678 else
679 {
680 return;
681 }
682}
683
684void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
685{
686 auto func = GLESSymbols::get().glUniformBlockBinding;
687 if(func != nullptr)
688 {
689 return func(program, uniformBlockIndex, uniformBlockBinding);
690 }
691 else
692 {
693 return;
694 }
695}
696
697GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName)
698{
699 auto func = GLESSymbols::get().glGetUniformBlockIndex;
700 if(func != nullptr)
701 {
702 return func(program, uniformBlockName);
703 }
704 else
705 {
706 return GL_INVALID_INDEX;
707 }
708}
709
710void GL_APIENTRY glGenTextures(GLsizei n, GLuint *textures)
711{
712 auto func = GLESSymbols::get().glGenTextures;
713 if(func != nullptr)
714 {
715 return func(n, textures);
716 }
717 else
718 {
719 return;
720 }
721}
722
723void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint *textures)
724{
725 auto func = GLESSymbols::get().glDeleteTextures;
726 if(func != nullptr)
727 {
728 return func(n, textures);
729 }
730 else
731 {
732 return;
733 }
734}
735
736void GL_APIENTRY glBindTexture(GLenum target, GLuint texture)
737{
738 auto func = GLESSymbols::get().glBindTexture;
739 if(func != nullptr)
740 {
741 return func(target, texture);
742 }
743 else
744 {
745 return;
746 }
747}
748
749void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
750{
751 auto func = GLESSymbols::get().glTexImage2D;
752 if(func != nullptr)
753 {
754 return func(target, level, internalformat, width, height, border, format, type, pixels);
755 }
756 else
757 {
758 return;
759 }
760}
761
762void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint *framebuffers)
763{
764 auto func = GLESSymbols::get().glGenFramebuffers;
765 if(func != nullptr)
766 {
767 return func(n, framebuffers);
768 }
769 else
770 {
771 return;
772 }
773}
774
775void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
776{
777 auto func = GLESSymbols::get().glDeleteFramebuffers;
778 if(func != nullptr)
779 {
780 return func(n, framebuffers);
781 }
782 else
783 {
784 return;
785 }
786}
787
788void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer)
789{
790 auto func = GLESSymbols::get().glBindFramebuffer;
791 if(func != nullptr)
792 {
793 return func(target, framebuffer);
794 }
795 else
796 {
797 return;
798 }
799}
800
801void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
802{
803 auto func = GLESSymbols::get().glFramebufferTexture2D;
804 if(func != nullptr)
805 {
806 return func(target, attachment, textarget, texture, level);
807 }
808 else
809 {
810 return;
811 }
812}