Skip to content

Commit

Permalink
refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
mdevaev committed Mar 9, 2024
1 parent b00a6ff commit 7228502
Showing 1 changed file with 108 additions and 94 deletions.
202 changes: 108 additions & 94 deletions src/v4p/drm.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,10 @@

static void _drm_vsync_callback(int fd, uint n_frame, uint sec, uint usec, void *v_buf);
static int _drm_check_status(us_drm_s *drm);
static int _drm_find_sink(us_drm_s *drm, uint width, uint height, float hz);
static int _drm_init_buffers(us_drm_s *drm, const us_device_s *dev);
static int _drm_find_sink(us_drm_s *drm, uint width, uint height, float hz);

static drmModeModeInfo *_find_best_mode(drmModeConnector *conn, uint width, uint height, float hz);
static u32 _find_crtc(int fd, drmModeRes *res, drmModeConnector *conn, u32 *taken_crtcs);
static const char *_connector_type_to_string(u32 type);
static float _get_refresh_rate(const drmModeModeInfo *mode);
Expand Down Expand Up @@ -411,6 +412,79 @@ static int _drm_check_status(us_drm_s *drm) {
return -1;
}

static int _drm_init_buffers(us_drm_s *drm, const us_device_s *dev) {
us_drm_runtime_s *const run = drm->run;

const uint n_bufs = (dev == NULL ? 4 : dev->run->n_bufs);
const char *name = (dev == NULL ? "STUB" : "DMA");

_D_LOG_DEBUG("Initializing %u %s buffers ...", n_bufs, name);

US_CALLOC(run->bufs, n_bufs);
for (run->n_bufs = 0; run->n_bufs < n_bufs; ++run->n_bufs) {
const uint n_buf = run->n_bufs;
us_drm_buffer_s *const buf = &run->bufs[n_buf];

buf->ctx.has_vsync = &run->has_vsync;

u32 handles[4] = {0};
u32 strides[4] = {0};
u32 offsets[4] = {0};

if (dev == NULL) {
struct drm_mode_create_dumb create = {
.width = run->mode.hdisplay,
.height = run->mode.vdisplay,
.bpp = 24,
};
if (drmIoctl(run->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create) < 0) {
_D_LOG_PERROR("Can't create %s buffer=%u", name, n_buf);
return -1;
}
buf->handle = create.handle;
buf->dumb_created = true;

struct drm_mode_map_dumb map = {.handle = create.handle};
if (drmIoctl(run->fd, DRM_IOCTL_MODE_MAP_DUMB, &map) < 0) {
_D_LOG_PERROR("Can't prepare dumb buffer=%u to mapping", n_buf);
return -1;
}
if ((buf->data = mmap(
NULL, create.size,
PROT_READ | PROT_WRITE, MAP_SHARED,
run->fd, map.offset
)) == MAP_FAILED) {
_D_LOG_PERROR("Can't map buffer=%u", n_buf);
return -1;
}
memset(buf->data, 0, create.size);
buf->allocated = create.size;

handles[0] = create.handle;
strides[0] = create.pitch;

} else {
if (drmPrimeFDToHandle(run->fd, dev->run->hw_bufs[n_buf].dma_fd, &buf->handle) < 0) {
_D_LOG_PERROR("Can't import DMA buffer=%u from capture device", n_buf);
return -1;
}
handles[0] = buf->handle;
strides[0] = dev->run->stride;
}

if (drmModeAddFB2(
run->fd,
run->mode.hdisplay, run->mode.vdisplay, DRM_FORMAT_RGB888,
handles, strides, offsets, &buf->id, 0
)) {
_D_LOG_PERROR("Can't setup buffer=%u", n_buf);
return -1;
}
buf->fb_added = true;
}
return 0;
}

