Update openglexample
This commit is contained in:
@@ -10,10 +10,12 @@
|
||||
#include "gl.h"
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <lvrc.h>
|
||||
#include <xcb/xcb.h>
|
||||
|
||||
#ifdef __unix
|
||||
#include <signal.h>
|
||||
@@ -23,125 +25,211 @@
|
||||
#define M_PI 3.14159265359
|
||||
#endif
|
||||
|
||||
const uint32_t xcb_window_attrib_mask = XCB_CW_EVENT_MASK;
|
||||
const uint32_t xcb_window_attrib_list[] = {
|
||||
XCB_EVENT_MASK_BUTTON_PRESS,
|
||||
XCB_EVENT_MASK_EXPOSURE,
|
||||
XCB_EVENT_MASK_KEY_PRESS,
|
||||
};
|
||||
|
||||
void init_gl(gl_ctx* ctx, struct lvrcInstance * compositor)
|
||||
void CreateWindow(const char *display_name,
|
||||
int window_x,
|
||||
int window_y,
|
||||
int window_width,
|
||||
int window_height,
|
||||
xcb_connection_t** out_connection,
|
||||
int* out_screen,
|
||||
xcb_window_t* out_window) {
|
||||
|
||||
xcb_generic_error_t* error;
|
||||
|
||||
//int iscreen;
|
||||
|
||||
xcb_connection_t *connection = xcb_connect(NULL, NULL);
|
||||
if (!connection)
|
||||
exit(-1);
|
||||
if (xcb_connection_has_error(connection))
|
||||
exit(-1);
|
||||
|
||||
const xcb_setup_t* setup = xcb_get_setup(connection);
|
||||
xcb_screen_t* screen = xcb_setup_roots_iterator(setup).data;
|
||||
assert(screen != 0);
|
||||
|
||||
xcb_window_t window = xcb_generate_id(connection);
|
||||
if (window <= 0)
|
||||
exit(-1);
|
||||
|
||||
xcb_void_cookie_t create_cookie = xcb_create_window_checked(
|
||||
connection,
|
||||
XCB_COPY_FROM_PARENT, // depth
|
||||
window,
|
||||
screen->root, // parent window
|
||||
window_x,
|
||||
window_y,
|
||||
window_width,
|
||||
window_height,
|
||||
0, // border width
|
||||
XCB_WINDOW_CLASS_INPUT_OUTPUT, // class
|
||||
screen->root_visual, // visual
|
||||
xcb_window_attrib_mask,
|
||||
xcb_window_attrib_list);
|
||||
|
||||
xcb_void_cookie_t map_cookie = xcb_map_window_checked(connection, window);
|
||||
|
||||
// Check errors.
|
||||
error = xcb_request_check(connection, create_cookie);
|
||||
if (error)
|
||||
exit(-1);
|
||||
error = xcb_request_check(connection, map_cookie);
|
||||
if (error)
|
||||
exit(-1);
|
||||
|
||||
*out_connection = connection;
|
||||
*out_window = window;
|
||||
}
|
||||
|
||||
static const EGLint egl_config_attribs[] = {
|
||||
//EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER,
|
||||
//EGL_BUFFER_SIZE, 32,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_ALPHA_SIZE, 8,
|
||||
|
||||
//EGL_DEPTH_SIZE, 24,
|
||||
//EGL_STENCIL_SIZE, 8,
|
||||
|
||||
//EGL_SAMPLE_BUFFERS, 0,
|
||||
//EGL_SAMPLES, 0,
|
||||
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
|
||||
|
||||
EGL_NONE,
|
||||
};
|
||||
|
||||
static const EGLint egl_context_attribs[] = {
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
static const EGLint egl_surface_attribs[] = {
|
||||
EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
|
||||
EGL_NONE,
|
||||
};
|
||||
|
||||
void CreateContext(
|
||||
EGLint api,
|
||||
EGLNativeWindowType native_window,
|
||||
EGLDisplay* out_display,
|
||||
EGLConfig* out_config,
|
||||
EGLContext* out_context,
|
||||
EGLSurface* out_window_surface) {
|
||||
|
||||
EGLint ignore;
|
||||
EGLBoolean ok;
|
||||
|
||||
ok = eglBindAPI(api);
|
||||
if (!ok)
|
||||
exit(-1);
|
||||
|
||||
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
if (display == EGL_NO_DISPLAY)
|
||||
exit(-1);
|
||||
|
||||
ok = eglInitialize(display, &ignore, &ignore);
|
||||
if (!ok)
|
||||
exit(-1);
|
||||
|
||||
EGLint configs_size = 256;
|
||||
EGLConfig configs [configs_size];
|
||||
EGLint num_configs;
|
||||
ok = eglChooseConfig(
|
||||
display,
|
||||
egl_config_attribs,
|
||||
configs,
|
||||
configs_size, // num requested configs
|
||||
&num_configs); // num returned configs
|
||||
if (!ok)
|
||||
exit(-1);
|
||||
if (num_configs == 0)
|
||||
exit(-1);
|
||||
EGLConfig config = configs[0];
|
||||
|
||||
EGLContext context = eglCreateContext(
|
||||
display,
|
||||
config,
|
||||
EGL_NO_CONTEXT, // can't share between 2 different drivers
|
||||
egl_context_attribs);
|
||||
if (!context)
|
||||
exit(-1);
|
||||
|
||||
EGLSurface surface = eglCreateWindowSurface(
|
||||
display,
|
||||
config,
|
||||
native_window,
|
||||
egl_surface_attribs);
|
||||
if (!surface)
|
||||
exit(-1);
|
||||
|
||||
ok = eglMakeCurrent(display, surface, surface, context);
|
||||
if (!ok)
|
||||
exit(-1);
|
||||
|
||||
// Check if surface is double buffered.
|
||||
EGLint render_buffer;
|
||||
ok = eglQueryContext(
|
||||
display,
|
||||
context,
|
||||
EGL_RENDER_BUFFER,
|
||||
&render_buffer);
|
||||
if (!ok)
|
||||
exit(-1);
|
||||
if (render_buffer == EGL_SINGLE_BUFFER)
|
||||
printf("warn: EGL surface is single buffered\n");
|
||||
|
||||
*out_display = display;
|
||||
*out_config = config;
|
||||
*out_context = context;
|
||||
*out_window_surface = surface;
|
||||
}
|
||||
|
||||
void init_gl(gl_ctx* ctx, int w, int h)
|
||||
{
|
||||
memset(ctx, 0, sizeof(gl_ctx));
|
||||
|
||||
bool bSwapChainCreated = lvrcInitSwapChain(compositor);
|
||||
const char *x_display_name = NULL;
|
||||
|
||||
if (!bSwapChainCreated)
|
||||
CreateWindow(x_display_name,
|
||||
0, 0, // x, y
|
||||
w, h, // width, height
|
||||
&ctx->x_connection,
|
||||
&ctx->x_screen,
|
||||
&ctx->x_window);
|
||||
|
||||
if(ctx->x_window == NULL)
|
||||
{
|
||||
fprintf(stderr, "swap chain not created\n");
|
||||
printf("CreateWindow failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static const EGLint attribs[] =
|
||||
{
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
//EGL_ALPHA_SIZE, 8,
|
||||
//EGL_DEPTH_SIZE, 16,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_NONE
|
||||
};
|
||||
ctx->w = w;
|
||||
ctx->h = h;
|
||||
ctx->is_fullscreen = 0;
|
||||
|
||||
static const EGLint context_attributes[] =
|
||||
{
|
||||
EGL_CONTEXT_CLIENT_VERSION, 2,
|
||||
EGL_NONE
|
||||
};
|
||||
CreateContext(EGL_OPENGL_API,
|
||||
ctx->x_window,
|
||||
&ctx->egl_display,
|
||||
&ctx->egl_config,
|
||||
&ctx->egl_context,
|
||||
&ctx->egl_surface);
|
||||
|
||||
//
|
||||
// Get Native Display
|
||||
EGLNativeDisplayType nativeDisplay = lvrcSwapChainGetNativeDisplay(compositor);
|
||||
|
||||
if (!nativeDisplay)
|
||||
if(ctx->egl_context == EGL_NO_CONTEXT)
|
||||
{
|
||||
fprintf(stderr, "invalid native display\n");
|
||||
printf("CreateContext\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//
|
||||
// get an EGL display connection
|
||||
ctx->display = eglGetDisplay(nativeDisplay);
|
||||
|
||||
if (EGL_NO_DISPLAY == ctx->display)
|
||||
{
|
||||
fprintf(stderr, "eglGetDisplay() failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//
|
||||
// initialize the EGL display connection
|
||||
EGLint major, minor;
|
||||
|
||||
if (!eglInitialize(ctx->display, &major, &minor))
|
||||
{
|
||||
fprintf(stderr, "eglInitialize() failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//
|
||||
// bind OpenGL API
|
||||
eglBindAPI(EGL_OPENGL_API);
|
||||
|
||||
//
|
||||
// get an appropriate EGL frame buffer configuration
|
||||
EGLint num_config;
|
||||
EGLConfig configs[128];
|
||||
|
||||
if (!eglChooseConfig(ctx->display, attribs, configs, 128, &num_config))
|
||||
{
|
||||
fprintf(stderr, "eglChooseConfig() failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
EGLConfig config = configs[0]; // FIXME
|
||||
|
||||
//
|
||||
// create context
|
||||
ctx->context = eglCreateContext(ctx->display, config, EGL_NO_CONTEXT, context_attributes);
|
||||
|
||||
if (EGL_NO_CONTEXT == ctx->context)
|
||||
{
|
||||
fprintf(stderr, "failed to create context\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//
|
||||
// Get Native Window
|
||||
EGLNativeWindowType nativeWindow = lvrcSwapChainGetNativeWindow(compositor);
|
||||
|
||||
if (!nativeWindow)
|
||||
{
|
||||
fprintf(stderr, "invalid native window\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//
|
||||
// Create Surface
|
||||
ctx->surface = eglCreateWindowSurface(ctx->display, config, nativeWindow, NULL);
|
||||
if (EGL_NO_SURFACE == ctx->surface)
|
||||
{
|
||||
fprintf(stderr, "eglCreateWindowSurface() failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//
|
||||
// Set current context
|
||||
if (!eglMakeCurrent(ctx->display, ctx->surface, ctx->surface, ctx->context))
|
||||
{
|
||||
fprintf(stderr, "failed to make context current\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
ctx->w = lvrcSwapChainGetWidth(compositor);
|
||||
ctx->h = lvrcSwapChainGetHeight(compositor);
|
||||
ctx->is_fullscreen = 1;
|
||||
|
||||
// Disable ctrl-c catching on Linux (and OS X?)
|
||||
#ifdef __unix
|
||||
signal(SIGINT, SIG_DFL);
|
||||
@@ -227,6 +315,59 @@ void draw_cube()
|
||||
|
||||
}
|
||||
|
||||
static void compile_shader_src(GLuint shader, const char* src)
|
||||
{
|
||||
glShaderSource(shader, 1, &src, NULL);
|
||||
glCompileShader(shader);
|
||||
|
||||
GLint status;
|
||||
GLint length;
|
||||
char log[4096] = {0};
|
||||
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||
glGetShaderInfoLog(shader, 4096, &length, log);
|
||||
if(status == GL_FALSE){
|
||||
printf("compile failed %s\n", log);
|
||||
}
|
||||
}
|
||||
|
||||
GLuint compile_shader(const char* vertex, const char* fragment)
|
||||
{
|
||||
// Create the handels
|
||||
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
GLuint programShader = glCreateProgram();
|
||||
|
||||
// Attach the shaders to a program handel.
|
||||
glAttachShader(programShader, vertexShader);
|
||||
glAttachShader(programShader, fragmentShader);
|
||||
|
||||
// Load and compile the Vertex Shader
|
||||
compile_shader_src(vertexShader, vertex);
|
||||
|
||||
// Load and compile the Fragment Shader
|
||||
compile_shader_src(fragmentShader, fragment);
|
||||
|
||||
// The shader objects are not needed any more,
|
||||
// the programShader is the complete shader to be used.
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
glLinkProgram(programShader);
|
||||
|
||||
GLint status;
|
||||
GLint length;
|
||||
char log[4096] = {0};
|
||||
|
||||
glGetProgramiv(programShader, GL_LINK_STATUS, &status);
|
||||
glGetProgramInfoLog(programShader, 4096, &length, log);
|
||||
if(status == GL_FALSE){
|
||||
printf("link failed %s\n", log);
|
||||
}
|
||||
|
||||
return programShader;
|
||||
}
|
||||
|
||||
void create_fbo(int eye_width, int eye_height, GLuint* fbo, GLuint* color_tex, GLuint* depth_tex)
|
||||
{
|
||||
glGenTextures(1, color_tex);
|
||||
@@ -248,14 +389,14 @@ void create_fbo(int eye_width, int eye_height, GLuint* fbo, GLuint* color_tex, G
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, *fbo);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER_EXT, *fbo);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, *color_tex, 0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, *depth_tex, 0);
|
||||
|
||||
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
|
||||
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
|
||||
|
||||
if(status != GL_FRAMEBUFFER_COMPLETE_EXT){
|
||||
printf("failed to create fbo %x\n", status);
|
||||
}
|
||||
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user