diff --git a/include/exstubs.h b/include/exstubs.h index 81d4636a..384ff884 100644 --- a/include/exstubs.h +++ b/include/exstubs.h @@ -119,12 +119,6 @@ typedef struct _DrmSurfaceBuffer { */ uint32_t fb_id; - /** - * The DMA buffer index if the buffer was allocated via drmDMA(). - * Since 5.0.13. - */ - int dma_idx; - /** The DRM format of the buffer. */ uint32_t drm_format; /** The bits per pixel */ diff --git a/src/newgal/drm/drmvideo.c b/src/newgal/drm/drmvideo.c index ea94ef2a..511e3346 100644 --- a/src/newgal/drm/drmvideo.c +++ b/src/newgal/drm/drmvideo.c @@ -58,12 +58,14 @@ #include #include #include +#include #include #include #include #include #include #include +#include #include "minigui.h" #include "newgal.h" @@ -73,6 +75,14 @@ #include "pixels_c.h" #include "drmvideo.h" +#ifndef DRM_RDWR +#define DRM_RDWR O_RDWR +#endif + +#ifndef DRM_CLOEXEC +#define DRM_CLOEXEC O_CLOEXEC +#endif + #ifdef _MGRM_PROCESSES #include "client.h" #include "sharedres.h" @@ -110,7 +120,6 @@ static int DRM_FillHWRect_Accl(_THIS, GAL_Surface *dst, GAL_Rect *rect, static void DRM_UpdateRects(_THIS, int numrects, GAL_Rect *rects); static BOOL DRM_SyncUpdate(_THIS); -static BOOL DRM_SyncUpdateDMA(_THIS); static int DRM_SetHWColorKey_Accl(_THIS, GAL_Surface *surface, Uint32 key); static int DRM_SetHWAlpha_Accl(_THIS, GAL_Surface *surface, Uint8 value); @@ -1317,14 +1326,10 @@ static GAL_VideoDevice *DRM_CreateDevice(int devindex) } #endif /* IS_COMPOSITING_SCHEMA */ - if (device->hidden->dbl_buff == DRM_DBLBUF_MEMCPY) { + if (device->hidden->dbl_buff) { device->UpdateRects = DRM_UpdateRects; device->SyncUpdate = DRM_SyncUpdate; } - else if (device->hidden->dbl_buff == DRM_DBLBUF_DMA) { - device->UpdateRects = DRM_UpdateRects; - device->SyncUpdate = DRM_SyncUpdateDMA; - } device->VideoInit = DRM_VideoInit; device->ListModes = DRM_ListModes; @@ -2050,7 +2055,6 @@ static DrmSurfaceBuffer *drm_create_dumb_buffer(DrmVideoData* vdata, surface_buffer->prime_fd = -1; surface_buffer->name = 0; surface_buffer->fb_id = 0; - surface_buffer->dma_idx = -1; surface_buffer->drm_format = drm_format; surface_buffer->width = creq.width; surface_buffer->height = creq.height - nr_header_lines; @@ -2061,11 +2065,11 @@ static DrmSurfaceBuffer *drm_create_dumb_buffer(DrmVideoData* vdata, surface_buffer->size = creq.size; _DBG_PRINTF ("Surface buffer info: handle(%u), w(%u), h(%u), " - "pitch(%u), size(%lu), offset(%lu)\n", + "pitch(%u), size(%u), offset(%u)\n", surface_buffer->handle, surface_buffer->width, surface_buffer->height, surface_buffer->pitch, - surface_buffer->size, surface_buffer->offset); + (unsigned)surface_buffer->size, (unsigned)surface_buffer->offset); /* prepare buffer for memory mapping */ memset(&mreq, 0, sizeof(mreq)); @@ -2077,11 +2081,12 @@ static DrmSurfaceBuffer *drm_create_dumb_buffer(DrmVideoData* vdata, } /* perform actual memory mapping */ - surface_buffer->buff = mmap(0, surface_buffer->size, + surface_buffer->buff = mmap64(0, surface_buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, vdata->dev_fd, mreq.offset); if (surface_buffer->buff == MAP_FAILED) { - _ERR_PRINTF("NEWGAL>DRM: cannot mmap dumb buffer (%d): %m\n", errno); + _ERR_PRINTF("NEWGAL>DRM: cannot mmap dumb buffer %m (%u at %u)\n", + (unsigned)surface_buffer->size, (unsigned)mreq.offset); goto err_fb; } @@ -2113,7 +2118,6 @@ static DrmSurfaceBuffer *drm_create_dumb_buffer_from_handle(DrmVideoData* vdata, surface_buffer->prime_fd = -1; surface_buffer->name = 0; surface_buffer->fb_id = 0; - surface_buffer->dma_idx = -1; surface_buffer->size = size; /* prepare buffer for memory mapping */ @@ -2126,7 +2130,7 @@ static DrmSurfaceBuffer *drm_create_dumb_buffer_from_handle(DrmVideoData* vdata, } /* perform actual memory mapping */ - surface_buffer->buff = mmap(0, surface_buffer->size, + surface_buffer->buff = mmap64(0, surface_buffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, vdata->dev_fd, mreq.offset); if (surface_buffer->buff == MAP_FAILED) { @@ -2173,7 +2177,6 @@ static DrmSurfaceBuffer *drm_create_dumb_buffer_from_name(DrmVideoData* vdata, surface_buffer->prime_fd = -1; surface_buffer->name = name; surface_buffer->fb_id = 0; - surface_buffer->dma_idx = -1; surface_buffer->size = oreq.size; return surface_buffer; @@ -2196,7 +2199,7 @@ static DrmSurfaceBuffer *drm_create_dumb_buffer_from_prime_fd(DrmVideoData* vdat return NULL; } - _DBG_PRINTF("size got by calling lseek: %lu\n", size); + _DBG_PRINTF("size got by calling lseek: %u\n", (unsigned)size); } ret = drmPrimeFDToHandle (vdata->dev_fd, prime_fd, &handle); @@ -2211,7 +2214,7 @@ static DrmSurfaceBuffer *drm_create_dumb_buffer_from_prime_fd(DrmVideoData* vdat surface_buffer->size = size; /* perform actual memory mapping */ - surface_buffer->buff = mmap(0, size, + surface_buffer->buff = mmap64(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, prime_fd, 0); if (surface_buffer->buff == MAP_FAILED) { _ERR_PRINTF("NEWGAL>DRM: cannot mmap dumb buffer for prime fd (%d): " @@ -2232,12 +2235,32 @@ static DrmSurfaceBuffer *drm_create_dumb_buffer_from_prime_fd(DrmVideoData* vdat surface_buffer->prime_fd = prime_fd; surface_buffer->name = 0; surface_buffer->fb_id = 0; - surface_buffer->dma_idx = -1; surface_buffer->size = size; return surface_buffer; } +static void drm_map_buffer_via_dmabuf(DrmVideoData* vdata, + DrmSurfaceBuffer *surface_buffer) +{ + if (drmPrimeHandleToFD(vdata->dev_fd, surface_buffer->handle, + DRM_RDWR | DRM_CLOEXEC, &vdata->dmabuf_fd)) { + _ERR_PRINTF ("NEWGAL>DRM: cannot get DMA-BUF fd: %m\n"); + return; + } + + /* perform actual memory mapping */ + surface_buffer->buff = mmap64(0, surface_buffer->size, + PROT_READ | PROT_WRITE, MAP_SHARED, + vdata->dmabuf_fd, 0); + if (surface_buffer->buff == MAP_FAILED) { + _ERR_PRINTF("NEWGAL>DRM: cannot mmap DMA-BUF %m (size: %u)\n", + (unsigned)surface_buffer->size); + surface_buffer->buff = NULL; + } +} + +#if 0 static DrmSurfaceBuffer *drm_create_dumb_buffer_from_dma(DrmVideoData* vdata, int idx) { @@ -2267,7 +2290,6 @@ static DrmSurfaceBuffer *drm_create_dumb_buffer_from_dma(DrmVideoData* vdata, surface_buffer->prime_fd = -1; surface_buffer->name = 0; surface_buffer->fb_id = 0; - surface_buffer->dma_idx = idx; surface_buffer->size = size; surface_buffer->buff = vdata->dma_bufs_map->list[idx].address; return surface_buffer; @@ -2278,21 +2300,17 @@ error: return NULL; } +#endif static void drm_destroy_dumb_buffer(DrmVideoData* vdata, DrmSurfaceBuffer *surface_buffer) { - if (surface_buffer->dma_idx >= 0) { - drmUnmapBufs(vdata->dma_bufs_map); + if (surface_buffer->fb_id) { + drmModeRmFB (vdata->dev_fd, surface_buffer->fb_id); } - else { - if (surface_buffer->fb_id) { - drmModeRmFB (vdata->dev_fd, surface_buffer->fb_id); - } - if (surface_buffer->buff) - munmap (surface_buffer->buff, surface_buffer->size); - } + if (surface_buffer->buff) + munmap (surface_buffer->buff, surface_buffer->size); assert (surface_buffer->handle); @@ -2328,14 +2346,23 @@ static DrmModeInfo* find_mode(DrmVideoData* vdata, int width, int height) return NULL; } +#if 0 static int drm_allocate_dma_buffers(DrmVideoData* vdata, int size) { - int ret; + int ret, count; + ret = drmCreateContext(vdata->dev_fd, &vdata->context); if (ret) { - _ERR_PRINTF("NEWGAL>DRM: " - "failed drmCreateContext: %s\n", strerror(errno)); - return ret; + _WRN_PRINTF("NEWGAL>DRM: " + "failed drmCreateContext: %m\n"); + drm_context_t *ctxt = drmGetReservedContextList(vdata->dev_fd, &count); + if (ctxt == NULL || count == 0) { + _ERR_PRINTF("NEWGAL>DRM: " + "failed drmGetReservedContextList: %m\n"); + vdata->context = 0; + } + else + vdata->context = ctxt[0]; } drmDMAReq dma_req; @@ -2365,6 +2392,7 @@ static int drm_allocate_dma_buffers(DrmVideoData* vdata, int size) return 0; } +#endif /* DRM engine methods for dumb buffers */ static GAL_Surface *DRM_SetVideoMode(_THIS, GAL_Surface *current, @@ -2403,30 +2431,12 @@ static GAL_Surface *DRM_SetVideoMode(_THIS, GAL_Surface *current, assert (vdata->driver_ops->create_buffer); real_buffer = vdata->driver_ops->create_buffer(vdata->driver, drm_format, 0, info->width, info->height); - vdata->driver_ops->map_buffer(vdata->driver, real_buffer, 1); - } - else if (vdata->dbl_buff == DRM_DBLBUF_DMA) { - int bpp, cpp; - drm_format_to_bpp(drm_format, &bpp, &cpp); - int pitch = cpp * info->width; - pitch = ROUND_TO_MULTIPLE(pitch, SIZEOF_PTR); - int size = pitch * info->height; - if (drm_allocate_dma_buffers(vdata, size)) { - _ERR_PRINTF("NEWGAL>DRM: " - "failed to allocate DMA buffers\n"); - return NULL; + if (vdata->dbl_buff == DRM_DBLBUF_DMA) { + drm_map_buffer_via_dmabuf(vdata, real_buffer); + } + else { + vdata->driver_ops->map_buffer(vdata->driver, real_buffer, 1); } - - real_buffer = drm_create_dumb_buffer_from_dma(vdata, - vdata->dma_bufs_idx); - real_buffer->fb_id = 0; - real_buffer->drm_format = drm_format; - real_buffer->bpp = bpp; - real_buffer->cpp = cpp; - real_buffer->width = width; - real_buffer->height = height; - real_buffer->pitch = pitch; - real_buffer->offset = 0; } else { real_buffer = drm_create_dumb_buffer (vdata, drm_format, 0, @@ -2455,7 +2465,7 @@ static GAL_Surface *DRM_SetVideoMode(_THIS, GAL_Surface *current, if (vdata->real_screen == NULL) goto error; - if (vdata->dbl_buff == DRM_DBLBUF_MEMCPY) { + if (vdata->dbl_buff) { uint32_t hdr_size = sizeof (GAL_ShadowSurfaceHeader); GAL_ShadowSurfaceHeader* hdr; @@ -2505,9 +2515,6 @@ static GAL_Surface *DRM_SetVideoMode(_THIS, GAL_Surface *current, GAL_SetColorKey (vdata->shadow_screen, 0, 0); GAL_SetAlpha (vdata->shadow_screen, 0, 0); } - else if (vdata->dbl_buff == DRM_DBLBUF_DMA) { - vdata->shadow_screen = NULL; - } #if IS_COMPOSITING_SCHEMA drm_setup_cursor_plane (vdata, @@ -3417,7 +3424,29 @@ static void DRM_UpdateRects (_THIS, int numrects, GAL_Rect *rects) #endif } -static BOOL DRM_SyncUpdate (_THIS) +static void drm_dmabuf_start(_THIS) +{ + struct dma_buf_sync sync; + + if (this->hidden->dmabuf_fd < 0) + return; + + sync.flags = DMA_BUF_SYNC_RW | DMA_BUF_SYNC_START; + ioctl(this->hidden->dmabuf_fd, DMA_BUF_IOCTL_SYNC, &sync); +} + +static void drm_dmabuf_end(_THIS) +{ + struct dma_buf_sync sync; + + if (this->hidden->dmabuf_fd < 0) + return; + + sync.flags = DMA_BUF_SYNC_RW | DMA_BUF_SYNC_END; + ioctl(this->hidden->dmabuf_fd, DMA_BUF_IOCTL_SYNC, &sync); +} + +static BOOL DRM_SyncUpdate(_THIS) { BOOL retval = FALSE; RECT* dirty_rc; @@ -3481,12 +3510,14 @@ static BOOL DRM_SyncUpdate (_THIS) src_rect.h = RECTH (bound); dst_rect = src_rect; + drm_dmabuf_start(this); GAL_SetupBlitting (this->hidden->shadow_screen, this->hidden->real_screen, 0); GAL_BlitSurface (this->hidden->shadow_screen, &src_rect, this->hidden->real_screen, &dst_rect); GAL_CleanupBlitting (this->hidden->shadow_screen, this->hidden->real_screen); + drm_dmabuf_end(this); #endif /* use blitting */ } @@ -3543,6 +3574,7 @@ ret: return retval; } +#if 0 static BOOL DRM_SyncUpdateDMA (_THIS) { drmDMAReq dma_req; @@ -3568,6 +3600,7 @@ static BOOL DRM_SyncUpdateDMA (_THIS) SetRectEmpty(&this->hidden->dirty_rc); return TRUE; } +#endif #if 0 /* test code */ #ifdef _MGSCHEMA_COMPOSITING diff --git a/src/newgal/drm/drmvideo.h b/src/newgal/drm/drmvideo.h index ed561047..c89b2b9a 100644 --- a/src/newgal/drm/drmvideo.h +++ b/src/newgal/drm/drmvideo.h @@ -109,11 +109,8 @@ typedef struct GAL_PrivateVideoData { uint32_t dbl_buff:2; uint32_t scanout_buff_id; - /* Use DMA for real buffer */ - drm_context_t context; - int dma_bufs_idx; - int dma_bufs_siz; - drmBufMapPtr dma_bufs_map; + /* Use DMA-BUF */ + int dmabuf_fd; void* exdrv_handle; DrmDriverOps* driver_ops; diff --git a/src/newgal/drm/linux-dma-buf.h b/src/newgal/drm/linux-dma-buf.h new file mode 100644 index 00000000..d75df521 --- /dev/null +++ b/src/newgal/drm/linux-dma-buf.h @@ -0,0 +1,41 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * Framework for buffer objects that can be shared across devices/subsystems. + * + * Copyright(C) 2015 Intel Ltd + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program. If not, see . + */ + +#ifndef _DMA_BUF_UAPI_H_ +#define _DMA_BUF_UAPI_H_ + +#include + +/* begin/end dma-buf functions used for userspace mmap. */ +struct dma_buf_sync { + __u64 flags; +}; + +#define DMA_BUF_SYNC_READ (1 << 0) +#define DMA_BUF_SYNC_WRITE (2 << 0) +#define DMA_BUF_SYNC_RW (DMA_BUF_SYNC_READ | DMA_BUF_SYNC_WRITE) +#define DMA_BUF_SYNC_START (0 << 2) +#define DMA_BUF_SYNC_END (1 << 2) +#define DMA_BUF_SYNC_VALID_FLAGS_MASK \ + (DMA_BUF_SYNC_RW | DMA_BUF_SYNC_END) + +#define DMA_BUF_BASE 'b' +#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync) + +#endif