Update API + example
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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);
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
@@ -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
14
include/lvrc_EGL.h
Normal 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
|
||||||
@@ -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")
|
||||||
|
|||||||
44
src/frame.c
44
src/frame.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
352
src/instance.c
352
src/instance.c
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
85
src/rendering_EGL.c
Normal 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;
|
||||||
|
}
|
||||||
550
src/swapChain.c
550
src/swapChain.c
@@ -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;
|
|
||||||
|
|
||||||
if (!internalInstance->swapChain)
|
|
||||||
{
|
{
|
||||||
return false;
|
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;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user