Update API + example

This commit is contained in:
2018-09-22 18:16:48 +02:00
parent b1febba24e
commit bdb827e07e
15 changed files with 680 additions and 722 deletions

View File

@@ -289,24 +289,11 @@ GLuint compile_shader(const char* vertex, const char* fragment)
return programShader; return programShader;
} }
void create_fbo(int eye_width, int eye_height, GLuint* fbo, GLuint* color_tex, GLuint* depth_tex, EGLImage image) void create_fbo(int eye_width, int eye_height, GLuint* fbo, GLuint color_tex, GLuint* depth_tex)
{ {
glGenTextures(1, color_tex);
glGenTextures(1, depth_tex); glGenTextures(1, depth_tex);
glGenFramebuffers(1, fbo); glGenFramebuffers(1, fbo);
glBindTexture(GL_TEXTURE_2D, *color_tex);
#if 0
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, eye_width, eye_height, 0, GL_RGBA, GL_UNSIGNED_INT, NULL);
#else
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress ("glEGLImageTargetTexture2DOES");
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
#endif // 0
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);
glBindTexture(GL_TEXTURE_2D, *depth_tex); glBindTexture(GL_TEXTURE_2D, *depth_tex);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, eye_width, eye_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL); glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, eye_width, eye_height, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_BYTE, NULL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
@@ -316,7 +303,7 @@ void create_fbo(int eye_width, int eye_height, GLuint* fbo, GLuint* color_tex, G
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glBindFramebuffer(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_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color_tex, 0);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, *depth_tex, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, *depth_tex, 0);
GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);

View File

@@ -37,7 +37,7 @@ void perspective(gl_ctx* ctx);
void init_gl(gl_ctx* ctx, int w, int h); void init_gl(gl_ctx* ctx, int w, int h);
void draw_cube(); void draw_cube();
GLuint compile_shader(const char* vertex, const char* fragment); 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, EGLImage image); void create_fbo(int eye_width, int eye_height, GLuint* fbo, GLuint color_tex, GLuint* depth_tex);
#endif #endif

View File

@@ -157,76 +157,28 @@ int main(int argc, char** argv)
gl_ctx gl; gl_ctx gl;
init_gl(&gl, hmd_w, hmd_h); 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(); GLuint list = gen_cubes();
lvrcInitRenderingEGL(compositor, gl.egl_display, gl.egl_context, gl.egl_surface);
int eye_w = hmd_w/2*OVERSAMPLE_SCALE; int eye_w = hmd_w/2*OVERSAMPLE_SCALE;
int eye_h = hmd_h*OVERSAMPLE_SCALE; int eye_h = hmd_h*OVERSAMPLE_SCALE;
EGLint imageAttribs[] = { GLuint textures [2];
EGL_WIDTH, eye_w,
EGL_HEIGHT, eye_h,
EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA,
EGL_NONE
};
PFNEGLCREATEDRMIMAGEMESAPROC eglCreateDRMImage = (PFNEGLCREATEDRMIMAGEMESAPROC) eglGetProcAddress("eglCreateDRMImageMESA"); bool bSwapChainInit = lvrcInitSwapChain(compositor, eye_w, eye_h, textures);
EGLImage left_image = eglCreateDRMImage(gl.egl_display, imageAttribs); if (!bSwapChainInit)
EGLImage right_image = eglCreateDRMImage(gl.egl_display, imageAttribs);
GLuint left_color_tex = 0, left_depth_tex = 0, left_fbo = 0;
create_fbo(eye_w, eye_h, &left_fbo, &left_color_tex, &left_depth_tex, left_image);
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, right_image);
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)
{ {
return(-1); return -1;
} }
GLuint left_color_tex = textures[0], left_depth_tex = 0, left_fbo = 0;
create_fbo(eye_w, eye_h, &left_fbo, left_color_tex, &left_depth_tex);
GLuint right_color_tex = textures[1], right_depth_tex = 0, right_fbo = 0;
create_fbo(eye_w, eye_h, &right_fbo, right_color_tex, &right_depth_tex);
bool done = false; bool done = false;
bool crosshair_overlay = false; bool crosshair_overlay = false;
while(!done){ while(!done){
@@ -290,11 +242,7 @@ int main(int argc, char** argv)
glDisable(GL_BLEND); glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
// Setup ortho state. // 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); glViewport(0, 0, hmd_w, hmd_h);
glEnable(GL_TEXTURE_2D); glEnable(GL_TEXTURE_2D);
glColor4d(1, 1, 1, 1); glColor4d(1, 1, 1, 1);
@@ -306,7 +254,6 @@ int main(int argc, char** argv)
glLoadIdentity(); glLoadIdentity();
// Draw left eye // Draw left eye
glUniform2fv(glGetUniformLocation(shader, "LensCenter"), 1, left_lens_center);
glBindTexture(GL_TEXTURE_2D, left_color_tex); glBindTexture(GL_TEXTURE_2D, left_color_tex);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2d( 0, 0); glTexCoord2d( 0, 0);
@@ -320,7 +267,6 @@ int main(int argc, char** argv)
glEnd(); glEnd();
// Draw right eye // Draw right eye
glUniform2fv(glGetUniformLocation(shader, "LensCenter"), 1, right_lens_center);
glBindTexture(GL_TEXTURE_2D, right_color_tex); glBindTexture(GL_TEXTURE_2D, right_color_tex);
glBegin(GL_QUADS); glBegin(GL_QUADS);
glTexCoord2d( 0, 0); glTexCoord2d( 0, 0);
@@ -338,19 +284,14 @@ int main(int argc, char** argv)
glDisable(GL_TEXTURE_2D); glDisable(GL_TEXTURE_2D);
glUseProgram(0); glUseProgram(0);
glFinish();
// Da swap-dawup! // Da swap-dawup!
eglSwapBuffers(gl.egl_display, gl.egl_surface); eglSwapBuffers(gl.egl_display, gl.egl_surface);
extern void vr_context_submit_eyes(struct lvrcInstance * compositor);
vr_context_submit_eyes(compositor);
lvrcEndFrame(compositor); lvrcEndFrame(compositor);
} }
lvrcReleaseFrameResources(compositor);
lvrcDestroyInstance(compositor); lvrcDestroyInstance(compositor);
ohmd_ctx_destroy(ctx); ohmd_ctx_destroy(ctx);

