Update API + example
This commit is contained in:
@@ -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")
|
||||
|
||||
44
src/frame.c
44
src/frame.c
@@ -6,7 +6,7 @@
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
#ifndef 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
|
||||
|
||||
352
src/instance.c
352
src/instance.c
@@ -2,23 +2,331 @@
|
||||
|
||||
#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
|
||||
# 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
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -7,19 +7,48 @@
|
||||
# include <xcb/xcb.h>
|
||||
#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
|
||||
{
|
||||
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
|
||||
|
||||
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;
|
||||
}
|
||||
552
src/swapChain.c
552
src/swapChain.c
@@ -3,436 +3,196 @@
|
||||
#include "lvrc_internal.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 <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include "context.inl"
|
||||
|
||||
#if ENABLE_XCB
|
||||
# include <xcb/xcb.h>
|
||||
# include <xcb/randr.h>
|
||||
#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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user