static int _drm_find_sink(us_drm_s *drm, uint width, uint height, float hz) {
us_drm_runtime_s *const run = drm->run;

Expand Down Expand Up @@ -452,34 +526,8 @@ static int _drm_find_sink(us_drm_s *drm, uint width, uint height, float hz) {
goto done;
}

drmModeModeInfo *best = NULL;
drmModeModeInfo *closest = NULL;
drmModeModeInfo *pref = NULL;
for (int mi = 0; mi < conn->count_modes; ++mi) {
drmModeModeInfo *const mode = &conn->modes[mi];
if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
continue; // Paranoia for size and discard interlaced
}
const float mode_hz = _get_refresh_rate(mode);
if (mode->hdisplay == width && mode->vdisplay == height) {
best = mode; // Any mode with exact resolution
if (hz > 0 && mode_hz == hz) {
break; // Exact mode with same freq
}
}
if (mode->hdisplay == width && mode->vdisplay < height) {
if (closest == NULL || _get_refresh_rate(closest) != hz) {
closest = mode; // Something like 1920x1080p60 for 1920x1200p60 source
}
}
if (pref == NULL && (mode->type & DRM_MODE_TYPE_PREFERRED)) {
pref = mode; // Preferred mode if nothing is found
}
}
if (best == NULL) { best = closest; }
if (best == NULL) { best = pref; }
if (best == NULL) { best = (conn->count_modes > 0 ? &conn->modes[0] : NULL); }
if (best == NULL) {
drmModeModeInfo *best;
if ((best = _find_best_mode(conn, width, height, hz)) == NULL) {
_D_LOG_ERROR("Can't find any appropriate display modes");
drmModeFreeConnector(conn);
goto unplugged;
Expand Down Expand Up @@ -512,77 +560,43 @@ static int _drm_find_sink(us_drm_s *drm, uint width, uint height, float hz) {
return -2;
}

static int _drm_init_buffers(us_drm_s *drm, const us_device_s *dev) {
us_drm_runtime_s *const run = drm->run;

const uint n_bufs = (dev == NULL ? 4 : dev->run->n_bufs);
const char *name = (dev == NULL ? "STUB" : "DMA");

_D_LOG_DEBUG("Initializing %u %s buffers ...", n_bufs, name);

US_CALLOC(run->bufs, n_bufs);
for (run->n_bufs = 0; run->n_bufs < n_bufs; ++run->n_bufs) {
const uint n_buf = run->n_bufs;
us_drm_buffer_s *const buf = &run->bufs[n_buf];

buf->ctx.has_vsync = &run->has_vsync;

u32 handles[4] = {0};
u32 strides[4] = {0};
u32 offsets[4] = {0};
static drmModeModeInfo *_find_best_mode(drmModeConnector *conn, uint width, uint height, float hz) {
drmModeModeInfo *best = NULL;
drmModeModeInfo *closest = NULL;
drmModeModeInfo *pref = NULL;

if (dev == NULL) {
struct drm_mode_create_dumb create = {
.width = run->mode.hdisplay,
.height = run->mode.vdisplay,
.bpp = 24,
};
if (drmIoctl(run->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create) < 0) {
_D_LOG_PERROR("Can't create %s buffer=%u", name, n_buf);
return -1;
}
buf->handle = create.handle;
buf->dumb_created = true;

struct drm_mode_map_dumb map = {.handle = create.handle};
if (drmIoctl(run->fd, DRM_IOCTL_MODE_MAP_DUMB, &map) < 0) {
_D_LOG_PERROR("Can't prepare dumb buffer=%u to mapping", n_buf);
return -1;
}
if ((buf->data = mmap(
NULL, create.size,
PROT_READ | PROT_WRITE, MAP_SHARED,
run->fd, map.offset
)) == MAP_FAILED) {
_D_LOG_PERROR("Can't map buffer=%u", n_buf);
return -1;
for (int mi = 0; mi < conn->count_modes; ++mi) {
drmModeModeInfo *const mode = &conn->modes[mi];
if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
continue; // Discard interlaced
}
const float mode_hz = _get_refresh_rate(mode);
if (mode->hdisplay == width && mode->vdisplay == height) {
best = mode; // Any mode with exact resolution
if (hz > 0 && mode_hz == hz) {
break; // Exact mode with same freq
}
memset(buf->data, 0, create.size);
buf->allocated = create.size;

handles[0] = create.handle;
strides[0] = create.pitch;

} else {
if (drmPrimeFDToHandle(run->fd, dev->run->hw_bufs[n_buf].dma_fd, &buf->handle) < 0) {
_D_LOG_PERROR("Can't import DMA buffer=%u from capture device", n_buf);
return -1;
}
if (mode->hdisplay == width && mode->vdisplay < height) {
if (closest == NULL || _get_refresh_rate(closest) != hz) {
closest = mode; // Something like 1920x1080p60 for 1920x1200p60 source
}
handles[0] = buf->handle;
strides[0] = dev->run->stride;
}

if (drmModeAddFB2(
run->fd,
run->mode.hdisplay, run->mode.vdisplay, DRM_FORMAT_RGB888,
handles, strides, offsets, &buf->id, 0
)) {
_D_LOG_PERROR("Can't setup buffer=%u", n_buf);
return -1;
if (pref == NULL && (mode->type & DRM_MODE_TYPE_PREFERRED)) {
pref = mode; // Preferred mode if nothing is found
}
buf->fb_added = true;
}
return 0;

if (best == NULL) {
best = closest;
}
if (best == NULL) {
best = pref;
}
if (best == NULL) {
best = (conn->count_modes > 0 ? &conn->modes[0] : NULL);
}
return best;
}

static u32 _find_crtc(int fd, drmModeRes *res, drmModeConnector *conn, u32 *taken_crtcs) {
Expand Down

0 comments on commit 7228502

Please sign in to comment.