Move more common code to drm_common.c

This commit is contained in:
twinaphex 2015-11-26 17:30:01 +01:00
parent 8f9c652693
commit e06121b661
4 changed files with 114 additions and 134 deletions

View File

@ -16,8 +16,15 @@
#include "drm_common.h" #include "drm_common.h"
uint32_t g_connector_id; uint32_t g_connector_id;
drmModeCrtc *g_orig_crtc;
int g_drm_fd; int g_drm_fd;
uint32_t g_crtc_id;
drmModeCrtc *g_orig_crtc;
drmModeRes *g_drm_resources;
drmModeConnector *g_drm_connector;
drmModeEncoder *g_drm_encoder;
drmModeModeInfo *g_drm_mode;
/* Restore the original CRTC. */ /* Restore the original CRTC. */
void drm_restore_crtc(void) void drm_restore_crtc(void)

View File

@ -26,8 +26,14 @@ extern "C" {
#endif #endif
extern uint32_t g_connector_id; extern uint32_t g_connector_id;
extern drmModeCrtc *g_orig_crtc;
extern int g_drm_fd; extern int g_drm_fd;
extern uint32_t g_crtc_id;
extern drmModeCrtc *g_orig_crtc;
extern drmModeRes *g_drm_resources;
extern drmModeConnector *g_drm_connector;
extern drmModeEncoder *g_drm_encoder;
extern drmModeModeInfo *g_drm_mode;
/* Restore the original CRTC. */ /* Restore the original CRTC. */
void drm_restore_crtc(void); void drm_restore_crtc(void);

View File

@ -115,21 +115,11 @@ struct exynos_fliphandler
drmEventContext evctx; drmEventContext evctx;
}; };
struct exynos_drm
{
drmModeRes *resources;
drmModeConnector *connector;
drmModeEncoder *encoder;
drmModeModeInfo *mode;
uint32_t crtc_id;
};
struct exynos_data struct exynos_data
{ {
char drmname[32]; char drmname[32];
struct exynos_device *device; struct exynos_device *device;
struct exynos_drm *drm;
struct exynos_fliphandler *fliphandler; struct exynos_fliphandler *fliphandler;
/* G2D is used for scaling to framebuffer dimensions. */ /* G2D is used for scaling to framebuffer dimensions. */
@ -208,17 +198,16 @@ static int exynos_get_device_index(void)
} }
static void exynos_clean_up_drm(struct exynos_drm *d, int fd) static void exynos_clean_up_drm(void)
{ {
if (d->encoder) if (g_drm_encoder)
drmModeFreeEncoder(d->encoder); drmModeFreeEncoder(g_drm_encoder);
if (d->connector) if (g_drm_connector)
drmModeFreeConnector(d->connector); drmModeFreeConnector(g_drm_connector);
if (d->resources) if (g_drm_resources)
drmModeFreeResources(d->resources); drmModeFreeResources(g_drm_resources);
free(d); close(g_drm_fd);
close(fd);
} }
/* The main pageflip handler, which the DRM executes /* The main pageflip handler, which the DRM executes
@ -597,58 +586,49 @@ static int exynos_open(struct exynos_data *pdata)
return -1; return -1;
} }
drm = (struct exynos_drm*)calloc(1, sizeof(struct exynos_drm)); g_drm_resources = drmModeGetResources(fd);
if (!g_drm_resources)
if (!drm)
{
RARCH_ERR("[video_exynos]: failed to allocate DRM.\n");
close(fd);
return -1;
}
drm->resources = drmModeGetResources(fd);
if (!drm->resources)
{ {
RARCH_ERR("[video_exynos]: failed to get DRM resources\n"); RARCH_ERR("[video_exynos]: failed to get DRM resources\n");
goto fail; goto fail;
} }
for (i = 0; i < drm->resources->count_connectors; ++i) for (i = 0; i < g_drm_resources->count_connectors; ++i)
{ {
if (settings->video.monitor_index != 0 && if (settings->video.monitor_index != 0 &&
settings->video.monitor_index - 1 != i) settings->video.monitor_index - 1 != i)
continue; continue;
drm->connector = drmModeGetConnector(fd, drm->resources->connectors[i]); g_drm_connector = drmModeGetConnector(fd, g_drm_resources->connectors[i]);
if (!drm->connecto) if (!drm->connecto)
continue; continue;
if (drm->connector->connection == DRM_MODE_CONNECTED && if (g_drm_connector->connection == DRM_MODE_CONNECTED &&
drm->connector->count_modes > 0) g_drm_connector->count_modes > 0)
break; break;
drmModeFreeConnector(drm->connector); drmModeFreeConnector(g_drm_connector);
drm->connector = NULL; g_drm_connector = NULL;
} }
if (i == drm->resources->count_connectors) if (i == g_drm_resources->count_connectors)
{ {
RARCH_ERR("[video_exynos]: no currently active connector found.\n"); RARCH_ERR("[video_exynos]: no currently active connector found.\n");
goto fail; goto fail;
} }
for (i = 0; i < drm->resources->count_encoders; i++) for (i = 0; i < g_drm_resources->count_encoders; i++)
{ {
drm->encoder = drmModeGetEncoder(fd, drm->resources->encoders[i]); g_drm_encoder = drmModeGetEncoder(fd, g_drm_resources->encoders[i]);
if (!drm->encoder) if (!g_drm_encoder)
continue; continue;
if (drm->encoder->encoder_id == drm->connector->encoder_id) if (g_drm_encoder->encoder_id == g_drm_connector->encoder_id)
break; break;
drmModeFreeEncoder(drm->encoder); drmModeFreeEncoder(g_drm_encoder);
drm->encoder = NULL; g_drm_encoder = NULL;
} }
fliphandler = (struct exynos_fliphandler*)calloc(1, sizeof(struct exynos_fliphandler)); fliphandler = (struct exynos_fliphandler*)calloc(1, sizeof(struct exynos_fliphandler));
@ -668,17 +648,16 @@ static int exynos_open(struct exynos_data *pdata)
strncpy(pdata->drmname, buf, sizeof(buf)); strncpy(pdata->drmname, buf, sizeof(buf));
g_drm_fd = fd; g_drm_fd = fd;
pdata->drm = drm;
pdata->fliphandler = fliphandler; pdata->fliphandler = fliphandler;
RARCH_LOG("[video_exynos]: using DRM device \"%s\" with connector id %u.\n", RARCH_LOG("[video_exynos]: using DRM device \"%s\" with connector id %u.\n",
pdata->drmname, pdata->drm->connector->connector_id); pdata->drmname, g_drm_connector->connector_id);
return 0; return 0;
fail: fail:
free(fliphandler); free(fliphandler);
exynos_clean_up_drm(drm, fd); exynos_clean_up_drm();
return -1; return -1;
} }
@ -691,31 +670,29 @@ static void exynos_close(struct exynos_data *pdata)
memset(pdata->drmname, 0, sizeof(char) * 32); memset(pdata->drmname, 0, sizeof(char) * 32);
exynos_clean_up_drm(pdata->drm, g_drm_fd); exynos_clean_up_drm();
g_drm_fd = -1; g_drm_fd = -1;
pdata->drm = NULL;
} }
static int exynos_init(struct exynos_data *pdata, unsigned bpp) static int exynos_init(struct exynos_data *pdata, unsigned bpp)
{ {
unsigned i; unsigned i;
struct exynos_drm *drm = pdata->drm;
settings_t *settings = config_get_ptr(); settings_t *settings = config_get_ptr();
if (settings->video.fullscreen_x != 0 && if (settings->video.fullscreen_x != 0 &&
settings->video.fullscreen_y != 0) settings->video.fullscreen_y != 0)
{ {
for (i = 0; i < drm->connector->count_modes; i++) for (i = 0; i < g_drm_connector->count_modes; i++)
{ {
if (drm->connector->modes[i].hdisplay == settings->video.fullscreen_x && if (g_drm_connector->modes[i].hdisplay == settings->video.fullscreen_x &&
drm->connector->modes[i].vdisplay == settings->video.fullscreen_y) g_drm_connector->modes[i].vdisplay == settings->video.fullscreen_y)
{ {
drm->mode = &drm->connector->modes[i]; g_drm_mode = &g_drm_connector->modes[i];
break; break;
} }
} }
if (!drm->mode) if (!g_drm_mode)
{ {
RARCH_ERR("[video_exynos]: requested resolution (%ux%u) not available\n", RARCH_ERR("[video_exynos]: requested resolution (%ux%u) not available\n",
settings->video.fullscreen_x, settings->video.fullscreen_y); settings->video.fullscreen_x, settings->video.fullscreen_y);
@ -726,26 +703,26 @@ static int exynos_init(struct exynos_data *pdata, unsigned bpp)
else else
{ {
/* Select first mode, which is the native one. */ /* Select first mode, which is the native one. */
drm->mode = &drm->connector->modes[0]; g_drm_mode = &g_drm_connector->modes[0];
} }
if (drm->mode->hdisplay == 0 || drm->mode->vdisplay == 0) if (g_drm_mode->hdisplay == 0 || g_drm_mode->vdisplay == 0)
{ {
RARCH_ERR("[video_exynos]: failed to select sane resolution\n"); RARCH_ERR("[video_exynos]: failed to select sane resolution\n");
goto fail; goto fail;
} }
drm->crtc_id = drm->encoder->crtc_id; g_crtc_id = g_drm_encoder->crtc_id;
g_connector_id = drm->connector->connector_id; g_connector_id = g_drm_connector->connector_id;
g_orig_crtc = drmModeGetCrtc(g_drm_fd, drm->crtc_id); g_orig_crtc = drmModeGetCrtc(g_drm_fd, g_crtc_id);
if (!g_orig_crtc) if (!g_orig_crtc)
RARCH_WARN("[video_exynos]: cannot find original crtc\n"); RARCH_WARN("[video_exynos]: cannot find original crtc\n");
pdata->width = drm->mode->hdisplay; pdata->width = g_drm_mode->hdisplay;
pdata->height = drm->mode->vdisplay; pdata->height = g_drm_mode->vdisplay;
pdata->aspect = (float)drm->mode->hdisplay / (float)drm->mode->vdisplay; pdata->aspect = (float)g_drm_mode->hdisplay / (float)g_drm_mode->vdisplay;
/* Always use triple buffering to reduce chance of tearing. */ /* Always use triple buffering to reduce chance of tearing. */
pdata->num_pages = 3; pdata->num_pages = 3;
@ -762,7 +739,7 @@ static int exynos_init(struct exynos_data *pdata, unsigned bpp)
fail: fail:
drm_restore_crtc(); drm_restore_crtc();
drm->mode = NULL; g_drm_mode = NULL;
return -1; return -1;
} }
@ -770,12 +747,8 @@ fail:
/* Counterpart to exynos_init. */ /* Counterpart to exynos_init. */
static void exynos_deinit(struct exynos_data *pdata) static void exynos_deinit(struct exynos_data *pdata)
{ {
struct exynos_drm *drm = pdata->drm;
drm_restore_crtc(); drm_restore_crtc();
drm = NULL;
pdata->width = 0; pdata->width = 0;
pdata->height = 0; pdata->height = 0;
pdata->num_pages = 0; pdata->num_pages = 0;
@ -867,9 +840,9 @@ static int exynos_alloc(struct exynos_data *pdata)
} }
/* Setup CRTC: display the last allocated page. */ /* Setup CRTC: display the last allocated page. */
if (drmModeSetCrtc(g_drm_fd, pdata->drm->crtc_id, if (drmModeSetCrtc(g_drm_fd, g_crtc_id,
pages[pdata->num_pages - 1].buf_id, pages[pdata->num_pages - 1].buf_id,
0, 0, &pdata->drm->connector_id, 1, pdata->drm->mode)) 0, 0, &g_drm_connector_id, 1, g_drm_mode))
{ {
RARCH_ERR("[video_exynos]: initial CRTC setup failed.\n"); RARCH_ERR("[video_exynos]: initial CRTC setup failed.\n");
goto fail; goto fail;
@ -895,7 +868,7 @@ static void exynos_free(struct exynos_data *pdata)
unsigned i; unsigned i;
/* Disable the CRTC. */ /* Disable the CRTC. */
if (drmModeSetCrtc(g_drm_fd, pdata->drm->crtc_id, 0, if (drmModeSetCrtc(g_drm_fd, g_crtc_id, 0,
0, 0, NULL, 0, NULL)) 0, 0, NULL, 0, NULL))
RARCH_WARN("[video_exynos]: failed to disable the CRTC.\n"); RARCH_WARN("[video_exynos]: failed to disable the CRTC.\n");
@ -1116,7 +1089,7 @@ static int exynos_flip(struct exynos_data *pdata, struct exynos_page *page)
exynos_wait_flip(pdata->fliphandler); exynos_wait_flip(pdata->fliphandler);
/* Issue a page flip at the next vblank interval. */ /* Issue a page flip at the next vblank interval. */
if (drmModePageFlip(g_drm_fd, pdata->drm->crtc_id, page->buf_id, if (drmModePageFlip(g_drm_fd, g_crtc_id, page->buf_id,
DRM_MODE_PAGE_FLIP_EVENT, page) != 0) DRM_MODE_PAGE_FLIP_EVENT, page) != 0)
{ {
RARCH_ERR("[video_exynos]: failed to issue page flip\n"); RARCH_ERR("[video_exynos]: failed to issue page flip\n");

View File

@ -55,15 +55,9 @@
typedef struct gfx_ctx_drm_egl_data typedef struct gfx_ctx_drm_egl_data
{ {
RFILE *g_drm; RFILE *g_drm;
uint32_t g_crtc_id;
unsigned g_fb_width; unsigned g_fb_width;
unsigned g_fb_height; unsigned g_fb_height;
drmModeModeInfo *g_drm_mode;
drmModeRes *g_resources;
drmModeConnector *g_connector;
drmModeEncoder *g_encoder;
struct gbm_bo *g_bo; struct gbm_bo *g_bo;
struct gbm_bo *g_next_bo; struct gbm_bo *g_next_bo;
struct gbm_device *g_gbm_dev; struct gbm_device *g_gbm_dev;
@ -225,7 +219,7 @@ static bool queue_flip(gfx_ctx_drm_egl_data_t *drm)
fb = (struct drm_fb*)drm_fb_get_from_bo(drm, drm->g_next_bo); fb = (struct drm_fb*)drm_fb_get_from_bo(drm, drm->g_next_bo);
if (drmModePageFlip(g_drm_fd, drm->g_crtc_id, fb->fb_id, if (drmModePageFlip(g_drm_fd, g_crtc_id, fb->fb_id,
DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip) == 0) DRM_MODE_PAGE_FLIP_EVENT, &waiting_for_flip) == 0)
return true; return true;
@ -304,23 +298,23 @@ static void free_drm_resources(gfx_ctx_drm_egl_data_t *drm)
if (drm->g_gbm_dev) if (drm->g_gbm_dev)
gbm_device_destroy(drm->g_gbm_dev); gbm_device_destroy(drm->g_gbm_dev);
if (drm->g_encoder) if (g_drm_encoder)
drmModeFreeEncoder(drm->g_encoder); drmModeFreeEncoder(g_drm_encoder);
if (drm->g_connector) if (g_drm_connector)
drmModeFreeConnector(drm->g_connector); drmModeFreeConnector(g_drm_connector);
if (drm->g_resources) if (g_drm_resources)
drmModeFreeResources(drm->g_resources); drmModeFreeResources(g_drm_resources);
if (g_drm_fd >= 0) if (g_drm_fd >= 0)
retro_fclose(drm->g_drm); retro_fclose(drm->g_drm);
drm->g_gbm_surface = NULL; drm->g_gbm_surface = NULL;
drm->g_gbm_dev = NULL; drm->g_gbm_dev = NULL;
drm->g_encoder = NULL; g_drm_encoder = NULL;
drm->g_connector = NULL; g_drm_connector = NULL;
drm->g_resources = NULL; g_drm_resources = NULL;
g_drm_fd = -1; g_drm_fd = -1;
} }
@ -338,8 +332,8 @@ static void gfx_ctx_drm_egl_destroy_resources(gfx_ctx_drm_egl_data_t *drm)
drm_restore_crtc(); drm_restore_crtc();
free_drm_resources(drm); free_drm_resources(drm);
drm->g_drm_mode = NULL; g_drm_mode = NULL;
drm->g_crtc_id = 0; g_crtc_id = 0;
g_connector_id = 0; g_connector_id = 0;
drm->g_fb_width = 0; drm->g_fb_width = 0;
@ -386,8 +380,8 @@ nextgpu:
g_drm_fd = retro_get_fd(drm->g_drm); g_drm_fd = retro_get_fd(drm->g_drm);
drm->g_resources = drmModeGetResources(g_drm_fd); g_drm_resources = drmModeGetResources(g_drm_fd);
if (!drm->g_resources) if (!g_drm_resources)
{ {
RARCH_WARN("[KMS/EGL]: Couldn't get device resources.\n"); RARCH_WARN("[KMS/EGL]: Couldn't get device resources.\n");
goto nextgpu; goto nextgpu;
@ -396,12 +390,12 @@ nextgpu:
/* Enumerate all connectors. */ /* Enumerate all connectors. */
monitor_index = 0; monitor_index = 0;
RARCH_LOG("[KMS/EGL]: Found %d connectors.\n", RARCH_LOG("[KMS/EGL]: Found %d connectors.\n",
drm->g_resources->count_connectors); g_drm_resources->count_connectors);
for (i = 0; i < drm->g_resources->count_connectors; i++) for (i = 0; i < g_drm_resources->count_connectors; i++)
{ {
drmModeConnectorPtr conn = drmModeGetConnector( drmModeConnectorPtr conn = drmModeGetConnector(
g_drm_fd, drm->g_resources->connectors[i]); g_drm_fd, g_drm_resources->connectors[i]);
if (conn) if (conn)
{ {
@ -418,72 +412,72 @@ nextgpu:
} }
monitor_index = 0; monitor_index = 0;
for (i = 0; i < drm->g_resources->count_connectors; i++) for (i = 0; i < g_drm_resources->count_connectors; i++)
{ {
drm->g_connector = drmModeGetConnector(g_drm_fd, g_drm_connector = drmModeGetConnector(g_drm_fd,
drm->g_resources->connectors[i]); g_drm_resources->connectors[i]);
if (!drm->g_connector) if (!g_drm_connector)
continue; continue;
if (drm->g_connector->connection == DRM_MODE_CONNECTED if (g_drm_connector->connection == DRM_MODE_CONNECTED
&& drm->g_connector->count_modes > 0) && g_drm_connector->count_modes > 0)
{ {
monitor_index++; monitor_index++;
if (monitor_index == monitor) if (monitor_index == monitor)
break; break;
} }
drmModeFreeConnector(drm->g_connector); drmModeFreeConnector(g_drm_connector);
drm->g_connector = NULL; g_drm_connector = NULL;
} }
if (!drm->g_connector) if (!g_drm_connector)
{ {
RARCH_WARN("[KMS/EGL]: Couldn't get device connector.\n"); RARCH_WARN("[KMS/EGL]: Couldn't get device connector.\n");
goto nextgpu; goto nextgpu;
} }
for (i = 0; i < drm->g_resources->count_encoders; i++) for (i = 0; i < g_drm_resources->count_encoders; i++)
{ {
drm->g_encoder = drmModeGetEncoder(g_drm_fd, g_drm_encoder = drmModeGetEncoder(g_drm_fd,
drm->g_resources->encoders[i]); g_drm_resources->encoders[i]);
if (!drm->g_encoder) if (!g_drm_encoder)
continue; continue;
if (drm->g_encoder->encoder_id == drm->g_connector->encoder_id) if (g_drm_encoder->encoder_id == g_drm_connector->encoder_id)
break; break;
drmModeFreeEncoder(drm->g_encoder); drmModeFreeEncoder(g_drm_encoder);
drm->g_encoder = NULL; g_drm_encoder = NULL;
} }
if (!drm->g_encoder) if (!g_drm_encoder)
{ {
RARCH_WARN("[KMS/EGL]: Couldn't find DRM encoder.\n"); RARCH_WARN("[KMS/EGL]: Couldn't find DRM encoder.\n");
goto nextgpu; goto nextgpu;
} }
for (i = 0; i < drm->g_connector->count_modes; i++) for (i = 0; i < g_drm_connector->count_modes; i++)
{ {
RARCH_LOG("[KMS/EGL]: Mode %d: (%s) %d x %d, %u Hz\n", RARCH_LOG("[KMS/EGL]: Mode %d: (%s) %d x %d, %u Hz\n",
i, i,
drm->g_connector->modes[i].name, g_drm_connector->modes[i].name,
drm->g_connector->modes[i].hdisplay, g_drm_connector->modes[i].hdisplay,
drm->g_connector->modes[i].vdisplay, g_drm_connector->modes[i].vdisplay,
drm->g_connector->modes[i].vrefresh); g_drm_connector->modes[i].vrefresh);
} }
drm->g_crtc_id = drm->g_encoder->crtc_id; g_crtc_id = g_drm_encoder->crtc_id;
g_orig_crtc = drmModeGetCrtc(g_drm_fd, drm->g_crtc_id); g_orig_crtc = drmModeGetCrtc(g_drm_fd, g_crtc_id);
if (!g_orig_crtc) if (!g_orig_crtc)
RARCH_WARN("[KMS/EGL]: Cannot find original CRTC.\n"); RARCH_WARN("[KMS/EGL]: Cannot find original CRTC.\n");
g_connector_id = drm->g_connector->connector_id; g_connector_id = g_drm_connector->connector_id;
/* First mode is assumed to be the "optimal" /* First mode is assumed to be the "optimal"
* one for get_video_size() purposes. */ * one for get_video_size() purposes. */
drm->g_fb_width = drm->g_connector->modes[0].hdisplay; drm->g_fb_width = g_drm_connector->modes[0].hdisplay;
drm->g_fb_height = drm->g_connector->modes[0].vdisplay; drm->g_fb_height = g_drm_connector->modes[0].vdisplay;
drm->g_gbm_dev = gbm_create_device(g_drm_fd); drm->g_gbm_dev = gbm_create_device(g_drm_fd);
@ -654,7 +648,7 @@ static bool gfx_ctx_drm_egl_set_video_mode(void *data,
* If not fullscreen, we get desired windowed size, * If not fullscreen, we get desired windowed size,
* which is not appropriate. */ * which is not appropriate. */
if ((width == 0 && height == 0) || !fullscreen) if ((width == 0 && height == 0) || !fullscreen)
drm->g_drm_mode = &drm->g_connector->modes[0]; g_drm_mode = &g_drm_connector->modes[0];
else else
{ {
/* Try to match settings->video.refresh_rate as closely as possible. /* Try to match settings->video.refresh_rate as closely as possible.
@ -664,32 +658,32 @@ static bool gfx_ctx_drm_egl_set_video_mode(void *data,
float minimum_fps_diff = 0.0f; float minimum_fps_diff = 0.0f;
/* Find best match. */ /* Find best match. */
for (i = 0; i < drm->g_connector->count_modes; i++) for (i = 0; i < g_drm_connector->count_modes; i++)
{ {
float diff; float diff;
if (width != drm->g_connector->modes[i].hdisplay || if (width != g_drm_connector->modes[i].hdisplay ||
height != drm->g_connector->modes[i].vdisplay) height != g_drm_connector->modes[i].vdisplay)
continue; continue;
diff = fabsf(refresh_mod * drm->g_connector->modes[i].vrefresh diff = fabsf(refresh_mod * g_drm_connector->modes[i].vrefresh
- settings->video.refresh_rate); - settings->video.refresh_rate);
if (!drm->g_drm_mode || diff < minimum_fps_diff) if (!g_drm_mode || diff < minimum_fps_diff)
{ {
drm->g_drm_mode = &drm->g_connector->modes[i]; g_drm_mode = &g_drm_connector->modes[i];
minimum_fps_diff = diff; minimum_fps_diff = diff;
} }
} }
} }
if (!drm->g_drm_mode) if (!g_drm_mode)
{ {
RARCH_ERR("[KMS/EGL]: Did not find suitable video mode for %u x %u.\n", width, height); RARCH_ERR("[KMS/EGL]: Did not find suitable video mode for %u x %u.\n", width, height);
goto error; goto error;
} }
drm->g_fb_width = drm->g_drm_mode->hdisplay; drm->g_fb_width = g_drm_mode->hdisplay;
drm->g_fb_height = drm->g_drm_mode->vdisplay; drm->g_fb_height = g_drm_mode->vdisplay;
/* Create GBM surface. */ /* Create GBM surface. */
drm->g_gbm_surface = gbm_surface_create( drm->g_gbm_surface = gbm_surface_create(
@ -732,7 +726,7 @@ static bool gfx_ctx_drm_egl_set_video_mode(void *data,
fb = drm_fb_get_from_bo(drm, drm->g_bo); fb = drm_fb_get_from_bo(drm, drm->g_bo);
ret = drmModeSetCrtc(g_drm_fd, ret = drmModeSetCrtc(g_drm_fd,
drm->g_crtc_id, fb->fb_id, 0, 0, &g_connector_id, 1, drm->g_drm_mode); g_crtc_id, fb->fb_id, 0, 0, &g_connector_id, 1, g_drm_mode);
if (ret < 0) if (ret < 0)
goto error; goto error;