diff --git a/examples/opengl/CMakeLists.txt b/examples/opengl/CMakeLists.txt index e34dded..9f41d76 100644 --- a/examples/opengl/CMakeLists.txt +++ b/examples/opengl/CMakeLists.txt @@ -1,13 +1,13 @@ -project (openglexample C) +set(OpenGL_GL_PREFERENCE GLVND) find_package(OpenGL REQUIRED) find_package(OpenHMD REQUIRED) -add_executable(openglexample gl.c gl.h main.c) - +add_executable(openglexample gl.c gl.h main.c vr_context.c vr_context.h) target_include_directories(openglexample PRIVATE ${OPENGL_INCLUDE_DIRS}) target_link_libraries(openglexample PRIVATE ${OPENGL_LIBRARIES}) target_link_libraries(openglexample PRIVATE m) target_link_libraries(openglexample PRIVATE openhmd) target_link_libraries(openglexample PRIVATE lvrc) +target_include_directories(openglexample PRIVATE "/usr/include/drm") diff --git a/examples/opengl/gl.c b/examples/opengl/gl.c index baaa8a3..e0a1426 100644 --- a/examples/opengl/gl.c +++ b/examples/opengl/gl.c @@ -10,10 +10,12 @@ #include "gl.h" #include #include + #include #include +#include -#include +#include #ifdef __unix #include @@ -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); } diff --git a/examples/opengl/gl.h b/examples/opengl/gl.h index cfa9f3a..10c19b5 100644 --- a/examples/opengl/gl.h +++ b/examples/opengl/gl.h @@ -10,24 +10,33 @@ #ifndef GL_H #define GL_H -#define GL_GLEXT_PROTOTYPES +#include + +#define GL_GLEXT_PROTOTYPES 1 #include #include - -#include +#include +#include typedef struct { - unsigned int w, h; - EGLDisplay display; - EGLSurface surface; - EGLContext context; + int w, h; + xcb_connection_t* x_connection; + int x_screen; + xcb_window_t x_window; + + EGLDisplay egl_display; + EGLConfig egl_config; + EGLContext egl_context; + EGLSurface egl_surface; + int is_fullscreen; } gl_ctx; void ortho(gl_ctx* ctx); void perspective(gl_ctx* ctx); -void init_gl(gl_ctx* ctx, struct lvrcInstance * compositor); -void draw_cube(void); +void init_gl(gl_ctx* ctx, int w, int h); +void draw_cube(); +GLuint compile_shader(const char* vertex, const char* fragment); void create_fbo(int eye_width, int eye_height, GLuint* fbo, GLuint* color_tex, GLuint* depth_tex); diff --git a/examples/opengl/main.c b/examples/opengl/main.c index 3828bc6..97ac870 100644 --- a/examples/opengl/main.c +++ b/examples/opengl/main.c @@ -11,9 +11,14 @@ #include #include #include +#include "gl.h" + #include #include -#include "gl.h" + +#include + +#include "vr_context.h" #define OVERSAMPLE_SCALE 2.0 @@ -150,7 +155,19 @@ int main(int argc, char** argv) struct lvrcInstance * compositor = lvrcCreateInstance(hmd); gl_ctx gl; - init_gl(&gl, compositor); + init_gl(&gl, hmd_w, hmd_h); + + const char* vertex; + ohmd_gets(OHMD_GLSL_DISTORTION_VERT_SRC, &vertex); + const char* fragment; + ohmd_gets(OHMD_GLSL_DISTORTION_FRAG_SRC, &fragment); + + GLuint shader = compile_shader(vertex, fragment); + glUseProgram(shader); + glUniform1i(glGetUniformLocation(shader, "warpTexture"), 0); + glUniform2fv(glGetUniformLocation(shader, "ViewportScale"), 1, viewport_scale); + glUniform3fv(glGetUniformLocation(shader, "aberr"), 1, aberr_scale); + glUseProgram(0); GLuint list = gen_cubes(); @@ -162,6 +179,32 @@ int main(int argc, char** argv) GLuint right_color_tex = 0, right_depth_tex = 0, right_fbo = 0; create_fbo(eye_w, eye_h, &right_fbo, &right_color_tex, &right_depth_tex); + PFNEGLEXPORTDMABUFIMAGEMESAPROC eglExportDMABUFImage = (PFNEGLEXPORTDMABUFIMAGEMESAPROC) eglGetProcAddress("eglExportDMABUFImageMESA"); + PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC eglExportDMABUFImageQuery = (PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC) eglGetProcAddress("eglExportDMABUFImageQueryMESA"); + +#if 1 + EGLImage left_image = eglCreateImage(gl.egl_display, gl.egl_context, EGL_GL_TEXTURE_2D, (EGLClientBuffer)(left_color_tex), NULL); + + dma_texture_params left_texture_params; + left_texture_params.width = eye_w; + left_texture_params.height = eye_h; + eglExportDMABUFImageQuery(gl.egl_display, left_image, &left_texture_params.fourcc, &left_texture_params.numplanes, &left_texture_params.modifiers); + eglExportDMABUFImage(gl.egl_display, left_image, &left_texture_params.fd, &left_texture_params.stride, &left_texture_params.offset); +#endif // 0 + +#if 1 + EGLImage right_image = eglCreateImage(gl.egl_display, gl.egl_context, EGL_GL_TEXTURE_2D, (EGLClientBuffer)(right_color_tex), NULL); + + dma_texture_params right_texture_params; + right_texture_params.width = eye_w; + right_texture_params.height = eye_h; + eglExportDMABUFImageQuery(gl.egl_display, right_image, &right_texture_params.fourcc, &right_texture_params.numplanes, &right_texture_params.modifiers); + eglExportDMABUFImage(gl.egl_display, right_image, &right_texture_params.fd, &right_texture_params.stride, &right_texture_params.offset); +#endif // 0 + + extern void init_vr_context(struct lvrcInstance * compositor, dma_texture_params * left_texture_params, dma_texture_params * right_texture_params); + init_vr_context(compositor, &left_texture_params, &right_texture_params); + bool bCompositorInit = lvrcInitFrameResources(compositor); if (!bCompositorInit) @@ -172,104 +215,12 @@ int main(int argc, char** argv) bool done = false; bool crosshair_overlay = false; while(!done){ + ohmd_ctx_update(ctx); lvrcBeginFrame(compositor); -#if 0 - SDL_Event event; - while(SDL_PollEvent(&event)){ - if(event.type == SDL_KEYDOWN){ - switch(event.key.keysym.sym){ - case SDLK_ESCAPE: - done = true; - break; - case SDLK_F1: - { - gl.is_fullscreen = !gl.is_fullscreen; - SDL_SetWindowFullscreen(gl.window, gl.is_fullscreen ? SDL_WINDOW_FULLSCREEN : 0); - } - break; - case SDLK_F2: - { - // reset rotation and position - float zero[] = {0, 0, 0, 1}; - ohmd_device_setf(hmd, OHMD_ROTATION_QUAT, zero); - ohmd_device_setf(hmd, OHMD_POSITION_VECTOR, zero); - } - break; - case SDLK_F3: - { - float mat[16]; - ohmd_device_getf(hmd, OHMD_LEFT_EYE_GL_PROJECTION_MATRIX, mat); - printf("Projection L: "); - print_matrix(mat); - printf("\n"); - ohmd_device_getf(hmd, OHMD_RIGHT_EYE_GL_PROJECTION_MATRIX, mat); - printf("Projection R: "); - print_matrix(mat); - printf("\n"); - ohmd_device_getf(hmd, OHMD_LEFT_EYE_GL_MODELVIEW_MATRIX, mat); - printf("View: "); - print_matrix(mat); - printf("\n"); - printf("viewport_scale: [%0.4f, %0.4f]\n", viewport_scale[0], viewport_scale[1]); - printf("lens separation: %04f\n", sep); - printf("IPD: %0.4f\n", ipd); - printf("warp_scale: %0.4f\r\n", warp_scale); - printf("distortion coeffs: [%0.4f, %0.4f, %0.4f, %0.4f]\n", distortion_coeffs[0], distortion_coeffs[1], distortion_coeffs[2], distortion_coeffs[3]); - printf("aberration coeffs: [%0.4f, %0.4f, %0.4f]\n", aberr_scale[0], aberr_scale[1], aberr_scale[2]); - printf("left_lens_center: [%0.4f, %0.4f]\n", left_lens_center[0], left_lens_center[1]); - printf("right_lens_center: [%0.4f, %0.4f]\n", right_lens_center[0], right_lens_center[1]); - } - break; - case SDLK_w: - sep += 0.001; - left_lens_center[0] = viewport_scale[0] - sep/2.0f; - right_lens_center[0] = sep/2.0f; - break; - case SDLK_q: - sep -= 0.001; - left_lens_center[0] = viewport_scale[0] - sep/2.0f; - right_lens_center[0] = sep/2.0f; - break; - case SDLK_a: - warp_adj *= 1.0/0.9; - break; - case SDLK_z: - warp_adj *= 0.9; - break; - case SDLK_i: - ipd -= 0.001; - ohmd_device_setf(hmd, OHMD_EYE_IPD, &ipd); - break; - case SDLK_o: - ipd += 0.001; - ohmd_device_setf(hmd, OHMD_EYE_IPD, &ipd); - break; - case SDLK_d: - /* toggle between distorted and undistorted views */ - if ((distortion_coeffs[0] != 0.0) || - (distortion_coeffs[1] != 0.0) || - (distortion_coeffs[2] != 0.0) || - (distortion_coeffs[3] != 1.0)) { - distortion_coeffs[0] = 0.0; - distortion_coeffs[1] = 0.0; - distortion_coeffs[2] = 0.0; - distortion_coeffs[3] = 1.0; - } else { - ohmd_device_getf(hmd, OHMD_UNIVERSAL_DISTORTION_K, &(distortion_coeffs[0])); - } - break; - case SDLK_x: - crosshair_overlay = ! crosshair_overlay; - break; - default: - break; - } - } - } -#endif // 0 + eglMakeCurrent(gl.egl_display, gl.egl_surface, gl.egl_surface, gl.egl_context); // Common scene state glEnable(GL_BLEND); @@ -286,7 +237,7 @@ int main(int argc, char** argv) glLoadMatrixf(matrix); // Draw scene into framebuffer. - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, left_fbo); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, left_fbo); glViewport(0, 0, eye_w, eye_h); glClearColor(0.0, 0.0, 0.0, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -308,7 +259,7 @@ int main(int argc, char** argv) glLoadMatrixf(matrix); // Draw scene into framebuffer. - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, right_fbo); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, right_fbo); glViewport(0, 0, eye_w, eye_h); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); draw_scene(list); @@ -320,15 +271,52 @@ int main(int argc, char** argv) } // Clean up common draw state - glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); + glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); + + // Setup ortho state. + glUseProgram(shader); + glUniform1f(glGetUniformLocation(shader, "WarpScale"), warp_scale*warp_adj); + glUniform4fv(glGetUniformLocation(shader, "HmdWarpParam"), 1, distortion_coeffs); + glViewport(0, 0, hmd_w, hmd_h); + glEnable(GL_TEXTURE_2D); + glColor4d(1, 1, 1, 1); + + // Setup simple render state + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + // Draw left eye - lvrcSubmitFrameLeft(compositor, left_color_tex); + glUniform2fv(glGetUniformLocation(shader, "LensCenter"), 1, left_lens_center); + glBindTexture(GL_TEXTURE_2D, left_color_tex); + glBegin(GL_QUADS); + glTexCoord2d( 0, 0); + glVertex3d( -1, -1, 0); + glTexCoord2d( 1, 0); + glVertex3d( 0, -1, 0); + glTexCoord2d( 1, 1); + glVertex3d( 0, 1, 0); + glTexCoord2d( 0, 1); + glVertex3d( -1, 1, 0); + glEnd(); // Draw right eye - lvrcSubmitFrameRight(compositor, right_color_tex); + glUniform2fv(glGetUniformLocation(shader, "LensCenter"), 1, right_lens_center); + glBindTexture(GL_TEXTURE_2D, right_color_tex); + glBegin(GL_QUADS); + glTexCoord2d( 0, 0); + glVertex3d( 0, -1, 0); + glTexCoord2d( 1, 0); + glVertex3d( 1, -1, 0); + glTexCoord2d( 1, 1); + glVertex3d( 1, 1, 0); + glTexCoord2d( 0, 1); + glVertex3d( 0, 1, 0); + glEnd(); // Clean up state. glBindTexture(GL_TEXTURE_2D, 0); @@ -336,17 +324,18 @@ int main(int argc, char** argv) glUseProgram(0); // Da swap-dawup! - eglSwapBuffers(gl.display, gl.surface); + eglSwapBuffers(gl.egl_display, gl.egl_surface); + + + extern void vr_context_submit_eyes(struct lvrcInstance * compositor); + + vr_context_submit_eyes(compositor); lvrcEndFrame(compositor); } lvrcReleaseFrameResources(compositor); - // TODO : destroy OpenGL context here - - lvrcReleaseSwapChain(compositor); - lvrcDestroyInstance(compositor); ohmd_ctx_destroy(ctx); diff --git a/examples/opengl/vr_context.c b/examples/opengl/vr_context.c new file mode 100644 index 0000000..81e4911 --- /dev/null +++ b/examples/opengl/vr_context.c @@ -0,0 +1,214 @@ +#include "vr_context.h" + +#include +#include +#include + +#include + +#include + +#include + +static EGLDisplay display; +static EGLSurface surface; +static EGLContext context; + +static void create_vr_context(struct lvrcInstance * compositor) +{ + 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 + }; + + static const EGLint context_attributes[] = + { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + // + // Get Native Display + EGLNativeDisplayType nativeDisplay = lvrcSwapChainGetNativeDisplay(compositor); + + if (!nativeDisplay) + { + fprintf(stderr, "invalid native display\n"); + exit(-1); + } + + // + // get an EGL display connection + display = eglGetDisplay(nativeDisplay); + + if (EGL_NO_DISPLAY == display) + { + fprintf(stderr, "eglGetDisplay() failed\n"); + exit(-1); + } + + // + // initialize the EGL display connection + EGLint major, minor; + + if (!eglInitialize(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(display, attribs, configs, 128, &num_config)) + { + fprintf(stderr, "eglChooseConfig() failed\n"); + exit(-1); + } + + EGLConfig config = configs[0]; // FIXME + + // + // create context + context = eglCreateContext(display, config, EGL_NO_CONTEXT, context_attributes); + + if (EGL_NO_CONTEXT == 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 + surface = eglCreateWindowSurface(display, config, nativeWindow, NULL); + if (EGL_NO_SURFACE == surface) + { + fprintf(stderr, "eglCreateWindowSurface() failed\n"); + exit(-1); + } + + // + // Set current context + if (!eglMakeCurrent(display, surface, surface, context)) + { + fprintf(stderr, "failed to make context current\n"); + exit(-1); + } +} + +GLuint left_color_tex = 0; +GLuint right_color_tex = 0; + +void init_vr_context(struct lvrcInstance * compositor, dma_texture_params * left_texture_params, dma_texture_params * right_texture_params) +{ + bool bSwapChainCreated = lvrcInitSwapChain(compositor); + + if (!bSwapChainCreated) + { + fprintf(stderr, "swap chain not created\n"); + exit(-1); + } + + create_vr_context(compositor); + + PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress ("glEGLImageTargetTexture2DOES"); + + // + // LEFT + EGLAttrib attrib_list_left[] = + { + EGL_DMA_BUF_PLANE0_FD_EXT, left_texture_params->fd, + EGL_DMA_BUF_PLANE0_PITCH_EXT, left_texture_params->stride, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, left_texture_params->offset, + EGL_WIDTH, left_texture_params->width, + EGL_HEIGHT, left_texture_params->height, + EGL_LINUX_DRM_FOURCC_EXT, left_texture_params->fourcc, + //EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, left_texture_params->modifiers & 0xFFFFFFFF, + //EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, left_texture_params->modifiers >> 32, + EGL_NONE, + }; + + EGLImage image_left = eglCreateImage(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attrib_list_left); + + glGenTextures(1, &left_color_tex); + glBindTexture(GL_TEXTURE_2D, left_color_tex); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_left); + assert(glGetError() == GL_NO_ERROR); + + glBindTexture(GL_TEXTURE_2D, 0); + + // + // RIGHT + EGLAttrib attrib_list_right[] = + { + EGL_DMA_BUF_PLANE0_FD_EXT, right_texture_params->fd, + EGL_DMA_BUF_PLANE0_PITCH_EXT, right_texture_params->stride, + EGL_DMA_BUF_PLANE0_OFFSET_EXT, right_texture_params->offset, + EGL_WIDTH, right_texture_params->width, + EGL_HEIGHT, right_texture_params->height, + EGL_LINUX_DRM_FOURCC_EXT, right_texture_params->fourcc, + //EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT, right_texture_params->modifiers & 0xFFFFFFFF, + //EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT, right_texture_params->modifiers >> 32, + EGL_NONE, + }; + + EGLImage image_right = eglCreateImage(display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attrib_list_right); + + glGenTextures(1, &right_color_tex); + glBindTexture(GL_TEXTURE_2D, right_color_tex); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image_right); + assert(glGetError() == GL_NO_ERROR); + + glBindTexture(GL_TEXTURE_2D, 0); +} + +void vr_context_submit_eyes(struct lvrcInstance * compositor) +{ + eglMakeCurrent(display, surface, surface, context); + + glClearColor(0.0f, 1.0f, 0.0f, 0.0f); + glClear(GL_COLOR_BUFFER_BIT); + + // Draw left eye + lvrcSubmitFrameLeft(compositor, left_color_tex); + + // Draw right eye + lvrcSubmitFrameRight(compositor, right_color_tex); + + eglSwapBuffers(display, surface); +} diff --git a/examples/opengl/vr_context.h b/examples/opengl/vr_context.h new file mode 100644 index 0000000..b08168b --- /dev/null +++ b/examples/opengl/vr_context.h @@ -0,0 +1,14 @@ + + + +typedef struct +{ + int fd; + int width; + int height; + int stride; + int offset; + int fourcc; + int numplanes; + unsigned long int modifiers; +} dma_texture_params;