init
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
/* Copyright (c) 2020-2024, Arm Limited
|
||||
* Copyright (c) 2020-2024, Bradley Austin Davis
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 the "License";
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "offscreen_context.h"
|
||||
|
||||
#include <common/error.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "core/util/logging.hpp"
|
||||
|
||||
void APIENTRY debug_message_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *user_param)
|
||||
{
|
||||
switch (severity)
|
||||
{
|
||||
case GL_DEBUG_SEVERITY_HIGH:
|
||||
LOGE("OpenGL: {}", message);
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_MEDIUM:
|
||||
LOGW("OpenGL: {}", message);
|
||||
break;
|
||||
case GL_DEBUG_SEVERITY_LOW:
|
||||
LOGI("OpenGL: {}", message);
|
||||
break;
|
||||
default:
|
||||
case GL_DEBUG_SEVERITY_NOTIFICATION:
|
||||
LOGD("OpenGL: {}", message);
|
||||
}
|
||||
}
|
||||
|
||||
OffscreenContext::OffscreenContext()
|
||||
{
|
||||
init_context();
|
||||
|
||||
glDebugMessageCallback(debug_message_callback, NULL);
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
}
|
||||
|
||||
OffscreenContext::~OffscreenContext()
|
||||
{
|
||||
destroy_context();
|
||||
}
|
||||
|
||||
GLuint OffscreenContext::load_shader(const char *shader_source, GLenum shader_type)
|
||||
{
|
||||
std::string source = get_shader_header() + "\n" + std::string(shader_source);
|
||||
const char *source_ptr = source.c_str();
|
||||
const GLint size = static_cast<GLint>(source.size());
|
||||
|
||||
GLuint shader = glCreateShader(shader_type);
|
||||
glShaderSource(shader, 1, &source_ptr, &size);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint is_compiled = 0;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &is_compiled);
|
||||
if (is_compiled == GL_FALSE)
|
||||
{
|
||||
GLint max_length = 0;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &max_length);
|
||||
|
||||
// The maxLength includes the NULL character
|
||||
std::vector<GLchar> error_log(max_length);
|
||||
glGetShaderInfoLog(shader, max_length, &max_length, &error_log[0]);
|
||||
std::string str_error;
|
||||
str_error.insert(str_error.end(), error_log.begin(), error_log.end());
|
||||
|
||||
// Provide the infolog in whatever manor you deem best.
|
||||
// Exit with failure.
|
||||
glDeleteShader(shader); // Don't leak the shader.
|
||||
LOGE("OpenGL: Shader compilation failed", str_error.c_str());
|
||||
}
|
||||
return shader;
|
||||
}
|
||||
|
||||
GLuint OffscreenContext::build_program(const char *vertex_shader_source, const char *fragment_shader_source)
|
||||
{
|
||||
GLuint program = glCreateProgram();
|
||||
GLuint vs = load_shader(vertex_shader_source, GL_VERTEX_SHADER);
|
||||
GLuint fs = load_shader(fragment_shader_source, GL_FRAGMENT_SHADER);
|
||||
glAttachShader(program, vs);
|
||||
glAttachShader(program, fs);
|
||||
glLinkProgram(program);
|
||||
glDeleteShader(vs);
|
||||
glDeleteShader(fs);
|
||||
return program;
|
||||
}
|
||||
|
||||
#ifdef VK_USE_PLATFORM_ANDROID_KHR
|
||||
void OffscreenContext::init_context()
|
||||
{
|
||||
EGLint egl_maj_vers{0},
|
||||
egl_min_vers{0};
|
||||
data.display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
eglInitialize(data.display, &egl_maj_vers, &egl_min_vers);
|
||||
|
||||
constexpr EGLint conf_attr[] = {
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT_KHR,
|
||||
EGL_NONE};
|
||||
|
||||
EGLint num_configs;
|
||||
eglChooseConfig(data.display, conf_attr, &data.config, 1, &num_configs);
|
||||
|
||||
// Create a EGL context
|
||||
constexpr EGLint ctx_attr[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
|
||||
|
||||
data.context = eglCreateContext(data.display, data.config, EGL_NO_CONTEXT, ctx_attr);
|
||||
if (data.context == EGL_NO_CONTEXT)
|
||||
{
|
||||
throw std::runtime_error{"Failed to create EGL context"};
|
||||
}
|
||||
|
||||
// Create an offscreen pbuffer surface, and then make it current
|
||||
constexpr EGLint surface_attr[] = {EGL_WIDTH, 10, EGL_HEIGHT, 10, EGL_NONE};
|
||||
data.surface = eglCreatePbufferSurface(data.display, data.config, surface_attr);
|
||||
eglMakeCurrent(data.display, data.surface, data.surface, data.context);
|
||||
gladLoadGLES2Loader((GLADloadproc) &eglGetProcAddress);
|
||||
|
||||
LOGD("EGL init with version {}.{}", egl_maj_vers, egl_min_vers);
|
||||
}
|
||||
|
||||
void OffscreenContext::destroy_context()
|
||||
{
|
||||
eglDestroySurface(data.display, data.surface);
|
||||
eglDestroyContext(data.display, data.context);
|
||||
}
|
||||
|
||||
std::string OffscreenContext::get_shader_header()
|
||||
{
|
||||
return "#version 320 es";
|
||||
}
|
||||
#else
|
||||
void OffscreenContext::init_context()
|
||||
{
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, 1);
|
||||
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
|
||||
data.window = glfwCreateWindow(SHARED_TEXTURE_DIMENSION, SHARED_TEXTURE_DIMENSION, "OpenGL Window", nullptr, nullptr);
|
||||
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
|
||||
glfwMakeContextCurrent(data.window);
|
||||
gladLoadGL();
|
||||
if (glGenSemaphoresEXT == nullptr)
|
||||
{
|
||||
LOGE("Required openGL extension glGenSemaphoresEXT not available, cannot run");
|
||||
throw vkb::VulkanException(VK_ERROR_EXTENSION_NOT_PRESENT, "Extensions not present");
|
||||
}
|
||||
}
|
||||
|
||||
void OffscreenContext::destroy_context()
|
||||
{
|
||||
glfwDestroyWindow(data.window);
|
||||
}
|
||||
|
||||
std::string OffscreenContext::get_shader_header()
|
||||
{
|
||||
return "#version 450 core";
|
||||
}
|
||||
#endif
|
||||
Reference in New Issue
Block a user