diff --git a/examples/opengl/gl.c b/examples/opengl/gl.c index 497df10..cf58b44 100644 --- a/examples/opengl/gl.c +++ b/examples/opengl/gl.c @@ -289,24 +289,11 @@ GLuint compile_shader(const char* vertex, const char* fragment) 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); 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); 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); @@ -316,7 +303,7 @@ void create_fbo(int eye_width, int eye_height, GLuint* fbo, GLuint* color_tex, G glBindTexture(GL_TEXTURE_2D, 0); 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); GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT); diff --git a/examples/opengl/gl.h b/examples/opengl/gl.h index cc0ba85..4ded410 100644 --- a/examples/opengl/gl.h +++ b/examples/opengl/gl.h @@ -37,7 +37,7 @@ void perspective(gl_ctx* ctx); void init_gl(gl_ctx* ctx, int w, int h); void draw_cube(); GLuint compile_shader(const char* vertex, const char* fragment); -void create_fbo(int eye_width, int eye_height, GLuint* fbo, GLuint* color_tex, GLuint* depth_tex, EGLImage image); +void create_fbo(int eye_width, int eye_height, GLuint* fbo, GLuint color_tex, GLuint* depth_tex); #endif diff --git a/examples/opengl/main.c b/examples/opengl/main.c index 3f64189..be17a33 100644 --- a/examples/opengl/main.c +++ b/examples/opengl/main.c @@ -157,76 +157,28 @@ int main(int argc, char** argv) gl_ctx gl; 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(); + lvrcInitRenderingEGL(compositor, gl.egl_display, gl.egl_context, gl.egl_surface); int eye_w = hmd_w/2*OVERSAMPLE_SCALE; int eye_h = hmd_h*OVERSAMPLE_SCALE; - EGLint imageAttribs[] = { - 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 - }; + GLuint textures [2]; - PFNEGLCREATEDRMIMAGEMESAPROC eglCreateDRMImage = (PFNEGLCREATEDRMIMAGEMESAPROC) eglGetProcAddress("eglCreateDRMImageMESA"); + bool bSwapChainInit = lvrcInitSwapChain(compositor, eye_w, eye_h, textures); - EGLImage left_image = eglCreateDRMImage(gl.egl_display, imageAttribs); - 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) + if (!bSwapChainInit) { - 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 crosshair_overlay = false; while(!done){ @@ -290,11 +242,7 @@ int main(int argc, char** argv) glDisable(GL_BLEND); glDisable(GL_DEPTH_TEST); - // Setup ortho state. - glUseProgram(shader); - glUniform1f(glGetUniformLocation(shader, "WarpScale"), warp_scale*warp_adj); - glUniform4fv(glGetUniformLocation(shader, "HmdWarpParam"), 1, distortion_coeffs); glViewport(0, 0, hmd_w, hmd_h); glEnable(GL_TEXTURE_2D); glColor4d(1, 1, 1, 1); @@ -306,7 +254,6 @@ int main(int argc, char** argv) glLoadIdentity(); // Draw left eye - glUniform2fv(glGetUniformLocation(shader, "LensCenter"), 1, left_lens_center); glBindTexture(GL_TEXTURE_2D, left_color_tex); glBegin(GL_QUADS); glTexCoord2d( 0, 0); @@ -320,7 +267,6 @@ int main(int argc, char** argv) glEnd(); // Draw right eye - glUniform2fv(glGetUniformLocation(shader, "LensCenter"), 1, right_lens_center); glBindTexture(GL_TEXTURE_2D, right_color_tex); glBegin(GL_QUADS); glTexCoord2d( 0, 0); @@ -338,19 +284,14 @@ int main(int argc, char** argv) glDisable(GL_TEXTURE_2D); glUseProgram(0); + glFinish(); + // Da swap-dawup! eglSwapBuffers(gl.egl_display, gl.egl_surface); - - extern void vr_context_submit_eyes(struct lvrcInstance * compositor); - - vr_context_submit_eyes(compositor); - lvrcEndFrame(compositor); } - lvrcReleaseFrameResources(compositor); - lvrcDestroyInstance(compositor); ohmd_ctx_destroy(ctx); diff --git a/examples/opengl/vr_context.c b/examples/opengl/vr_context.c deleted file mode 100644 index 7a7d896..0000000 --- a/examples/opengl/vr_context.c +++ /dev/null @@ -1,155 +0,0 @@ -#include "vr_context.h" - -#include -#include -#include - -#include - -#include - -#include - -#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); -} diff --git a/examples/opengl/vr_context.h b/examples/opengl/vr_context.h deleted file mode 100644 index b08168b..0000000 --- a/examples/opengl/vr_context.h +++ /dev/null @@ -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; diff --git a/include/lvrc.h b/include/lvrc.h index 60bcb84..e128795 100644 --- a/include/lvrc.h +++ b/include/lvrc.h @@ -3,12 +3,6 @@ #include -#ifndef __GBM__ -#define __GBM__ -#endif // __GBM__ - -#include - #include #define LVRC_API __attribute__ ((visibility ("default"))) @@ -30,31 +24,23 @@ LVRC_API void lvrcDestroyInstance(struct lvrcInstance * state); // 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 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 // -LVRC_API bool lvrcInitFrameResources(struct lvrcInstance * state); -LVRC_API bool lvrcReleaseFrameResources(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); #ifdef __cplusplus } #endif + +#ifdef __egl_h_ +# include "lvrc_EGL.h" +#endif // __egl_h_ + #endif // LINUX_VR_COMPOSITOR_H diff --git a/include/lvrc_EGL.h b/include/lvrc_EGL.h new file mode 100644 index 0000000..2c0ac90 --- /dev/null +++ b/include/lvrc_EGL.h @@ -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 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index eb23cff..e45d5b4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,11 +1,13 @@ +cmake_minimum_required(VERSION 3.10) # GLVND find_path(DRM_INCLUDE_DIR drm.h PATH_SUFFIXES drm libdrm) find_library(DRM_LIBRARY drm) +set(OpenGL_GL_PREFERENCE GLVND) find_package(OpenGL 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 "${DRM_LIBRARY}" "gbm") diff --git a/src/frame.c b/src/frame.c index fa16959..ba553f0 100644 --- a/src/frame.c +++ b/src/frame.c @@ -6,7 +6,7 @@ #include #include -#define USE_ES_SHADERS 0 +#define USE_ES_SHADERS 1 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; - - if (!internalState->swapChain) - { - return false; - } - - ohmd_device * hmd = internalState->device; + ohmd_device * hmd = instance->hmd; float viewport_scale[2]; float distortion_coeffs[4]; @@ -151,13 +144,6 @@ bool lvrcInitFrameResources(struct lvrcInstance * instance) return true; } -bool lvrcReleaseFrameResources(struct lvrcInstance * state) -{ - // TODO - - return true; -} - bool lvrcBeginFrame(struct lvrcInstance * state) { return true; // nothing yet @@ -188,13 +174,13 @@ bool lvrcSubmitFrameLeft(struct lvrcInstance * instance, GLuint texture) { Instance * internalInstance = (Instance*)instance; - if (!internalInstance->swapChain) + if (!internalInstance->mode) { return false; } - unsigned int hmd_w = internalInstance->swapChain->mode->hdisplay; - unsigned int hmd_h = internalInstance->swapChain->mode->vdisplay; + unsigned int hmd_w = internalInstance->mode->hdisplay; + unsigned int hmd_h = internalInstance->mode->vdisplay; prepare(texture); @@ -212,13 +198,13 @@ bool lvrcSubmitFrameRight(struct lvrcInstance * instance, GLuint texture) { Instance * internalInstance = (Instance*)instance; - if (!internalInstance->swapChain) + if (!internalInstance->mode) { return false; } - unsigned int hmd_w = internalInstance->swapChain->mode->hdisplay; - unsigned int hmd_h = internalInstance->swapChain->mode->vdisplay; + unsigned int hmd_w = internalInstance->mode->hdisplay; + unsigned int hmd_h = internalInstance->mode->vdisplay; prepare(texture); @@ -236,12 +222,14 @@ bool lvrcEndFrame(struct lvrcInstance * instance) { Instance * internalInstance = (Instance*)instance; - if (!internalInstance->swapChain) - { - return false; - } + eglMakeCurrent(internalInstance->vr_display, internalInstance->vr_surface, internalInstance->vr_surface, internalInstance->vr_context); - SwapBuffers(internalInstance->swapChain); + lvrcSubmitFrameLeft(instance, internalInstance->textures[0]); + lvrcSubmitFrameRight(instance, internalInstance->textures[1]); + + eglSwapBuffers(internalInstance->vr_display, internalInstance->vr_surface); + + SwapBuffers(internalInstance); return true; } diff --git a/src/frame.h b/src/frame.h index a0e4ed6..d412d17 100644 --- a/src/frame.h +++ b/src/frame.h @@ -1,5 +1,10 @@ #ifndef LINUX_VR_COMPOSITOR_FRAME_H #define LINUX_VR_COMPOSITOR_FRAME_H +#include + +#include "instance.h" + +bool InitFrameResources(Instance * instance); #endif // LINUX_VR_COMPOSITOR_FRAME_H diff --git a/src/instance.c b/src/instance.c index e5eef0e..2fe1d32 100644 --- a/src/instance.c +++ b/src/instance.c @@ -2,23 +2,331 @@ #include "lvrc_internal.h" -#include +#include +#include +#include + +#include +#include + +#if ENABLE_XCB +# include +# include +#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 -# include +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 + struct lvrcInstance * lvrcCreateInstance(ohmd_device * hmd) { Instance * instance = calloc(1, sizeof(Instance)); - instance->device = hmd; + instance->hmd = hmd; #ifdef ENABLE_XCB 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; } @@ -27,3 +335,37 @@ void lvrcDestroyInstance(struct lvrcInstance * 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; +} diff --git a/src/instance.h b/src/instance.h index 37717a2..028d134 100644 --- a/src/instance.h +++ b/src/instance.h @@ -7,19 +7,48 @@ # include #endif // ENABLE_XCB -#include "swapChain.h" +#include +#include + +#include + +#include + +#include typedef struct { - ohmd_device * device; + ohmd_device * hmd; #ifdef ENABLE_XCB xcb_connection_t * connection; int screen; #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; +void SwapBuffers(Instance * instance); + #endif // LINUX_VR_COMPOSITOR_STATE_H diff --git a/src/rendering_EGL.c b/src/rendering_EGL.c new file mode 100644 index 0000000..5f115cf --- /dev/null +++ b/src/rendering_EGL.c @@ -0,0 +1,85 @@ +#include "instance.h" +#include "frame.h" + +#include +#include + +#include "lvrc_internal.h" + +#include "context.inl" + +#include + +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; +} diff --git a/src/swapChain.c b/src/swapChain.c index 73b7fcd..190a983 100644 --- a/src/swapChain.c +++ b/src/swapChain.c @@ -3,436 +3,196 @@ #include "lvrc_internal.h" #include "instance.h" -#include +#include +#include +#include +#include -#include -#include -#include +#include -#include -#include +#include "context.inl" -#if ENABLE_XCB -# include -# include -#endif // ENABLE_XCB +#include "frame.h" -#define EDID_SIZE (0x80) - -static int drm_find_psvr_fd(SwapChain * swapChain, int fd) +typedef struct { - drmModeRes * resources = NULL; - drmModeConnector * connector = NULL; - drmModeEncoder * encoder = NULL; + int fd; + int width; + int height; + int stride; + int offset; + int fourcc; + int numplanes; + unsigned long int modifiers; +} dma_texture_params; - 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 // - - 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) +bool lvrcInitSwapChain(struct lvrcInstance * instance, unsigned int width, unsigned int height, GLuint * textures) { Instance * internalInstance = (Instance*)instance; - if (!internalInstance->device) + if (!internalInstance->user_context) { return false; } - SwapChain * swapChain = calloc(1, sizeof(SwapChain)); + eglMakeCurrent(internalInstance->user_display, internalInstance->user_surface, internalInstance->user_surface, internalInstance->user_context); -#ifdef ENABLE_XCB - if (drm_find_psvr_xcb(swapChain, internalInstance->connection, internalInstance->screen)) + EGLint imageAttribs[] = { - printf("device found using XCB\n"); - } - else -#endif // ENABLE_XCB - if (drm_find_psvr_udev(swapChain)) + EGL_WIDTH, width, + EGL_HEIGHT, height, + 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"); + + 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; } - 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; } - 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; } - 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; } bool lvrcReleaseSwapChain(struct lvrcInstance * instance) { - Instance * internalInstance = (Instance*)instance; - - if (!internalInstance->swapChain) - { - return false; - } - - // TODO : destroy resources - - free(internalInstance->swapChain); - internalInstance->swapChain = NULL; - - return true; + return false; } -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; -} diff --git a/src/swapChain.h b/src/swapChain.h index b5230e4..a5985f5 100644 --- a/src/swapChain.h +++ b/src/swapChain.h @@ -10,20 +10,8 @@ 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; -void SwapBuffers(SwapChain * swapChain); #endif // LINUX_VR_COMPOSITOR_SWAPCHAIN_H