blob: f56bcfaeb6d5426d99ced0a1b36ad001f3ee8ef5 [file] [log] [blame]
/*
* 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 <dlfcn.h>
#include <iostream>
#include <vector>
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<void *> 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;
}
}