This commit is contained in:
Twinaphex 2012-09-17 02:16:41 +02:00
commit 84f0149c86
2 changed files with 108 additions and 30 deletions

View File

@ -56,11 +56,17 @@ static drmModeModeInfo *g_drm_mode;
static uint32_t g_crtc_id; static uint32_t g_crtc_id;
static uint32_t g_connector_id; static uint32_t g_connector_id;
static drmModeCrtcPtr g_orig_crtc;
static unsigned g_fb_width; // Just use something for now. static unsigned g_fb_width; // Just use something for now.
static unsigned g_fb_height; static unsigned g_fb_height;
static struct gbm_bo *g_bo; static struct gbm_bo *g_bo;
static drmModeRes *g_resources;
static drmModeConnector *g_connector;
static drmModeEncoder *g_encoder;
struct drm_fb struct drm_fb
{ {
struct gbm_bo *bo; struct gbm_bo *bo;
@ -98,18 +104,16 @@ static void page_flip_handler(int fd, unsigned int frame, unsigned int sec, unsi
(void)sec; (void)sec;
(void)usec; (void)usec;
int *waiting = (int*)data; bool *waiting = (bool*)data;
*waiting = 0; *waiting = false;
} }
void gfx_ctx_swap_buffers(void) static void wait_vsync(void)
{ {
eglSwapBuffers(g_egl_dpy, g_egl_surf);
struct gbm_bo *next_bo = gbm_surface_lock_front_buffer(g_gbm_surface); struct gbm_bo *next_bo = gbm_surface_lock_front_buffer(g_gbm_surface);
struct drm_fb *fb = drm_fb_get_from_bo(next_bo); struct drm_fb *fb = drm_fb_get_from_bo(next_bo);
int waiting_for_flip = 1; bool waiting_for_flip = true;
int ret = drmModePageFlip(g_drm_fd, g_crtc_id, fb->fb_id, int ret = drmModePageFlip(g_drm_fd, g_crtc_id, fb->fb_id,
DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip); DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip);
@ -147,6 +151,25 @@ void gfx_ctx_swap_buffers(void)
g_bo = next_bo; g_bo = next_bo;
} }
static void nowait_vsync(void)
{
struct gbm_bo *next_bo = gbm_surface_lock_front_buffer(g_gbm_surface);
drm_fb_get_from_bo(next_bo);
gbm_surface_release_buffer(g_gbm_surface, g_bo);
g_bo = next_bo;
}
void gfx_ctx_swap_buffers(void)
{
eglSwapBuffers(g_egl_dpy, g_egl_surf);
if (g_interval)
wait_vsync();
else
nowait_vsync();
}
void gfx_ctx_set_resize(unsigned width, unsigned height) void gfx_ctx_set_resize(unsigned width, unsigned height)
{ {
(void)width; (void)width;
@ -167,16 +190,15 @@ void gfx_ctx_get_video_size(unsigned *width, unsigned *height)
bool gfx_ctx_init(void) bool gfx_ctx_init(void)
{ {
if (g_inited) if (g_inited)
{
RARCH_ERR("[KMS/EGL]: Driver does not support reinitialization yet.\n");
return false; return false;
}
static const char *modules[] = { static const char *modules[] = {
"i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", NULL "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos", NULL
}; };
drmModeRes *resources = NULL;
drmModeConnector *connector = NULL;
drmModeEncoder *encoder = NULL;
for (int i = 0; modules[i]; i++) for (int i = 0; modules[i]; i++)
{ {
RARCH_LOG("[KMS/EGL]: Trying to load module %s ...\n", modules[i]); RARCH_LOG("[KMS/EGL]: Trying to load module %s ...\n", modules[i]);
@ -194,32 +216,37 @@ bool gfx_ctx_init(void)
goto error; goto error;
} }
resources = drmModeGetResources(g_drm_fd); g_resources = drmModeGetResources(g_drm_fd);
if (!resources) if (!g_resources)
{ {
RARCH_ERR("[KMS/EGL]: Couldn't get device resources.\n"); RARCH_ERR("[KMS/EGL]: Couldn't get device resources.\n");
goto error; goto error;
} }
for (int i = 0; i < resources->count_connectors; i++) for (int i = 0; i < g_resources->count_connectors; i++)
{ {
connector = drmModeGetConnector(g_drm_fd, resources->connectors[i]); g_connector = drmModeGetConnector(g_drm_fd, g_resources->connectors[i]);
if (connector->connection == DRM_MODE_CONNECTED) if (g_connector->connection == DRM_MODE_CONNECTED)
break; break;
drmModeFreeConnector(connector); drmModeFreeConnector(g_connector);
connector = NULL; g_connector = NULL;
} }
if (!connector) // TODO: Figure out what index for crtcs to use ...
g_orig_crtc = drmModeGetCrtc(g_drm_fd, g_resources->crtcs[0]);
if (!g_orig_crtc)
RARCH_WARN("[KMS/EGL]: Cannot find original CRTC.\n");
if (!g_connector)
{ {
RARCH_ERR("[KMS/EGL]: Couldn't get device connector.\n"); RARCH_ERR("[KMS/EGL]: Couldn't get device connector.\n");
goto error; goto error;
} }
for (int i = 0, area = 0; i < connector->count_modes; i++) for (int i = 0, area = 0; i < g_connector->count_modes; i++)
{ {
drmModeModeInfo *current_mode = &connector->modes[i]; drmModeModeInfo *current_mode = &g_connector->modes[i];
int current_area = current_mode->hdisplay * current_mode->vdisplay; int current_area = current_mode->hdisplay * current_mode->vdisplay;
if (current_area > area) if (current_area > area)
{ {
@ -234,24 +261,24 @@ bool gfx_ctx_init(void)
goto error; goto error;
} }
for (int i = 0; i < resources->count_encoders; i++) for (int i = 0; i < g_resources->count_encoders; i++)
{ {
encoder = drmModeGetEncoder(g_drm_fd, resources->encoders[i]); g_encoder = drmModeGetEncoder(g_drm_fd, g_resources->encoders[i]);
if (encoder->encoder_id == connector->encoder_id) if (g_encoder->encoder_id == g_connector->encoder_id)
break; break;
drmModeFreeEncoder(encoder); drmModeFreeEncoder(g_encoder);
encoder = NULL; g_encoder = NULL;
} }
if (!encoder) if (!g_encoder)
{ {
RARCH_ERR("[KMS/EGL]: Couldn't find DRM encoder.\n"); RARCH_ERR("[KMS/EGL]: Couldn't find DRM encoder.\n");
goto error; goto error;
} }
g_crtc_id = encoder->crtc_id; g_crtc_id = g_encoder->crtc_id;
g_connector_id = connector->connector_id; g_connector_id = g_connector->connector_id;
g_fb_width = g_drm_mode->hdisplay; g_fb_width = g_drm_mode->hdisplay;
g_fb_height = g_drm_mode->vdisplay; g_fb_height = g_drm_mode->vdisplay;
@ -404,14 +431,63 @@ void gfx_ctx_destroy(void)
eglTerminate(g_egl_dpy); eglTerminate(g_egl_dpy);
} }
// Be as careful as possible in deinit.
// If we screw up, the KMS tty will not restore.
g_egl_ctx = NULL; g_egl_ctx = NULL;
g_egl_surf = NULL; g_egl_surf = NULL;
g_egl_dpy = NULL; g_egl_dpy = NULL;
g_config = 0; g_config = 0;
drmClose(g_drm_fd); // Restore original CRTC.
if (g_orig_crtc)
{
drmModeSetCrtc(g_drm_fd, g_orig_crtc->crtc_id,
g_orig_crtc->buffer_id,
g_orig_crtc->x,
g_orig_crtc->y,
&g_connector_id, 1, &g_orig_crtc->mode);
g_inited = false; drmModeFreeCrtc(g_orig_crtc);
}
if (g_gbm_surface)
gbm_surface_destroy(g_gbm_surface);
if (g_gbm_dev)
gbm_device_destroy(g_gbm_dev);
if (g_encoder)
drmModeFreeEncoder(g_encoder);
if (g_connector)
drmModeFreeConnector(g_connector);
if (g_resources)
drmModeFreeResources(g_resources);
g_gbm_surface = NULL;
g_gbm_dev = NULL;
g_encoder = NULL;
g_connector = NULL;
g_resources = NULL;
g_orig_crtc = NULL;
g_quit = 0;
g_crtc_id = 0;
g_connector_id = 0;
g_fb_width = 0;
g_fb_height = 0;
// TODO: Do we have to free this?
g_bo = NULL;
drmClose(g_drm_fd);
g_drm_fd = -1;
// Reinitialization fails for now ...
//g_inited = false;
} }
void gfx_ctx_input_driver(const input_driver_t **input, void **input_data) void gfx_ctx_input_driver(const input_driver_t **input, void **input_data)

View File

@ -324,6 +324,8 @@ bool gfx_ctx_set_video_mode(
if (g_quit_atom) if (g_quit_atom)
XSetWMProtocols(g_dpy, g_win, &g_quit_atom, 1); XSetWMProtocols(g_dpy, g_win, &g_quit_atom, 1);
gfx_suspend_screensaver(g_win);
XFree(vi); XFree(vi);
g_has_focus = true; g_has_focus = true;
g_inited = true; g_inited = true;