diff options
author | Michel Dänzer <michel.daenzer@amd.com> | 2018-06-29 17:57:03 +0200 |
---|---|---|
committer | Michel Dänzer <michel@daenzer.net> | 2018-07-09 18:28:21 +0200 |
commit | 3c4c0213c11d623cba7adbc28dde652694f2f758 (patch) | |
tree | 278200a4fbf0790fcba3f21c6ca46d790cc75faa /src | |
parent | b85b7b11f5b5e792f21951b881bd8433d3d70858 (diff) |
glamor: Use GBM for BO allocation when possible
Inspired by amdgpu. This avoids various issues due to a GEM handle
lifetime conflict between us and Mesa with current glamor.
Bugzilla: https://bugs.freedesktop.org/105381
Tested-by: Konstantin Kharlamov <hi-angel@yandex.ru>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/drmmode_display.c | 39 | ||||
-rw-r--r-- | src/radeon.h | 7 | ||||
-rw-r--r-- | src/radeon_bo_helper.c | 118 | ||||
-rw-r--r-- | src/radeon_bo_helper.h | 20 | ||||
-rw-r--r-- | src/radeon_dri2.c | 7 | ||||
-rw-r--r-- | src/radeon_dri3.c | 13 | ||||
-rw-r--r-- | src/radeon_glamor.c | 47 | ||||
-rw-r--r-- | src/radeon_glamor.h | 28 | ||||
-rw-r--r-- | src/radeon_kms.c | 40 |
10 files changed, 256 insertions, 67 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index ed1bfa9e..df4a95e4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -62,8 +62,8 @@ radeon_drv_la_SOURCES = \ $(RADEON_KMS_SRCS) if GLAMOR -AM_CFLAGS += @LIBGLAMOR_CFLAGS@ -radeon_drv_la_LIBADD += @LIBGLAMOR_LIBS@ +AM_CFLAGS += @LIBGLAMOR_CFLAGS@ @GBM_CFLAGS@ +radeon_drv_la_LIBADD += @LIBGLAMOR_LIBS@ @GBM_LIBS@ radeon_drv_la_SOURCES += \ radeon_glamor_wrappers.c \ radeon_glamor.c diff --git a/src/drmmode_display.c b/src/drmmode_display.c index c91f5bb2..2773ce67 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -142,8 +142,7 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn, } if (!info->use_glamor || - radeon_glamor_create_textured_pixmap(pixmap, - radeon_get_pixmap_private(pixmap))) + radeon_glamor_create_textured_pixmap(pixmap, bo)) return pixmap; fail: @@ -435,8 +434,14 @@ destroy_pixmap_for_fbcon(ScrnInfoPtr pScrn) /* XXX: The current GPUVM support in the kernel doesn't allow removing * the virtual address range for this BO, so we need to keep around * the pixmap to avoid breaking glamor with GPUVM + * + * Similarly, need to keep around the pixmap with current glamor, to + * avoid issues due to a GEM handle lifetime conflict between us and + * Mesa */ - if (info->use_glamor && info->ChipFamily >= CHIP_FAMILY_CAYMAN) + if (info->use_glamor && + (info->ChipFamily >= CHIP_FAMILY_CAYMAN || + xorgGetVersion() >= XORG_VERSION_NUMERIC(1,19,99,1,0))) return; if (info->fbcon_pixmap) @@ -2277,21 +2282,23 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) scrn->displayWidth = pitch / cpp; + if (!info->use_glamor) { #if X_BYTE_ORDER == X_BIG_ENDIAN - switch (cpp) { - case 4: - tiling_flags |= RADEON_TILING_SWAP_32BIT; - break; - case 2: - tiling_flags |= RADEON_TILING_SWAP_16BIT; - break; - } - if (info->ChipFamily < CHIP_FAMILY_R600 && - info->r600_shadow_fb && tiling_flags) - tiling_flags |= RADEON_TILING_SURFACE; + switch (cpp) { + case 4: + tiling_flags |= RADEON_TILING_SWAP_32BIT; + break; + case 2: + tiling_flags |= RADEON_TILING_SWAP_16BIT; + break; + } + if (info->ChipFamily < CHIP_FAMILY_R600 && + info->r600_shadow_fb && tiling_flags) + tiling_flags |= RADEON_TILING_SURFACE; #endif - if (tiling_flags) - radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch); + if (tiling_flags) + radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch); + } if (!info->r600_shadow_fb) { if (info->surf_man && !info->use_glamor) diff --git a/src/radeon.h b/src/radeon.h index 648fd98a..2bcfa41b 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -606,6 +606,8 @@ typedef struct { unsigned hwcursor_disabled; #ifdef USE_GLAMOR + struct gbm_device *gbm; + struct { CreateGCProcPtr SavedCreateGC; RegionPtr (*SavedCopyArea)(DrawablePtr, DrawablePtr, GCPtr, int, int, @@ -744,8 +746,6 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_buffer *bo } if (bo) { - uint32_t pitch; - if (!priv) { priv = calloc(1, sizeof (struct radeon_pixmap)); if (!priv) @@ -754,11 +754,10 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_buffer *bo radeon_buffer_ref(bo); priv->bo = bo; - - radeon_bo_get_tiling(bo->bo.radeon, &priv->tiling_flags, &pitch); } radeon_set_pixmap_private(pPix, priv); + radeon_get_pixmap_tiling_flags(pPix); return TRUE; } else #endif /* USE_GLAMOR */ diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c index 2b836bbf..79e8ff1b 100644 --- a/src/radeon_bo_helper.c +++ b/src/radeon_bo_helper.c @@ -28,6 +28,37 @@ #include "radeon_glamor.h" #include "radeon_bo_gem.h" + +#ifdef USE_GLAMOR + +static uint32_t +radeon_get_gbm_format(int depth, int bitsPerPixel) +{ + switch (depth) { +#ifdef GBM_FORMAT_R8 + case 8: + return GBM_FORMAT_R8; +#endif + case 16: + return GBM_FORMAT_RGB565; + case 32: + return GBM_FORMAT_ARGB8888; + case 30: + return GBM_FORMAT_XRGB2101010; + case 24: + if (bitsPerPixel == 32) + return GBM_FORMAT_XRGB8888; + /* fall through */ + default: + ErrorF("%s: Unsupported depth/bpp %d/%d\n", __func__, depth, + bitsPerPixel); + return ~0U; + } +} + +#endif /* USE_GLAMOR */ + + static const unsigned MicroBlockTable[5][3][2] = { /*linear tiled square-tiled */ {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */ @@ -158,6 +189,46 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, struct radeon_surface surface; struct radeon_buffer *bo; int domain = RADEON_GEM_DOMAIN_VRAM; + +#ifdef USE_GLAMOR + if (info->use_glamor && + !(usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && + info->shadow_primary)) { + uint32_t bo_use = GBM_BO_USE_RENDERING; + uint32_t gbm_format = radeon_get_gbm_format(depth, bitsPerPixel); + + if (gbm_format == ~0U) + return NULL; + + bo = calloc(1, sizeof(struct radeon_buffer)); + if (!bo) + return NULL; + + bo->ref_count = 1; + + if (bitsPerPixel == pScrn->bitsPerPixel) + bo_use |= GBM_BO_USE_SCANOUT; + + if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP && + info->shadow_primary) || + (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) + bo_use |= GBM_BO_USE_LINEAR; + + bo->bo.gbm = gbm_bo_create(info->gbm, width, height, gbm_format, bo_use); + if (!bo->bo.gbm) { + free(bo); + return NULL; + } + + bo->flags |= RADEON_BO_FLAGS_GBM; + + if (new_pitch) + *new_pitch = gbm_bo_get_stride(bo->bo.gbm); + + return bo; + } +#endif + if (usage_hint) { if (info->allowColorTiling) { if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO) @@ -245,6 +316,13 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, void radeon_finish(ScrnInfoPtr scrn, struct radeon_buffer *bo) { + RADEONInfoPtr info = RADEONPTR(scrn); + + if (info->use_glamor) { + radeon_glamor_finish(scrn); + return; + } + radeon_cs_flush_indirect(scrn); radeon_bo_wait(bo->bo.radeon); } @@ -282,7 +360,7 @@ Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle) RADEONInfoPtr info = RADEONPTR(scrn); #endif - if (bo) { + if (bo && !(bo->flags & RADEON_BO_FLAGS_GBM)) { *handle = bo->bo.radeon->handle; return TRUE; } @@ -380,6 +458,44 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle, if (!bo) goto error; +#ifdef USE_GLAMOR + if (info->use_glamor) { + struct gbm_import_fd_data data; + uint32_t bo_use = GBM_BO_USE_RENDERING; + + data.format = radeon_get_gbm_format(ppix->drawable.depth, + ppix->drawable.bitsPerPixel); + if (data.format == ~0U) + goto error; + + bo->ref_count = 1; + + data.fd = ihandle; + data.width = ppix->drawable.width; + data.height = ppix->drawable.height; + data.stride = ppix->devKind; + + if (ppix->drawable.bitsPerPixel == pScrn->bitsPerPixel) + bo_use |= GBM_BO_USE_SCANOUT; + + bo->bo.gbm = gbm_bo_import(info->gbm, GBM_BO_IMPORT_FD, &data, bo_use); + if (!bo->bo.gbm) + goto error; + + bo->flags |= RADEON_BO_FLAGS_GBM; + + if (!radeon_glamor_create_textured_pixmap(ppix, bo)) { + radeon_buffer_unref(&bo); + return FALSE; + } + + ret = radeon_set_pixmap_bo(ppix, bo); + /* radeon_set_pixmap_bo increments ref_count if it succeeds */ + radeon_buffer_unref(&bo); + return ret; + } +#endif + bo->bo.radeon = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size); if (!bo) goto error; diff --git a/src/radeon_bo_helper.h b/src/radeon_bo_helper.h index 53af87c3..cc3d1d3b 100644 --- a/src/radeon_bo_helper.h +++ b/src/radeon_bo_helper.h @@ -23,13 +23,21 @@ #ifndef RADEON_BO_HELPER_H #define RADEON_BO_HELPER_H 1 +#ifdef USE_GLAMOR +#include <gbm.h> +#endif + #define RADEON_BO_FLAGS_GBM 0x1 struct radeon_buffer { union { +#ifdef USE_GLAMOR + struct gbm_bo *gbm; +#endif struct radeon_bo *radeon; } bo; uint32_t ref_count; + uint32_t flags; }; extern struct radeon_buffer * @@ -88,8 +96,16 @@ radeon_buffer_unref(struct radeon_buffer **buffer) return; } - radeon_bo_unmap(buf->bo.radeon); - radeon_bo_unref(buf->bo.radeon); +#ifdef USE_GLAMOR + if (buf->flags & RADEON_BO_FLAGS_GBM) { + gbm_bo_destroy(buf->bo.gbm); + } else +#endif + { + radeon_bo_unmap(buf->bo.radeon); + radeon_bo_unref(buf->bo.radeon); + } + free(buf); *buffer = NULL; } diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c index 584a1d9d..ab3db6c5 100644 --- a/src/radeon_dri2.c +++ b/src/radeon_dri2.c @@ -79,11 +79,12 @@ static DevPrivateKeyRec dri2_window_private_key_rec; static Bool radeon_get_flink_name(RADEONEntPtr pRADEONEnt, PixmapPtr pixmap, uint32_t *name) { - struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap)->bo.radeon; + struct radeon_buffer *bo = radeon_get_pixmap_bo(pixmap); struct drm_gem_flink flink; - if (bo) - return radeon_gem_get_kernel_name(bo, name) == 0; + if (bo && !(bo->flags & RADEON_BO_FLAGS_GBM) && + radeon_gem_get_kernel_name(bo->bo.radeon, name) == 0) + return TRUE; if (radeon_get_pixmap_handle(pixmap, &flink.handle)) { if (drmIoctl(pRADEONEnt->fd, DRM_IOCTL_GEM_FLINK, &flink) != 0) diff --git a/src/radeon_dri3.c b/src/radeon_dri3.c index b199c793..688e594e 100644 --- a/src/radeon_dri3.c +++ b/src/radeon_dri3.c @@ -213,17 +213,16 @@ static int radeon_dri3_fd_from_pixmap(ScreenPtr screen, { struct radeon_bo *bo; int fd; - - bo = radeon_get_pixmap_bo(pixmap)->bo.radeon; - if (!bo) { #ifdef USE_GLAMOR - ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - RADEONInfoPtr info = RADEONPTR(scrn); + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONInfoPtr info = RADEONPTR(scrn); - if (info->use_glamor) - return glamor_fd_from_pixmap(screen, pixmap, stride, size); + if (info->use_glamor) + return glamor_fd_from_pixmap(screen, pixmap, stride, size); #endif + bo = radeon_get_pixmap_bo(pixmap)->bo.radeon; + if (!bo) { exaMoveInPixmap(pixmap); bo = radeon_get_pixmap_bo(pixmap)->bo.radeon; if (!bo) diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c index c1d96160..fa634947 100644 --- a/src/radeon_glamor.c +++ b/src/radeon_glamor.c @@ -52,6 +52,7 @@ radeon_glamor_create_screen_resources(ScreenPtr screen) { ScrnInfoPtr scrn = xf86ScreenToScrn(screen); RADEONInfoPtr info = RADEONPTR(scrn); + uint32_t handle; if (!info->use_glamor) return TRUE; @@ -61,8 +62,12 @@ radeon_glamor_create_screen_resources(ScreenPtr screen) return FALSE; #endif - if (!glamor_egl_create_textured_screen(screen, - info->front_buffer->bo.radeon->handle, + if (info->front_buffer->flags & RADEON_BO_FLAGS_GBM) + handle = gbm_bo_get_handle(info->front_buffer->bo.gbm).u32; + else + handle = info->front_buffer->bo.radeon->handle; + + if (!glamor_egl_create_textured_screen(screen, handle, scrn->displayWidth * info->pixel_bytes)) return FALSE; @@ -136,6 +141,13 @@ radeon_glamor_pre_init(ScrnInfoPtr scrn) } #endif + info->gbm = gbm_create_device(pRADEONEnt->fd); + if (!info->gbm) { + xf86DrvMsg(scrn->scrnIndex, X_ERROR, + "gbm_create_device returned NULL\n"); + return FALSE; + } + /* Load glamor module */ if ((glamor_module = xf86LoadSubModule(scrn, GLAMOR_EGL_MODULE_NAME))) { version = xf86GetModuleVersion(glamor_module); @@ -164,10 +176,21 @@ radeon_glamor_pre_init(ScrnInfoPtr scrn) } Bool -radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *priv) +radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_buffer *bo) { - return glamor_egl_create_textured_pixmap(pixmap, priv->bo->bo.radeon->handle, - pixmap->devKind); + ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); + RADEONInfoPtr info = RADEONPTR(scrn); + uint32_t handle; + + if (!info->use_glamor) + return TRUE; + + if (bo->flags & RADEON_BO_FLAGS_GBM) + handle = gbm_bo_get_handle(bo->bo.gbm).u32; + else + handle = bo->bo.radeon->handle; + + return glamor_egl_create_textured_pixmap(pixmap, handle, pixmap->devKind); } static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap) @@ -179,13 +202,6 @@ static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap) #endif if (pixmap->refcnt == 1) { - if (pixmap->devPrivate.ptr) { - struct radeon_buffer *bo = radeon_get_pixmap_bo(pixmap); - - if (bo) - radeon_bo_unmap(bo->bo.radeon); - } - #ifdef HAVE_GLAMOR_EGL_DESTROY_TEXTURED_PIXMAP glamor_egl_destroy_textured_pixmap(pixmap); #endif @@ -259,7 +275,7 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL); - if (!radeon_glamor_create_textured_pixmap(pixmap, priv)) + if (!radeon_glamor_create_textured_pixmap(pixmap, priv->bo)) goto fallback_glamor; pixmap->devPrivate.ptr = NULL; @@ -390,13 +406,12 @@ radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle) { ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - struct radeon_pixmap *priv; if (!radeon_set_shared_pixmap_backing(pixmap, handle, NULL)) return FALSE; - priv = radeon_get_pixmap_private(pixmap); - if (!radeon_glamor_create_textured_pixmap(pixmap, priv)) { + if (!radeon_glamor_create_textured_pixmap(pixmap, + radeon_get_pixmap_bo(pixmap))) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "Failed to get PRIME drawable for glamor pixmap.\n"); return FALSE; diff --git a/src/radeon_glamor.h b/src/radeon_glamor.h index ec42df1f..2740ab33 100644 --- a/src/radeon_glamor.h +++ b/src/radeon_glamor.h @@ -33,6 +33,12 @@ struct radeon_pixmap; #ifdef USE_GLAMOR +#ifndef HAVE_GLAMOR_FINISH +#include <GL/gl.h> +#endif + +#include <gbm.h> + #define GLAMOR_FOR_XORG 1 #include <glamor.h> @@ -65,12 +71,27 @@ void radeon_glamor_screen_init(ScreenPtr screen); Bool radeon_glamor_create_screen_resources(ScreenPtr screen); void radeon_glamor_free_screen(int scrnIndex, int flags); -Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *priv); +Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_buffer *bo); void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst); PixmapPtr radeon_glamor_set_pixmap_bo(DrawablePtr drawable, PixmapPtr pixmap); XF86VideoAdaptorPtr radeon_glamor_xv_init(ScreenPtr pScreen, int num_adapt); +static inline void +radeon_glamor_finish(ScrnInfoPtr scrn) +{ + RADEONInfoPtr info = RADEONPTR(scrn); + +#if HAVE_GLAMOR_FINISH + glamor_finish(scrn->pScreen); +#else + glamor_block_handler(scrn); + glFinish(); +#endif + + info->gpu_flushed++; +} + #else static inline Bool radeon_glamor_pre_init(ScrnInfoPtr scrn) { return FALSE; } @@ -79,7 +100,7 @@ static inline void radeon_glamor_fini(ScreenPtr screen) { } static inline Bool radeon_glamor_create_screen_resources(ScreenPtr screen) { return FALSE; } static inline void radeon_glamor_free_screen(int scrnIndex, int flags) { } -static inline Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *priv) { return TRUE; } +static inline Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_buffer *bo) { return TRUE; } static inline void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst) {} static inline PixmapPtr radeon_glamor_set_pixmap_bo(DrawablePtr drawable, PixmapPtr pixmap) { return pixmap; } @@ -87,6 +108,9 @@ static inline PixmapPtr radeon_glamor_set_pixmap_bo(DrawablePtr drawable, Pixmap static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap) { return NULL; } static inline XF86VideoAdaptorPtr radeon_glamor_xv_init(ScreenPtr pScreen, int num_adapt) { return NULL; } + +static inline void radeon_glamor_finish(ScrnInfoPtr pScrn) { } + #endif #endif /* RADEON_GLAMOR_H */ diff --git a/src/radeon_kms.c b/src/radeon_kms.c index d3eeebea..72e60831 100644 --- a/src/radeon_kms.c +++ b/src/radeon_kms.c @@ -212,6 +212,11 @@ static void RADEONFreeRec(ScrnInfoPtr pScrn) info->accel_state = NULL; } +#ifdef USE_GLAMOR + if (info->gbm) + gbm_device_destroy(info->gbm); +#endif + pEnt = info->pEnt; free(pScrn->driverPrivate); pScrn->driverPrivate = NULL; @@ -2269,7 +2274,11 @@ Bool RADEONScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv) xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "radeon_setup_kernel_mem failed\n"); return FALSE; } - front_ptr = info->front_buffer->bo.radeon->ptr; + + if (!(info->front_buffer->flags & RADEON_BO_FLAGS_GBM)) + front_ptr = info->front_buffer->bo.radeon->ptr; + else + front_ptr = NULL; if (info->r600_shadow_fb) { info->fb_shadow = calloc(1, @@ -2739,21 +2748,24 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen) ErrorF("Failed to map cursor buffer memory\n"); } } + + if (!info->use_glamor) { #if X_BYTE_ORDER == X_BIG_ENDIAN - switch (cpp) { - case 4: - tiling_flags |= RADEON_TILING_SWAP_32BIT; - break; - case 2: - tiling_flags |= RADEON_TILING_SWAP_16BIT; - break; - } - if (info->ChipFamily < CHIP_FAMILY_R600 && - info->r600_shadow_fb && tiling_flags) - tiling_flags |= RADEON_TILING_SURFACE; + switch (cpp) { + case 4: + tiling_flags |= RADEON_TILING_SWAP_32BIT; + break; + case 2: + tiling_flags |= RADEON_TILING_SWAP_16BIT; + break; + } + if (info->ChipFamily < CHIP_FAMILY_R600 && + info->r600_shadow_fb && tiling_flags) + tiling_flags |= RADEON_TILING_SURFACE; #endif - if (tiling_flags) - radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch); + if (tiling_flags) + radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch); + } } pScrn->displayWidth = pitch / cpp; |