/* * Copyright (c) 2017-2018 ARM Limited. * * SPDX-License-Identifier: MIT * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ #include "arm_compute/core/GLES_COMPUTE/OpenGLES.h" #include #include #include using eglGetProcAddress_func = __eglMustCastToProperFunctionPointerType EGLAPIENTRY (*)(const char *procname); using eglBindAPI_func = EGLBoolean EGLAPIENTRY (*)(EGLenum api); using eglChooseConfig_func = EGLBoolean EGLAPIENTRY (*)(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config); using eglCreateContext_func = EGLContext EGLAPIENTRY (*)(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list); using eglDestroyContext_func = EGLBoolean EGLAPIENTRY (*)(EGLDisplay dpy, EGLContext ctx); using eglGetDisplay_func = EGLDisplay EGLAPIENTRY (*)(EGLNativeDisplayType display_id); using eglInitialize_func = EGLBoolean EGLAPIENTRY (*)(EGLDisplay dpy, EGLint *major, EGLint *minor); using eglMakeCurrent_func = EGLBoolean EGLAPIENTRY (*)(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx); using eglTerminate_func = EGLBoolean EGLAPIENTRY (*)(EGLDisplay dpy); using eglGetError_func = EGLint EGLAPIENTRY (*)(); using eglQueryString_func = char const * EGLAPIENTRY (*)(EGLDisplay dpy, EGLint name); using glAttachShader_func = void GL_APIENTRY (*)(GLuint program, GLuint shader); using glCompileShader_func = void GL_APIENTRY (*)(GLuint shader); using glCreateProgram_func = GLuint GL_APIENTRY (*)(); using glCreateShader_func = GLuint GL_APIENTRY (*)(GLenum type); using glDeleteProgram_func = void GL_APIENTRY (*)(GLuint program); using glDeleteShader_func = void GL_APIENTRY (*)(GLuint shader); using glDetachShader_func = void GL_APIENTRY (*)(GLuint program, GLuint shader); using glGetProgramInfoLog_func = void GL_APIENTRY (*)(GLuint program, GLsizei bufsize, GLsizei *length, GLchar *infolog); using glGetProgramiv_func = void GL_APIENTRY (*)(GLuint program, GLenum pname, GLint *params); using glGetShaderInfoLog_func = void GL_APIENTRY (*)(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *infolog); using glGetShaderiv_func = void GL_APIENTRY (*)(GLuint shader, GLenum pname, GLint *params); using glLinkProgram_func = void GL_APIENTRY (*)(GLuint program); using glShaderSource_func = void GL_APIENTRY (*)(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length); using glUseProgram_func = void GL_APIENTRY (*)(GLuint program); using glBindBuffer_func = void GL_APIENTRY (*)(GLenum target, GLuint buffer); using glBindBufferBase_func = void GL_APIENTRY (*)(GLenum target, GLuint index, GLuint buffer); using glBufferData_func = void GL_APIENTRY (*)(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage); using glDeleteBuffers_func = void GL_APIENTRY (*)(GLsizei n, const GLuint *buffers); using glDispatchCompute_func = void GL_APIENTRY (*)(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z); using glFlush_func = void GL_APIENTRY (*)(); using glGenBuffers_func = void GL_APIENTRY (*)(GLsizei n, GLuint *buffers); using glGetProgramResourceIndex_func = GLuint GL_APIENTRY (*)(GLuint program, GLenum programInterface, const GLchar *name); using glGetUniformLocation_func = GLint GL_APIENTRY (*)(GLuint program, const GLchar *name); using glMapBufferRange_func = void *GL_APIENTRY (*)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access); using glMemoryBarrier_func = void GL_APIENTRY (*)(GLbitfield barriers); using glUniform1ui_func = void GL_APIENTRY (*)(GLint location, GLuint v0); using glUnmapBuffer_func = GLboolean GL_APIENTRY (*)(GLenum target); using glGetError_func = GLenum GL_APIENTRY (*)(); using glGetString_func = const GLubyte * GL_APIENTRY (*)(GLenum name); using glGetActiveUniformBlockiv_func = void GL_APIENTRY (*)(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params); using glUniformBlockBinding_func = void GL_APIENTRY (*)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding); using glGetUniformBlockIndex_func = GLuint GL_APIENTRY (*)(GLuint program, const GLchar *uniformBlockName); using glGenTextures_func = void GL_APIENTRY (*)(GLsizei n, GLuint *textures); using glDeleteTextures_func = void GL_APIENTRY (*)(GLsizei n, const GLuint *textures); using glBindTexture_func = void GL_APIENTRY (*)(GLenum target, GLuint texture); using glTexImage2D_func = void GL_APIENTRY (*)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels); using glGenFramebuffers_func = void GL_APIENTRY (*)(GLsizei n, GLuint *framebuffers); using glDeleteFramebuffers_func = void GL_APIENTRY (*)(GLsizei n, const GLuint *framebuffers); using glBindFramebuffer_func = void GL_APIENTRY (*)(GLenum target, GLuint framebuffer); using glFramebufferTexture2D_func = void GL_APIENTRY (*)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level); class GLESSymbols { private: void init() { void *egl_handle = dlopen("libEGL.so", RTLD_LAZY | RTLD_LOCAL); void *glesv2_handle = dlopen("libGLESv2.so", RTLD_LAZY | RTLD_LOCAL); void *glesv3_handle = dlopen("libGLESv3.so", RTLD_LAZY | RTLD_LOCAL); if(egl_handle == nullptr) { std::cerr << "Can't load libEGL.so: " << dlerror() << std::endl; } else { #undef EGL_ENTRY #define EGL_ENTRY(_api) _api = reinterpret_cast<_api##_func>(dlsym(egl_handle, #_api)); #include "./egl_entries.in" #undef EGL_ENTRY if(eglGetProcAddress != nullptr) { #undef EGL_ENTRY #define EGL_ENTRY(_api) \ if((_api) == nullptr) \ (_api) = reinterpret_cast<_api##_func>(eglGetProcAddress(#_api)); #include "./egl_entries.in" #undef EGL_ENTRY #undef GL_ENTRY #define GL_ENTRY(_api) _api = reinterpret_cast<_api##_func>(eglGetProcAddress(#_api)); #include "./gl_entries.in" #undef GL_ENTRY } std::vector handles = { glesv3_handle, glesv2_handle }; for(auto &handle : handles) { if(handle != nullptr) { #undef GL_ENTRY #define GL_ENTRY(_api) \ if((_api) == nullptr) \ (_api) = reinterpret_cast<_api##_func>(dlsym(handle, #_api)); #include "./gl_entries.in" #undef GL_ENTRY } } //Don't call dlclose(handle) or all the symbols will be unloaded ! } } bool _initialized = false; public: static GLESSymbols &get() { static GLESSymbols symbols = GLESSymbols(); if(!symbols._initialized) { symbols._initialized = true; symbols.init(); } return symbols; } #undef EGL_ENTRY #undef GL_ENTRY #define EGL_ENTRY(_api) _api##_func _api = nullptr; #define GL_ENTRY(_api) EGL_ENTRY(_api) #include "./egl_entries.in" #include "./gl_entries.in" #undef EGL_ENTRY #undef GL_ENTRY }; bool arm_compute::opengles31_is_available() { return GLESSymbols::get().glDispatchCompute != nullptr; } __eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname) { auto func = GLESSymbols::get().eglGetProcAddress; if(func != nullptr) { return func(procname); } else { return nullptr; } } EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api) { auto func = GLESSymbols::get().eglBindAPI; if(func != nullptr) { return func(api); } else { return EGL_FALSE; } } EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) { auto func = GLESSymbols::get().eglChooseConfig; if(func != nullptr) { return func(dpy, attrib_list, configs, config_size, num_config); } else { return EGL_FALSE; } } EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list) { auto func = GLESSymbols::get().eglCreateContext; if(func != nullptr) { return func(dpy, config, share_context, attrib_list); } else { return nullptr; } } EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { auto func = GLESSymbols::get().eglDestroyContext; if(func != nullptr) { return func(dpy, ctx); } else { return EGL_FALSE; } } EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id) { auto func = GLESSymbols::get().eglGetDisplay; if(func != nullptr) { return func(display_id); } else { return nullptr; } } EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { auto func = GLESSymbols::get().eglInitialize; if(func != nullptr) { return func(dpy, major, minor); } else { return EGL_FALSE; } } EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { auto func = GLESSymbols::get().eglMakeCurrent; if(func != nullptr) { return func(dpy, draw, read, ctx); } else { return EGL_FALSE; } } EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy) { auto func = GLESSymbols::get().eglTerminate; if(func != nullptr) { return func(dpy); } else { return EGL_FALSE; } } EGLint EGLAPIENTRY eglGetError() { auto func = GLESSymbols::get().eglGetError; if(func != nullptr) { return func(); } else { return GL_NO_ERROR; } } char const *EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name) { auto func = GLESSymbols::get().eglQueryString; if(func != nullptr) { return func(dpy, name); } else { return nullptr; } } void GL_APIENTRY glAttachShader(GLuint program, GLuint shader) { auto func = GLESSymbols::get().glAttachShader; if(func != nullptr) { return func(program, shader); } else { return; } } void GL_APIENTRY glCompileShader(GLuint shader) { auto func = GLESSymbols::get().glCompileShader; if(func != nullptr) { return func(shader); } else { return; } } GLuint GL_APIENTRY glCreateProgram() { auto func = GLESSymbols::get().glCreateProgram; if(func != nullptr) { return func(); } else { return 0; } } GLuint GL_APIENTRY glCreateShader(GLenum type) { auto func = GLESSymbols::get().glCreateShader; if(func != nullptr) { return func(type); } else { return 0; } } void GL_APIENTRY glDeleteProgram(GLuint program) { auto func = GLESSymbols::get().glDeleteProgram; if(func != nullptr) { return func(program); } else { return; } } void GL_APIENTRY glDeleteShader(GLuint shader) { auto func = GLESSymbols::get().glDeleteShader; if(func != nullptr) { return func(shader); } else { return; } } void GL_APIENTRY glDetachShader(GLuint program, GLuint shader) { auto func = GLESSymbols::get().glDetachShader; if(func != nullptr) { return func(program, shader); } else { return; } } void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { auto func = GLESSymbols::get().glGetProgramInfoLog; if(func != nullptr) { return func(program, bufSize, length, infoLog); } else { return; } } void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint *params) { auto func = GLESSymbols::get().glGetProgramiv; if(func != nullptr) { return func(program, pname, params); } else { return; } } void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) { auto func = GLESSymbols::get().glGetShaderInfoLog; if(func != nullptr) { return func(shader, bufSize, length, infoLog); } else { return; } } void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint *params) { auto func = GLESSymbols::get().glGetShaderiv; if(func != nullptr) { return func(shader, pname, params); } else { return; } } void GL_APIENTRY glLinkProgram(GLuint program) { auto func = GLESSymbols::get().glLinkProgram; if(func != nullptr) { return func(program); } else { return; } } void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar *const *string, const GLint *length) { auto func = GLESSymbols::get().glShaderSource; if(func != nullptr) { return func(shader, count, string, length); } else { return; } } void GL_APIENTRY glUseProgram(GLuint program) { auto func = GLESSymbols::get().glUseProgram; if(func != nullptr) { return func(program); } else { return; } } void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer) { auto func = GLESSymbols::get().glBindBuffer; if(func != nullptr) { return func(target, buffer); } else { return; } } void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer) { auto func = GLESSymbols::get().glBindBufferBase; if(func != nullptr) { return func(target, index, buffer); } else { return; } } void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid *data, GLenum usage) { auto func = GLESSymbols::get().glBufferData; if(func != nullptr) { return func(target, size, data, usage); } else { return; } } void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint *buffers) { auto func = GLESSymbols::get().glDeleteBuffers; if(func != nullptr) { return func(n, buffers); } else { return; } } void GL_APIENTRY glDispatchCompute(GLuint num_groups_x, GLuint num_groups_y, GLuint num_groups_z) { auto func = GLESSymbols::get().glDispatchCompute; if(func != nullptr) { return func(num_groups_x, num_groups_y, num_groups_z); } else { return; } } void GL_APIENTRY glFlush(void) { auto func = GLESSymbols::get().glFlush; if(func != nullptr) { return func(); } else { return; } } void GL_APIENTRY glGenBuffers(GLsizei n, GLuint *buffers) { auto func = GLESSymbols::get().glGenBuffers; if(func != nullptr) { return func(n, buffers); } else { return; } } GLuint GL_APIENTRY glGetProgramResourceIndex(GLuint program, GLenum programInterface, const GLchar *name) { auto func = GLESSymbols::get().glGetProgramResourceIndex; if(func != nullptr) { return func(program, programInterface, name); } else { return GL_INVALID_INDEX; } } GLint GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar *name) { auto func = GLESSymbols::get().glGetUniformLocation; if(func != nullptr) { return func(program, name); } else { return -1; } } void *GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) { auto func = GLESSymbols::get().glMapBufferRange; if(func != nullptr) { return func(target, offset, length, access); } else { return nullptr; } } void GL_APIENTRY glMemoryBarrier(GLbitfield barriers) { auto func = GLESSymbols::get().glMemoryBarrier; if(func != nullptr) { return func(barriers); } else { return; } } void GL_APIENTRY glUniform1ui(GLint location, GLuint v0) { auto func = GLESSymbols::get().glUniform1ui; if(func != nullptr) { return func(location, v0); } else { return; } } GLboolean GL_APIENTRY glUnmapBuffer(GLenum target) { auto func = GLESSymbols::get().glUnmapBuffer; if(func != nullptr) { return func(target); } else { return GL_FALSE; } } GLenum GL_APIENTRY glGetError(void) { auto func = GLESSymbols::get().glGetError; if(func != nullptr) { return func(); } else { return GL_NO_ERROR; } } const GLubyte *GL_APIENTRY glGetString(GLenum name) { auto func = GLESSymbols::get().glGetString; if(func != nullptr) { return func(name); } else { return nullptr; } } void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint *params) { auto func = GLESSymbols::get().glGetActiveUniformBlockiv; if(func != nullptr) { return func(program, uniformBlockIndex, pname, params); } else { return; } } void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) { auto func = GLESSymbols::get().glUniformBlockBinding; if(func != nullptr) { return func(program, uniformBlockIndex, uniformBlockBinding); } else { return; } } GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar *uniformBlockName) { auto func = GLESSymbols::get().glGetUniformBlockIndex; if(func != nullptr) { return func(program, uniformBlockName); } else { return GL_INVALID_INDEX; } } void GL_APIENTRY glGenTextures(GLsizei n, GLuint *textures) { auto func = GLESSymbols::get().glGenTextures; if(func != nullptr) { return func(n, textures); } else { return; } } void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint *textures) { auto func = GLESSymbols::get().glDeleteTextures; if(func != nullptr) { return func(n, textures); } else { return; } } void GL_APIENTRY glBindTexture(GLenum target, GLuint texture) { auto func = GLESSymbols::get().glBindTexture; if(func != nullptr) { return func(target, texture); } else { return; } } void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels) { auto func = GLESSymbols::get().glTexImage2D; if(func != nullptr) { return func(target, level, internalformat, width, height, border, format, type, pixels); } else { return; } } void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint *framebuffers) { auto func = GLESSymbols::get().glGenFramebuffers; if(func != nullptr) { return func(n, framebuffers); } else { return; } } void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers) { auto func = GLESSymbols::get().glDeleteFramebuffers; if(func != nullptr) { return func(n, framebuffers); } else { return; } } void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer) { auto func = GLESSymbols::get().glBindFramebuffer; if(func != nullptr) { return func(target, framebuffer); } else { return; } } void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) { auto func = GLESSymbols::get().glFramebufferTexture2D; if(func != nullptr) { return func(target, attachment, textarget, texture, level); } else { return; } }