View File

@@ -1,155 +0,0 @@
#include "vr_context.h"
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <GL/gl.h>
#include <lvrc.h>
#include <EGL/eglext.h>
#include "context.inl"
static EGLDisplay display;
static EGLSurface surface;
static EGLContext context;
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
};
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);
}
//
// Get Native Display
EGLNativeDisplayType nativeDisplay = lvrcSwapChainGetNativeDisplay(compositor);
if (!nativeDisplay)
{
fprintf(stderr, "invalid native display\n");
exit(-1);
}
//
// Get Native Window
EGLNativeWindowType nativeWindow = lvrcSwapChainGetNativeWindow(compositor);
if (!nativeWindow)
{
fprintf(stderr, "invalid native window\n");
exit(-1);
}
bool bContextCreated = create_context(EGL_PLATFORM_GBM_KHR, nativeDisplay, nativeWindow, attribs, context_attributes, NULL, &display, &context, &surface);
if (!bContextCreated)
{
fprintf(stderr, "couldn't create compositor context\n");
exit(-1);
}
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);
}

View File

@@ -1,14 +0,0 @@
typedef struct
{
int fd;
int width;
int height;
int stride;
int offset;
int fourcc;
int numplanes;
unsigned long int modifiers;
} dma_texture_params;

View File

@@ -3,12 +3,6 @@
#include <openhmd.h> #include <openhmd.h>
#ifndef __GBM__
#define __GBM__
#endif // __GBM__
#include <EGL/egl.h>
#include <stdbool.h> #include <stdbool.h>
#define LVRC_API __attribute__ ((visibility ("default"))) #define LVRC_API __attribute__ ((visibility ("default")))
@@ -30,31 +24,23 @@ LVRC_API void lvrcDestroyInstance(struct lvrcInstance * state);
// Swap Chain // Swap Chain
// //
LVRC_API bool lvrcInitSwapChain(struct lvrcInstance * state); LVRC_API bool lvrcInitSwapChain(struct lvrcInstance * state, unsigned int width, unsigned int height, GLuint * textures);
LVRC_API bool lvrcReleaseSwapChain(struct lvrcInstance * state); LVRC_API bool lvrcReleaseSwapChain(struct lvrcInstance * state);
LVRC_API EGLNativeDisplayType lvrcSwapChainGetNativeDisplay(struct lvrcInstance * state);
LVRC_API EGLNativeWindowType lvrcSwapChainGetNativeWindow(struct lvrcInstance * state);
LVRC_API unsigned int lvrcSwapChainGetWidth(struct lvrcInstance * state);
LVRC_API unsigned int lvrcSwapChainGetHeight(struct lvrcInstance * state);
// //
// Frame // Frame
// //
LVRC_API bool lvrcInitFrameResources(struct lvrcInstance * state);
LVRC_API bool lvrcReleaseFrameResources(struct lvrcInstance * state);
LVRC_API bool lvrcBeginFrame(struct lvrcInstance * state); LVRC_API bool lvrcBeginFrame(struct lvrcInstance * state);
LVRC_API bool lvrcSubmitFrameLeft(struct lvrcInstance * state, GLuint texture);
LVRC_API bool lvrcSubmitFrameRight(struct lvrcInstance * state, GLuint texture);
LVRC_API bool lvrcEndFrame(struct lvrcInstance * state); LVRC_API bool lvrcEndFrame(struct lvrcInstance * state);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#ifdef __egl_h_
# include "lvrc_EGL.h"
#endif // __egl_h_
#endif // LINUX_VR_COMPOSITOR_H #endif // LINUX_VR_COMPOSITOR_H

14
include/lvrc_EGL.h Normal file
View File

@@ -0,0 +1,14 @@
#ifndef LINUX_VR_COMPOSITOR_EGL_H
#define LINUX_VR_COMPOSITOR_EGL_H
#ifdef __cplusplus
extern "C" {
#endif
LVRC_API bool lvrcInitRenderingEGL(struct lvrcInstance * state, EGLDisplay display, EGLContext context, EGLSurface surface);
#ifdef __cplusplus
}
#endif
#endif // LINUX_VR_COMPOSITOR_EGL_H

View File

@@ -1,11 +1,13 @@
cmake_minimum_required(VERSION 3.10) # GLVND
find_path(DRM_INCLUDE_DIR drm.h PATH_SUFFIXES drm libdrm) find_path(DRM_INCLUDE_DIR drm.h PATH_SUFFIXES drm libdrm)
find_library(DRM_LIBRARY drm) find_library(DRM_LIBRARY drm)
set(OpenGL_GL_PREFERENCE GLVND)
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
find_package(OpenHMD REQUIRED) find_package(OpenHMD REQUIRED)
add_library(lvrc ../include/lvrc.h lvrc.c lvrc_internal.h instance.c instance.h swapChain.c swapChain.h frame.c frame.h) add_library(lvrc ../include/lvrc.h ../include/lvrc_EGL.h lvrc.c lvrc_internal.h instance.c instance.h swapChain.c swapChain.h frame.c frame.h rendering_EGL.c)
target_link_libraries(lvrc PUBLIC openhmd ${OPENGL_LIBRARIES} EGL) target_link_libraries(lvrc PUBLIC openhmd ${OPENGL_LIBRARIES} EGL)
target_link_libraries(lvrc PUBLIC "${DRM_LIBRARY}" "gbm") target_link_libraries(lvrc PUBLIC "${DRM_LIBRARY}" "gbm")

View File

@@ -6,7 +6,7 @@
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#define USE_ES_SHADERS 0 #define USE_ES_SHADERS 1
static const GLfloat textureVertices[] = static const GLfloat textureVertices[] =
{ {
@@ -79,16 +79,9 @@ static GLuint compile_shader(const char* vertex, const char* fragment)
// ------------------------------------------------------------------- // -------------------------------------------------------------------
bool lvrcInitFrameResources(struct lvrcInstance * instance) bool InitFrameResources(Instance * instance)
{ {
Instance * internalState = (Instance*)instance; ohmd_device * hmd = instance->hmd;
if (!internalState->swapChain)
{
return false;
}
ohmd_device * hmd = internalState->device;
float viewport_scale[2]; float viewport_scale[2];
float distortion_coeffs[4]; float distortion_coeffs[4];
@@ -151,13 +144,6 @@ bool lvrcInitFrameResources(struct lvrcInstance * instance)
return true; return true;
} }
bool lvrcReleaseFrameResources(struct lvrcInstance * state)
{
// TODO
return true;
}
bool lvrcBeginFrame(struct lvrcInstance * state) bool lvrcBeginFrame(struct lvrcInstance * state)
{ {
return true; // nothing yet return true; // nothing yet
@@ -188,13 +174,13 @@ bool lvrcSubmitFrameLeft(struct lvrcInstance * instance, GLuint texture)
{ {
Instance * internalInstance = (Instance*)instance; Instance * internalInstance = (Instance*)instance;
if (!internalInstance->swapChain) if (!internalInstance->mode)
{ {
return false; return false;
} }
unsigned int hmd_w = internalInstance->swapChain->mode->hdisplay; unsigned int hmd_w = internalInstance->mode->hdisplay;
unsigned int hmd_h = internalInstance->swapChain->mode->vdisplay; unsigned int hmd_h = internalInstance->mode->vdisplay;
prepare(texture); prepare(texture);
@@ -212,13 +198,13 @@ bool lvrcSubmitFrameRight(struct lvrcInstance * instance, GLuint texture)
{ {
Instance * internalInstance = (Instance*)instance; Instance * internalInstance = (Instance*)instance;
if (!internalInstance->swapChain) if (!internalInstance->mode)
{ {
return false; return false;
} }
unsigned int hmd_w = internalInstance->swapChain->mode->hdisplay; unsigned int hmd_w = internalInstance->mode->hdisplay;
unsigned int hmd_h = internalInstance->swapChain->mode->vdisplay; unsigned int hmd_h = internalInstance->mode->vdisplay;
prepare(texture); prepare(texture);
@@ -236,12 +222,14 @@ bool lvrcEndFrame(struct lvrcInstance * instance)
{ {
Instance * internalInstance = (Instance*)instance; Instance * internalInstance = (Instance*)instance;
if (!internalInstance->swapChain) eglMakeCurrent(internalInstance->vr_display, internalInstance->vr_surface, internalInstance->vr_surface, internalInstance->vr_context);
{
return false;
}
SwapBuffers(internalInstance->swapChain); lvrcSubmitFrameLeft(instance, internalInstance->textures[0]);
lvrcSubmitFrameRight(instance, internalInstance->textures[1]);
eglSwapBuffers(internalInstance->vr_display, internalInstance->vr_surface);
SwapBuffers(internalInstance);
return true; return true;
} }

View File

@@ -1,5 +1,10 @@
#ifndef LINUX_VR_COMPOSITOR_FRAME_H #ifndef LINUX_VR_COMPOSITOR_FRAME_H
#define LINUX_VR_COMPOSITOR_FRAME_H #define LINUX_VR_COMPOSITOR_FRAME_H
#include <stdbool.h>
#include "instance.h"
bool InitFrameResources(Instance * instance);
#endif // LINUX_VR_COMPOSITOR_FRAME_H #endif // LINUX_VR_COMPOSITOR_FRAME_H

View File

@@ -2,23 +2,331 @@
#include "lvrc_internal.h" #include "lvrc_internal.h"
#include <malloc.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#if ENABLE_XCB
# include <xcb/xcb.h>
# include <xcb/randr.h>
#endif // ENABLE_XCB
#define EDID_SIZE (0x80)
static int drm_find_psvr_fd(Instance * instance, int fd)
{
drmModeRes * resources = NULL;
drmModeConnector * connector = NULL;
drmModeEncoder * encoder = NULL;
resources = drmModeGetResources(fd);
if (!resources)
{
//fprintf(stderr, "drmModeGetResources failed\n");
return(0);
}
if (resources->count_connectors <= 0)
{
//fprintf(stderr, "no connector\n");
return(0);
}
int i = 0;
for (i = 0; i < resources->count_connectors; i++)
{
drmModeConnector * connectorToTest = drmModeGetConnector(fd, resources->connectors[i]);
if (connectorToTest == NULL)
{
continue;
}
if (connectorToTest->connection != DRM_MODE_CONNECTED)
{
continue;
}
if (connectorToTest->count_modes <= 0)
{
continue;
}
for (int j = 0; j < connectorToTest->count_props; j++)
{
drmModePropertyPtr prop = drmModeGetProperty(fd, connectorToTest->props[j]);
if (prop)
{
if (prop->flags & DRM_MODE_PROP_RANGE && strcmp(prop->name, "non-desktop") == 0)
{
uint64_t value = connectorToTest->prop_values[j];
if (value == 1)
{
connector = connectorToTest;
break;
}
}
else if (prop->flags & DRM_MODE_PROP_BLOB && strcmp(prop->name, "EDID") == 0)
{
uint64_t value = connectorToTest->prop_values[j];
drmModePropertyBlobPtr blob_ptr = drmModeGetPropertyBlob(fd, value);
if (blob_ptr)
{
char edid[EDID_SIZE];
memcpy(&edid, blob_ptr->data, EDID_SIZE);
drmModeFreePropertyBlob(blob_ptr);
if (strncmp(edid+95, "SIE HMD *08", 12) == 0) // ugly
{
connector = connectorToTest;
break;
}
}
}
drmModeFreeProperty(prop);
}
}
if (connector)
{
break;
}
drmModeFreeConnector(connectorToTest);
}
if (!connector)
{
return 0;
}
if (i == resources->count_connectors)
{
//fprintf(stderr, "No currently active connector found.\n");
return(0);
}
if (resources->count_encoders <= 0)
{
//fprintf(stderr, "no encoder\n");
return(0);
}
for (i = 0; i < resources->count_encoders; i++)
{
encoder = drmModeGetEncoder(fd, resources->encoders[i]);
if (encoder == NULL)
{
continue;
}
if (encoder->encoder_id == connector->encoder_id)
{
break;
}
drmModeFreeEncoder(encoder);
}
static drmModeModeInfo force_timing;
#if 1 // PSVR
force_timing.clock = 297700;
force_timing.hdisplay = 1920;
force_timing.hsync_start = 2008;
force_timing.hsync_end = 2052;
force_timing.htotal = 2200;
force_timing.vdisplay = 1080;
force_timing.vsync_start = 1084;
force_timing.vsync_end = 1089;
force_timing.vtotal = 1125;
#else // VIVE
force_timing.clock = 297000;
force_timing.hdisplay = 2160;
force_timing.hsync_start = 2200;
force_timing.hsync_end = 2220;
force_timing.htotal = 2266;
force_timing.vdisplay = 1200;
force_timing.vsync_start = 1228;
force_timing.vsync_end = 1230;
force_timing.vtotal = 1464;
#endif //
instance->fd = fd;
instance->connector = connector;
instance->encoder = encoder;
instance->mode = &force_timing;
return 1;
}
static const char device_name[] = "/dev/dri/card1";
static int drm_find_psvr_udev(Instance * instance)
{
int fd = open(device_name, O_RDWR); // FIXME : use udev to available devices
if (fd < 0)
{
fprintf(stderr, "Can't open device\n");
return 0;
}
return drm_find_psvr_fd(instance, fd);
}
#ifdef ENABLE_XCB #ifdef ENABLE_XCB
# include <xcb/xcb.h> static int drm_find_psvr_xcb(Instance * instance)
{
xcb_randr_query_version_cookie_t rqv_c = xcb_randr_query_version(instance->connection, XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION);
xcb_randr_query_version_reply_t *rqv_r = xcb_randr_query_version_reply(instance->connection, rqv_c, NULL);
if (!rqv_r || rqv_r->minor_version < 6)
{
printf("No new-enough RandR version\n");
return(0);
}
xcb_screen_iterator_t s_i;
int i_s = 0;
for (s_i = xcb_setup_roots_iterator(xcb_get_setup(instance->connection)); s_i.rem; xcb_screen_next(&s_i), i_s++)
{
printf ("index %d screen %d\n", s_i.index, instance->screen);
if (i_s == instance->screen)
break;
}
xcb_window_t root = s_i.data->root;
printf("root %x\n", root);
xcb_randr_get_screen_resources_cookie_t gsr_c = xcb_randr_get_screen_resources(instance->connection, root);
xcb_randr_get_screen_resources_reply_t *gsr_r = xcb_randr_get_screen_resources_reply(instance->connection, gsr_c, NULL);
if (!gsr_r)
{
printf("get_screen_resources failed\n");
return(0);
}
xcb_randr_output_t *ro = xcb_randr_get_screen_resources_outputs(gsr_r);
int o, c;
xcb_randr_output_t output = 0;
/* Find a connected but idle output */
for (o = 0; output == 0 && o < gsr_r->num_outputs; o++) {
xcb_randr_get_output_info_cookie_t goi_c = xcb_randr_get_output_info(instance->connection, ro[o], gsr_r->config_timestamp);
xcb_randr_get_output_info_reply_t *goi_r = xcb_randr_get_output_info_reply(instance->connection, goi_c, NULL);
/* Find the first connected but unused output */
if (goi_r->connection == XCB_RANDR_CONNECTION_CONNECTED &&
goi_r->crtc == 0) {
output = ro[o];
}
free(goi_r);
}
xcb_randr_crtc_t *rc = xcb_randr_get_screen_resources_crtcs(gsr_r);
xcb_randr_crtc_t crtc = 0;
/* Find an idle crtc */
for (c = 0; crtc == 0 && c < gsr_r->num_crtcs; c++) {
xcb_randr_get_crtc_info_cookie_t gci_c = xcb_randr_get_crtc_info(instance->connection, rc[c], gsr_r->config_timestamp);
xcb_randr_get_crtc_info_reply_t *gci_r = xcb_randr_get_crtc_info_reply(instance->connection, gci_c, NULL);
/* Find the first connected but unused crtc */
if (gci_r->mode == 0)
crtc = rc[c];
free(gci_r);
}
free(gsr_r);
printf("output %x crtc %x\n", output, crtc);
xcb_randr_lease_t lease = xcb_generate_id(instance->connection);
xcb_randr_create_lease_cookie_t rcl_c = xcb_randr_create_lease(instance->connection,
root,
lease,
1,
1,
&crtc,
&output);
xcb_randr_create_lease_reply_t *rcl_r = xcb_randr_create_lease_reply(instance->connection, rcl_c, NULL);
if (!rcl_r) {
printf("create_lease failed\n");
exit(1);
}
int *rcl_f = xcb_randr_create_lease_reply_fds(instance->connection, rcl_r);
return drm_find_psvr_fd(instance, rcl_f[0]);
}
#endif // ENABLE_XCB #endif // ENABLE_XCB
struct lvrcInstance * lvrcCreateInstance(ohmd_device * hmd) struct lvrcInstance * lvrcCreateInstance(ohmd_device * hmd)
{ {
Instance * instance = calloc(1, sizeof(Instance)); Instance * instance = calloc(1, sizeof(Instance));
instance->device = hmd; instance->hmd = hmd;
#ifdef ENABLE_XCB #ifdef ENABLE_XCB
instance->connection = xcb_connect(NULL, &instance->screen); instance->connection = xcb_connect(NULL, &instance->screen);
#endif // ENABLE_XCB
instance->swapChain = NULL; if (drm_find_psvr_xcb(instance))
{
printf("device found using XCB\n");
}
else
#endif // ENABLE_XCB
if (drm_find_psvr_udev(instance))
{
printf("device found using udev\n");
}
else
{
fprintf(stderr, "couldn't find devicee\n");
free(instance);
return NULL;
}
instance->device = gbm_create_device(instance->fd);
if (instance->device == NULL)
{
fprintf(stderr, "couldn't create gbm device\n");
free(instance);
return NULL;
}
instance->surface = gbm_surface_create(instance->device, instance->mode->hdisplay, instance->mode->vdisplay, GBM_BO_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
if (instance->surface == NULL)
{
fprintf(stderr, "couldn't create gbm surface\n");
free(instance);
return NULL;
}
return (struct lvrcInstance *)instance; return (struct lvrcInstance *)instance;
} }
@@ -27,3 +335,37 @@ void lvrcDestroyInstance(struct lvrcInstance * instance)
{ {
free(instance); free(instance);
} }
void SwapBuffers(Instance * instance)
{
struct gbm_bo * newbo = gbm_surface_lock_front_buffer(instance->surface);
uint32_t handle = gbm_bo_get_handle(newbo).u32;
uint32_t stride = gbm_bo_get_stride(newbo);
{
uint32_t newfb = 0;
drmModeAddFB(instance->fd, instance->mode->hdisplay, instance->mode->vdisplay, 24, 32, stride, handle, &newfb);
int rc = drmModeSetCrtc(instance->fd, instance->encoder->crtc_id, newfb, 0, 0, &instance->connector->connector_id, 1, instance->mode);
if (rc < 0)
{
fprintf(stderr, "drmModeSetCrtc() failed\n");
return;
}
if (instance->fbid)
{
drmModeRmFB(instance->fd, instance->fbid);
}
instance->fbid = newfb;
}
if (instance->bo)
{
gbm_surface_release_buffer(instance->surface, instance->bo);
}
instance->bo = newbo;
}

View File

@@ -7,19 +7,48 @@
# include <xcb/xcb.h> # include <xcb/xcb.h>
#endif // ENABLE_XCB #endif // ENABLE_XCB
#include "swapChain.h" #include <xf86drm.h>
#include <xf86drmMode.h>
#include <gbm.h>
#include <EGL/egl.h>
#include <GL/gl.h>
typedef struct typedef struct
{ {
ohmd_device * device; ohmd_device * hmd;
#ifdef ENABLE_XCB #ifdef ENABLE_XCB
xcb_connection_t * connection; xcb_connection_t * connection;
int screen; int screen;
#endif // ENABLE_XCB #endif // ENABLE_XCB
SwapChain * swapChain; int fd;
drmModeConnector * connector;
drmModeEncoder * encoder;
drmModeModeInfo * mode;
struct gbm_device * device;
struct gbm_surface * surface;
uint32_t fbid;
struct gbm_bo * bo;
EGLDisplay vr_display;
EGLContext vr_context;
EGLSurface vr_surface;
EGLDisplay user_display;
EGLContext user_context;
EGLSurface user_surface;
GLuint textures [2];
} Instance; } Instance;
void SwapBuffers(Instance * instance);
#endif // LINUX_VR_COMPOSITOR_STATE_H #endif // LINUX_VR_COMPOSITOR_STATE_H

85
src/rendering_EGL.c Normal file
View File

@@ -0,0 +1,85 @@
#include "instance.h"
#include "frame.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include "lvrc_internal.h"
#include "context.inl"
#include <malloc.h>
bool lvrcInitRenderingEGL(struct lvrcInstance * instance, EGLDisplay user_display, EGLContext user_context, EGLSurface user_surface)
{
Instance * internalInstance = (Instance*)instance;
if (!internalInstance->device)
{
return false;
}
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 = internalInstance->device;
if (!nativeDisplay)
{
fprintf(stderr, "invalid native display\n");
return false;
}
//
// Get Native Window
EGLNativeWindowType nativeWindow = internalInstance->surface;
if (!nativeWindow)
{
fprintf(stderr, "invalid native window\n");
return false;
}
EGLDisplay display;
EGLSurface surface;
EGLContext context;
bool bContextCreated = create_context(EGL_PLATFORM_GBM_KHR, nativeDisplay, nativeWindow, attribs, context_attributes, NULL, &display, &context, &surface);
if (!bContextCreated)
{
fprintf(stderr, "couldn't create compositor context\n");
return false;
}
InitFrameResources(internalInstance);
internalInstance->vr_display = display;
internalInstance->vr_context = context;
internalInstance->vr_surface = surface;
internalInstance->user_display = user_display;
internalInstance->user_context = user_context;
internalInstance->user_surface = user_surface;
eglMakeCurrent(user_display, user_surface, user_surface, user_context);
return true;
}

View File

@@ -3,436 +3,196 @@
#include "lvrc_internal.h" #include "lvrc_internal.h"
#include "instance.h" #include "instance.h"
#include <malloc.h> #include <GL/gl.h>
#include <GL/glext.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <stdio.h> #include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h> #include "context.inl"
#include <unistd.h>
#if ENABLE_XCB #include "frame.h"
# include <xcb/xcb.h>
# include <xcb/randr.h>
#endif // ENABLE_XCB
#define EDID_SIZE (0x80) typedef struct
static int drm_find_psvr_fd(SwapChain * swapChain, int fd)
{ {
drmModeRes * resources = NULL; int fd;
drmModeConnector * connector = NULL; int width;
drmModeEncoder * encoder = NULL; int height;
int stride;
int offset;
int fourcc;
int numplanes;
unsigned long int modifiers;
} dma_texture_params;
resources = drmModeGetResources(fd); bool lvrcInitSwapChain(struct lvrcInstance * instance, unsigned int width, unsigned int height, GLuint * textures)
if (!resources)
{
//fprintf(stderr, "drmModeGetResources failed\n");
return(0);
}
if (resources->count_connectors <= 0)
{
//fprintf(stderr, "no connector\n");
return(0);
}
int i = 0;
for (i = 0; i < resources->count_connectors; i++)
{
drmModeConnector * connectorToTest = drmModeGetConnector(fd, resources->connectors[i]);
if (connectorToTest == NULL)
{
continue;
}
if (connectorToTest->connection != DRM_MODE_CONNECTED)
{
continue;
}
if (connectorToTest->count_modes <= 0)
{
continue;
}
for (int j = 0; j < connectorToTest->count_props; j++)
{
drmModePropertyPtr prop = drmModeGetProperty(fd, connectorToTest->props[j]);
if (prop)
{
if (prop->flags & DRM_MODE_PROP_RANGE && strcmp(prop->name, "non-desktop") == 0)
{
uint64_t value = connectorToTest->prop_values[j];
if (value == 1)
{
connector = connectorToTest;
break;
}
}
else if (prop->flags & DRM_MODE_PROP_BLOB && strcmp(prop->name, "EDID") == 0)
{
uint64_t value = connectorToTest->prop_values[j];
drmModePropertyBlobPtr blob_ptr = drmModeGetPropertyBlob(fd, value);
if (blob_ptr)
{
char edid[EDID_SIZE];
memcpy(&edid, blob_ptr->data, EDID_SIZE);
drmModeFreePropertyBlob(blob_ptr);
if (strncmp(edid+95, "SIE HMD *08", 12) == 0) // ugly
{
connector = connectorToTest;
break;
}
}
}
drmModeFreeProperty(prop);
}
}
if (connector)
{
break;
}
drmModeFreeConnector(connectorToTest);
}
if (!connector)
{
return 0;
}
if (i == resources->count_connectors)
{
//fprintf(stderr, "No currently active connector found.\n");
return(0);
}
if (resources->count_encoders <= 0)
{
//fprintf(stderr, "no encoder\n");
return(0);
}
for (i = 0; i < resources->count_encoders; i++)
{
encoder = drmModeGetEncoder(fd, resources->encoders[i]);
if (encoder == NULL)
{
continue;
}
if (encoder->encoder_id == connector->encoder_id)
{
break;
}
drmModeFreeEncoder(encoder);
}
static drmModeModeInfo force_timing;
#if 1 // PSVR
force_timing.clock = 297700;
force_timing.hdisplay = 1920;
force_timing.hsync_start = 2008;
force_timing.hsync_end = 2052;
force_timing.htotal = 2200;
force_timing.vdisplay = 1080;
force_timing.vsync_start = 1084;
force_timing.vsync_end = 1089;
force_timing.vtotal = 1125;
#else // VIVE
force_timing.clock = 297000;
force_timing.hdisplay = 2160;
force_timing.hsync_start = 2200;
force_timing.hsync_end = 2220;
force_timing.htotal = 2266;
force_timing.vdisplay = 1200;
force_timing.vsync_start = 1228;
force_timing.vsync_end = 1230;
force_timing.vtotal = 1464;
#endif //
swapChain->fd = fd;
swapChain->connector = connector;
swapChain->encoder = encoder;
swapChain->mode = &force_timing;
return 1;
}
static const char device_name[] = "/dev/dri/card1";
static int drm_find_psvr_udev(SwapChain * swapChain)
{
int fd = open(device_name, O_RDWR); // FIXME : use udev to available devices
if (fd < 0)
{
fprintf(stderr, "Can't open device\n");
return 0;
}
return drm_find_psvr_fd(swapChain, fd);
}
#ifdef ENABLE_XCB
static int drm_find_psvr_xcb(SwapChain * swapChain, xcb_connection_t * connection, int screen)
{
xcb_randr_query_version_cookie_t rqv_c = xcb_randr_query_version(connection, XCB_RANDR_MAJOR_VERSION, XCB_RANDR_MINOR_VERSION);
xcb_randr_query_version_reply_t *rqv_r = xcb_randr_query_version_reply(connection, rqv_c, NULL);
if (!rqv_r || rqv_r->minor_version < 6)
{
printf("No new-enough RandR version\n");
return(0);
}
xcb_screen_iterator_t s_i;
int i_s = 0;
for (s_i = xcb_setup_roots_iterator(xcb_get_setup(connection)); s_i.rem; xcb_screen_next(&s_i), i_s++)
{
printf ("index %d screen %d\n", s_i.index, screen);
if (i_s == screen)
break;
}
xcb_window_t root = s_i.data->root;
printf("root %x\n", root);
xcb_randr_get_screen_resources_cookie_t gsr_c = xcb_randr_get_screen_resources(connection, root);
xcb_randr_get_screen_resources_reply_t *gsr_r = xcb_randr_get_screen_resources_reply(connection, gsr_c, NULL);
if (!gsr_r)
{
printf("get_screen_resources failed\n");
return(0);
}
xcb_randr_output_t *ro = xcb_randr_get_screen_resources_outputs(gsr_r);
int o, c;
xcb_randr_output_t output = 0;
/* Find a connected but idle output */
for (o = 0; output == 0 && o < gsr_r->num_outputs; o++) {
xcb_randr_get_output_info_cookie_t goi_c = xcb_randr_get_output_info(connection, ro[o], gsr_r->config_timestamp);
xcb_randr_get_output_info_reply_t *goi_r = xcb_randr_get_output_info_reply(connection, goi_c, NULL);
/* Find the first connected but unused output */
if (goi_r->connection == XCB_RANDR_CONNECTION_CONNECTED &&
goi_r->crtc == 0) {
output = ro[o];
}
free(goi_r);
}
xcb_randr_crtc_t *rc = xcb_randr_get_screen_resources_crtcs(gsr_r);
xcb_randr_crtc_t crtc = 0;
/* Find an idle crtc */
for (c = 0; crtc == 0 && c < gsr_r->num_crtcs; c++) {
xcb_randr_get_crtc_info_cookie_t gci_c = xcb_randr_get_crtc_info(connection, rc[c], gsr_r->config_timestamp);
xcb_randr_get_crtc_info_reply_t *gci_r = xcb_randr_get_crtc_info_reply(connection, gci_c, NULL);
/* Find the first connected but unused crtc */
if (gci_r->mode == 0)
crtc = rc[c];
free(gci_r);
}
free(gsr_r);
printf("output %x crtc %x\n", output, crtc);
xcb_randr_lease_t lease = xcb_generate_id(connection);
xcb_randr_create_lease_cookie_t rcl_c = xcb_randr_create_lease(connection,
root,
lease,
1,
1,
&crtc,
&output);
xcb_randr_create_lease_reply_t *rcl_r = xcb_randr_create_lease_reply(connection, rcl_c, NULL);
if (!rcl_r) {
printf("create_lease failed\n");
exit(1);
}
int *rcl_f = xcb_randr_create_lease_reply_fds(connection, rcl_r);
return drm_find_psvr_fd(swapChain, rcl_f[0]);
}
#endif // ENABLE_XCB
bool lvrcInitSwapChain(struct lvrcInstance * instance)
{ {
Instance * internalInstance = (Instance*)instance; Instance * internalInstance = (Instance*)instance;
if (!internalInstance->device) if (!internalInstance->user_context)
{ {
return false; return false;
} }
SwapChain * swapChain = calloc(1, sizeof(SwapChain)); eglMakeCurrent(internalInstance->user_display, internalInstance->user_surface, internalInstance->user_surface, internalInstance->user_context);
#ifdef ENABLE_XCB EGLint imageAttribs[] =
if (drm_find_psvr_xcb(swapChain, internalInstance->connection, internalInstance->screen))
{ {
printf("device found using XCB\n"); EGL_WIDTH, width,
} EGL_HEIGHT, height,
else EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA,
#endif // ENABLE_XCB EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA,
if (drm_find_psvr_udev(swapChain)) EGL_NONE
};
PFNEGLCREATEDRMIMAGEMESAPROC eglCreateDRMImage = (PFNEGLCREATEDRMIMAGEMESAPROC) eglGetProcAddress("eglCreateDRMImageMESA");
PFNEGLEXPORTDMABUFIMAGEMESAPROC eglExportDMABUFImage = (PFNEGLEXPORTDMABUFIMAGEMESAPROC) eglGetProcAddress("eglExportDMABUFImageMESA");
PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC eglExportDMABUFImageQuery = (PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC) eglGetProcAddress("eglExportDMABUFImageQueryMESA");
if (!eglCreateDRMImage || !eglExportDMABUFImage || !eglExportDMABUFImageQuery)
{ {
printf("device found using udev\n");
}
else
{
fprintf(stderr, "couldn't find devicee\n");
free(swapChain);
return false; return false;
} }
swapChain->device = gbm_create_device(swapChain->fd); //
// Create and export left image
//
if (swapChain->device == NULL) EGLImage left_image = eglCreateDRMImage(internalInstance->user_display, imageAttribs);
if (!left_image)
{ {
fprintf(stderr, "couldn't create gbm device\n");
free(swapChain);
return false; return false;
} }
swapChain->surface = gbm_surface_create(swapChain->device, swapChain->mode->hdisplay, swapChain->mode->vdisplay, GBM_BO_FORMAT_XRGB8888, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING); //
// Create and export right image
//
if (swapChain->surface == NULL) EGLImage right_image = eglCreateDRMImage(internalInstance->user_display, imageAttribs);
if (!right_image)
{ {
fprintf(stderr, "couldn't create gbm surface\n");
free(swapChain);
return false; return false;
} }
internalInstance->swapChain = swapChain; //
// Import textures in user context
//
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2D_user = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress ("glEGLImageTargetTexture2DOES");
glGenTextures(2, textures);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glEGLImageTargetTexture2D_user(GL_TEXTURE_2D, left_image);
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);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glEGLImageTargetTexture2D_user(GL_TEXTURE_2D, right_image);
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);
glBindTexture(GL_TEXTURE_2D, 0);
dma_texture_params left_texture_params;
left_texture_params.width = width;
left_texture_params.height = height;
eglExportDMABUFImageQuery(internalInstance->user_display, left_image, &left_texture_params.fourcc, &left_texture_params.numplanes, &left_texture_params.modifiers);
eglExportDMABUFImage(internalInstance->user_display, left_image, &left_texture_params.fd, &left_texture_params.stride, &left_texture_params.offset);
dma_texture_params right_texture_params;
right_texture_params.width = width;
right_texture_params.height = height;
eglExportDMABUFImageQuery(internalInstance->user_display, right_image, &right_texture_params.fourcc, &right_texture_params.numplanes, &right_texture_params.modifiers);
eglExportDMABUFImage(internalInstance->user_display, right_image, &right_texture_params.fd, &right_texture_params.stride, &right_texture_params.offset);
//
// Import textures in VR context
//
eglMakeCurrent(internalInstance->vr_display, internalInstance->vr_surface, internalInstance->vr_surface, internalInstance->vr_context);
PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2D_VR = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress ("glEGLImageTargetTexture2DOES");
glGenTextures(2, internalInstance->textures);
//
// 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(internalInstance->vr_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attrib_list_left);
glBindTexture(GL_TEXTURE_2D, internalInstance->textures[0]);
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);
glEGLImageTargetTexture2D_VR(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(internalInstance->vr_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attrib_list_right);
glBindTexture(GL_TEXTURE_2D, internalInstance->textures[1]);
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);
glEGLImageTargetTexture2D_VR(GL_TEXTURE_2D, image_right);
assert(glGetError() == GL_NO_ERROR);
glBindTexture(GL_TEXTURE_2D, 0);
eglMakeCurrent(internalInstance->user_display, internalInstance->user_surface, internalInstance->user_surface, internalInstance->user_context);
return true; return true;
} }
bool lvrcReleaseSwapChain(struct lvrcInstance * instance) bool lvrcReleaseSwapChain(struct lvrcInstance * instance)
{ {
Instance * internalInstance = (Instance*)instance; return false;
if (!internalInstance->swapChain)
{
return false;
}
// TODO : destroy resources
free(internalInstance->swapChain);
internalInstance->swapChain = NULL;
return true;
} }
EGLNativeDisplayType lvrcSwapChainGetNativeDisplay(struct lvrcInstance * instance)
{
Instance * internalInstance = (Instance*)instance;
if (!internalInstance->swapChain)
{
return NULL;
}
return internalInstance->swapChain->device;
}
EGLNativeWindowType lvrcSwapChainGetNativeWindow(struct lvrcInstance * instance)
{
Instance * internalInstance = (Instance*)instance;
if (!internalInstance->swapChain)
{
return NULL;
}
return internalInstance->swapChain->surface;
}
unsigned int lvrcSwapChainGetWidth(struct lvrcInstance * instance)
{
Instance * internalInstance = (Instance*)instance;
if (!internalInstance->swapChain)
{
return 0;
}
return internalInstance->swapChain->mode->hdisplay;
}
unsigned int lvrcSwapChainGetHeight(struct lvrcInstance * instance)
{
Instance * internalInstance = (Instance*)instance;
if (!internalInstance->swapChain)
{
return 0;
}
return internalInstance->swapChain->mode->vdisplay;
}
void SwapBuffers(SwapChain * swapChain)
{
struct gbm_bo * newbo = gbm_surface_lock_front_buffer(swapChain->surface);
uint32_t handle = gbm_bo_get_handle(newbo).u32;
uint32_t stride = gbm_bo_get_stride(newbo);
{
uint32_t newfb = 0;
drmModeAddFB(swapChain->fd, swapChain->mode->hdisplay, swapChain->mode->vdisplay, 24, 32, stride, handle, &newfb);
int rc = drmModeSetCrtc(swapChain->fd, swapChain->encoder->crtc_id, newfb, 0, 0, &swapChain->connector->connector_id, 1, swapChain->mode);
if (rc < 0)
{
fprintf(stderr, "drmModeSetCrtc() failed\n");
return;
}
if (swapChain->fbid)
{
drmModeRmFB(swapChain->fd, swapChain->fbid);
}
swapChain->fbid = newfb;
}
if (swapChain->bo)
{
gbm_surface_release_buffer(swapChain->surface, swapChain->bo);
}
swapChain->bo = newbo;
}

View File

@@ -10,20 +10,8 @@
typedef struct typedef struct
{ {
int fd;
drmModeConnector * connector;
drmModeEncoder * encoder;
drmModeModeInfo * mode;
struct gbm_device * device;
struct gbm_surface * surface;
uint32_t fbid;
struct gbm_bo * bo;
} SwapChain; } SwapChain;
void SwapBuffers(SwapChain * swapChain);
#endif // LINUX_VR_COMPOSITOR_SWAPCHAIN_H #endif // LINUX_VR_COMPOSITOR_SWAPCHAIN_H