diff options
author | Matthieu Herrb <matthieu@herrb.eu> | 2021-05-22 18:41:45 +0200 |
---|---|---|
committer | Matthieu Herrb <matthieu@herrb.eu> | 2021-05-22 18:41:45 +0200 |
commit | 67ad41f8059984dd3e5210f68adcc8eb076bb995 (patch) | |
tree | 60ead8a13243abc6fb515c97e9402dbeedeed133 | |
parent | 7e4b90a9639792571c3f981309acec75f5f25deb (diff) | |
parent | 5eba006e4129e8015b822f9e1d2f1e613e252cda (diff) |
Merge remote-tracking branch 'origin/master' into obsd
42 files changed, 2633 insertions, 1467 deletions
@@ -26,12 +26,7 @@ INSTALL install-sh .libs/ libtool -libtool.m4 ltmain.sh -lt~obsolete.m4 -ltoptions.m4 -ltsugar.m4 -ltversion.m4 Makefile Makefile.in mdate-sh diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 00000000..f7891323 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,80 @@ +# FDO_DISTRIBUTION_TAG is the tag of the docker image used for the build +# jobs. If the image doesn't exist yet, the docker-image stage generates it +# or copies it from upstream (this is all handled by the templates). +# +# In order to generate a new image, one should generally change the tag. +# While removing the image from the registry would also work, that's not +# recommended except for ephemeral images during development. +# +variables: + FDO_DISTRIBUTION_VERSION: buster-slim + FDO_DISTRIBUTION_EXEC: 'bash .gitlab-ci/debian-install.sh' + FDO_DISTRIBUTION_TAG: "2021-05-10" + FDO_UPSTREAM_REPO: xorg/driver/xf86-video-ati + +include: + - project: 'freedesktop/ci-templates' + ref: 290b79e0e78eab67a83766f4e9691be554fc4afd + file: '/templates/debian.yml' + +stages: + - docker-image + - build + + +container-build: + extends: + - .fdo.container-build@debian + stage: docker-image + variables: + + +# The default build instructions +.default_build: + extends: + - .fdo.distribution-image@debian + stage: build + script: + - ./autogen.sh + - make -j${FDO_CI_CONCURRENT:-4} check V=1 + variables: + CFLAGS: "-pipe -g -O2 -Werror" + ACLOCAL_PATH: /usr/local/xserver-$XSERVER_VERSION/share/aclocal + PKG_CONFIG_PATH: /usr/local/xserver-$XSERVER_VERSION/lib/pkgconfig + +build-distcheck: + extends: + - .default_build + script: + - ./autogen.sh + - make -j${FDO_CI_CONCURRENT:-4} check V=1 + - make install V=1 + - make -j${FDO_CI_CONCURRENT:-4} distcheck + variables: + XSERVER_VERSION: "1.20" + +build-gcc: + extends: + - .default_build + parallel: + matrix: + - XSERVER_VERSION: ["1.16", "1.17", "1.18", "1.19"] + +build-clang: + extends: + - .default_build + parallel: + matrix: + - XSERVER_VERSION: ["1.20", "1.18", "1.19"] + variables: + CC: clang + +build-noglamor: + extends: + - .default_build + script: + - ./autogen.sh --disable-glamor + - make -j${FDO_CI_CONCURRENT:-4} check V=1 + parallel: + matrix: + - XSERVER_VERSION: ["1.13", "1.14", "1.15"] diff --git a/.gitlab-ci/debian-install.sh b/.gitlab-ci/debian-install.sh new file mode 100644 index 00000000..4e528588 --- /dev/null +++ b/.gitlab-ci/debian-install.sh @@ -0,0 +1,74 @@ +#!/bin/bash + +set -e +set -o xtrace + +echo 'deb-src https://deb.debian.org/debian buster main' >/etc/apt/sources.list.d/deb-src.list +apt-get update + + +# Ephemeral packages (installed for this script and removed again at the end) +EPHEMERAL=" + ca-certificates + git + " + +# libXfont/xserver build dependencies +apt-get install -y --no-remove \ + autoconf \ + automake \ + build-essential \ + libtool \ + pkg-config \ + $EPHEMERAL + +echo 'APT::Get::Build-Dep-Automatic "true";' >>/etc/apt/apt.conf +apt-get build-dep -y xorg-server + + +git clone https://gitlab.freedesktop.org/xorg/lib/libXfont.git +cd libXfont +git checkout libXfont-1.5-branch +./autogen.sh +make install-pkgconfigDATA +cd .. +rm -rf libXfont + + +git clone https://gitlab.freedesktop.org/xorg/xserver.git +cd xserver + +for VERSION in 1.13 1.14 1.15; do + git checkout server-${VERSION}-branch + ./autogen.sh --prefix=/usr/local/xserver-$VERSION --enable-dri2 + make -C include install-nodist_sdkHEADERS + make install-headers install-aclocalDATA install-pkgconfigDATA clean +done + +for VERSION in 1.16 1.17 1.18 1.19 1.20; do + git checkout server-${VERSION}-branch + ./autogen.sh --prefix=/usr/local/xserver-$VERSION --enable-dri2 --enable-dri3 --enable-glamor + make -C include install-nodist_sdkHEADERS + make install-headers install-aclocalDATA install-pkgconfigDATA clean +done + +cd .. +rm -rf xserver + + +# xf86-video-ati build dependencies +apt-get install -y --no-remove \ + clang \ + libdrm-dev \ + libgbm-dev \ + libgl1-mesa-dev \ + libpciaccess-dev \ + libpixman-1-dev \ + libudev-dev \ + xutils-dev \ + x11proto-dev + + +# Remove unneeded packages +apt-get purge -y $EPHEMERAL +apt-get autoremove -y --purge diff --git a/Makefile.am b/Makefile.am index b8d99f32..d14ed8f9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -31,4 +31,4 @@ INSTALL: ChangeLog: $(CHANGELOG_CMD) -EXTRA_DIST = ChangeLog INSTALL +EXTRA_DIST = ChangeLog INSTALL README.md diff --git a/README b/README deleted file mode 100644 index bf7c6407..00000000 --- a/README +++ /dev/null @@ -1,25 +0,0 @@ -xf86-video-ati - ATI/AMD Radeon video driver for the Xorg X server - -Patches and questions regarding this software should be directed at the -amd-gfx mailing list: - - https://lists.freedesktop.org/mailman/listinfo/amd-gfx - -Please submit bug reports to the Xorg bugzilla: - - https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=Driver/Radeon - -The master development code repository can be found at: - - git://anongit.freedesktop.org/git/xorg/driver/xf86-video-ati - - https://cgit.freedesktop.org/xorg/driver/xf86-video-ati - -For patch submission instructions, see: - - https://www.x.org/wiki/Development/Documentation/SubmittingPatches - -For more information on the git code manager, see: - - https://wiki.x.org/wiki/GitPage - diff --git a/README.md b/README.md new file mode 100644 index 00000000..7c9925c7 --- /dev/null +++ b/README.md @@ -0,0 +1,19 @@ +xf86-video-ati - ATI/AMD Radeon video driver for the Xorg X server +------------------------------------------------------------------ + +Patches and questions regarding this software should be directed at the +amd-gfx mailing list: + + https://lists.freedesktop.org/mailman/listinfo/amd-gfx + +Please submit bug reports to the Xorg bugzilla: + + https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=Driver/Radeon + +The master development code repository can be found at: + + https://gitlab.freedesktop.org/xorg/driver/xf86-video-ati + +For patch submission instructions, see: + + https://www.x.org/wiki/Development/Documentation/SubmittingPatches diff --git a/configure.ac b/configure.ac index a11ba2a4..a504695b 100644 --- a/configure.ac +++ b/configure.ac @@ -23,13 +23,13 @@ # Initialize Autoconf AC_PREREQ([2.60]) AC_INIT([xf86-video-ati], - [7.10.99], + [19.1.0], [https://bugs.freedesktop.org/enter_bug.cgi?product=xorg&component=Driver/Radeon], [xf86-video-ati]) AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_HEADERS([config.h]) -AC_CONFIG_MACRO_DIRS([m4]) +AC_CONFIG_MACRO_DIR([m4]) AC_CONFIG_AUX_DIR(.) @@ -70,7 +70,7 @@ XORG_DRIVER_CHECK_EXT(XV, videoproto) XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto) # Checks for libraries. -PKG_CHECK_MODULES(LIBDRM, [libdrm >= 2.4.78]) +PKG_CHECK_MODULES(LIBDRM, [libdrm >= 2.4.89]) PKG_CHECK_MODULES(LIBDRM_RADEON, [libdrm_radeon]) # Obtain compiler/linker options for the driver dependencies @@ -138,12 +138,22 @@ if test "x$GLAMOR" != "xno"; then [Have glamor_egl_destroy_textured_pixmap API])], [], [#include "xorg-server.h" #include "glamor.h"]) + + AC_CHECK_DECL(glamor_finish, + [AC_DEFINE(HAVE_GLAMOR_FINISH, 1, + [Have glamor_finish API])], + [PKG_CHECK_MODULES(LIBGL, [gl])], + [#include "xorg-server.h" + #include "glamor.h"]) fi if test "x$GLAMOR_XSERVER" != xyes; then PKG_CHECK_MODULES(LIBGLAMOR, [glamor >= 0.6.0]) PKG_CHECK_MODULES(LIBGLAMOR_EGL, [glamor-egl]) fi + + PKG_CHECK_MODULES(GBM, [gbm >= 10.6]) + AC_DEFINE(USE_GLAMOR, 1, [Enable glamor acceleration]) else AC_MSG_RESULT([$GLAMOR]) @@ -181,8 +191,8 @@ AC_CHECK_HEADERS([misyncshm.h], [], [], AC_CHECK_HEADERS([present.h], [], [], [#include <X11/Xmd.h> #include <X11/Xproto.h> - #include <X11/X.h> - #include "xorg-server.h"]) + #include "xorg-server.h" + #include <X11/X.h>]) AC_CHECK_HEADERS([dri3.h], [], [], [#include <X11/Xmd.h> diff --git a/m4/.gitignore b/m4/.gitignore new file mode 100644 index 00000000..464ba5ca --- /dev/null +++ b/m4/.gitignore @@ -0,0 +1,5 @@ +libtool.m4 +lt~obsolete.m4 +ltoptions.m4 +ltsugar.m4 +ltversion.m4 diff --git a/man/radeon.man b/man/radeon.man index f4441c4b..247dcdb7 100644 --- a/man/radeon.man +++ b/man/radeon.man @@ -18,7 +18,8 @@ following features: .PD 0 .TP 2 \(bu -Full support for 8-, 15-, 16- and 24-bit pixel depths; +Full support for 8-, 15-, 16- and 24-bit pixel depths, and for 30-bit depth on Linux 3.16 +and later; .TP \(bu RandR 1.2 and RandR 1.3 support; @@ -289,7 +290,7 @@ on. If this option is set, the default value of the property is 'on' or 'off' accordingly. If this option isn't set, the default value of the property is .B auto, which means that TearFree is on for rotated outputs, outputs with RandR -transforms applied and for RandR 1.4 slave outputs, otherwise off. +transforms applied and for RandR 1.4 secondary outputs, otherwise off. .TP .BI "Option \*qAccelMethod\*q \*q" "string" \*q Chooses between available acceleration architectures. Valid values are 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 @@ -109,7 +109,7 @@ ati_device_get_primary(void) device_iter = pci_slot_match_iterator_create(NULL); - while ((device = pci_device_next(device_iter)) != NULL) { + while ((device = pci_device_next(device_iter))) { if (xf86IsPrimaryPci(device)) break; } @@ -128,7 +128,7 @@ ati_device_get_indexed(int index) device_iter = pci_slot_match_iterator_create(NULL); - while ((device = pci_device_next(device_iter)) != NULL) { + while ((device = pci_device_next(device_iter))) { if (device->vendor_id == PCI_VENDOR_ATI) { if (count == index) return device; diff --git a/src/compat-api.h b/src/compat-api.h index f4e7524f..def6d3e4 100644 --- a/src/compat-api.h +++ b/src/compat-api.h @@ -34,4 +34,10 @@ #define BLOCKHANDLER_ARGS pScreen, pTimeout, pReadmask #endif +#if ABI_VIDEODRV_VERSION < SET_ABI_VERSION(25, 2) +#define current_primary current_master +#define primary_pixmap master_pixmap +#define secondary_dst slave_dst +#endif + #endif diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 369c1efc..a58f24dd 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -34,8 +34,10 @@ #include <time.h> #include "cursorstr.h" #include "damagestr.h" +#include "inputstr.h" #include "list.h" #include "micmap.h" +#include "mipointrst.h" #include "xf86cmap.h" #include "xf86Priv.h" #include "radeon.h" @@ -43,7 +45,9 @@ #include "radeon_glamor.h" #include "radeon_reg.h" +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,19,99,1,0) #include <dri.h> +#endif #include "drmmode_display.h" @@ -98,24 +102,15 @@ RADEONZaphodStringMatches(ScrnInfoPtr pScrn, const char *s, char *output_name) } -/* Wait for the boolean condition to be FALSE */ -#define drmmode_crtc_wait_pending_event(drmmode_crtc, fd, condition) \ - do {} while ((condition) && \ - drmHandleEvent(fd, &drmmode_crtc->drmmode->event_context) \ - > 0); - - static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn, int width, int height, int depth, int bpp, int pitch, - struct radeon_bo *bo, struct radeon_surface *psurf) + struct radeon_buffer *bo) { RADEONInfoPtr info = RADEONPTR(pScrn); ScreenPtr pScreen = pScrn->pScreen; PixmapPtr pixmap; - struct radeon_surface *surface; - uint32_t tiling; pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, RADEON_CREATE_PIXMAP_SCANOUT); @@ -133,48 +128,16 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn, if (!radeon_set_pixmap_bo(pixmap, bo)) goto fail; - if (info->ChipFamily >= CHIP_FAMILY_R600) { - surface = radeon_get_pixmap_surface(pixmap); - if (surface && psurf) - *surface = *psurf; - else if (surface) { - memset(surface, 0, sizeof(struct radeon_surface)); - surface->npix_x = width; - surface->npix_y = height; - surface->npix_z = 1; - surface->blk_w = 1; - surface->blk_h = 1; - surface->blk_d = 1; - surface->array_size = 1; - surface->last_level = 0; - surface->bpe = bpp / 8; - surface->nsamples = 1; - surface->flags = RADEON_SURF_SCANOUT; - /* we are requiring a recent enough libdrm version */ - surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX; - surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); - surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); - tiling = radeon_get_pixmap_tiling_flags(pixmap); - if (tiling & RADEON_TILING_MICRO) { - surface->flags = RADEON_SURF_CLR(surface->flags, MODE); - surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); - } - if (tiling & RADEON_TILING_MACRO) { - surface->flags = RADEON_SURF_CLR(surface->flags, MODE); - surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); - } - if (radeon_surface_best(info->surf_man, surface)) { - goto fail; - } - if (radeon_surface_init(info->surf_man, surface)) { - goto fail; - } - } + if (info->surf_man && !info->use_glamor) { + struct radeon_surface *surface = radeon_get_pixmap_surface(pixmap); + + if (!radeon_surface_initialize(info, surface, width, height, bpp / 8, + radeon_get_pixmap_tiling_flags(pixmap), 0)) + goto fail; } 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: @@ -338,8 +301,7 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode) if (drmmode_crtc->dpms_mode == DPMSModeOn && mode != DPMSModeOn) { uint32_t seq; - drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd, - drmmode_crtc->flip_pending); + radeon_drm_wait_pending_flip(crtc); /* * On->Off transition: record the last vblank time, @@ -364,6 +326,9 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode) nominal_frame_rate /= pix_in_frame; drmmode_crtc->dpms_last_fps = nominal_frame_rate; } + + drmmode_crtc->dpms_mode = mode; + radeon_drm_queue_handle_deferred(crtc); } else if (drmmode_crtc->dpms_mode != DPMSModeOn && mode == DPMSModeOn) { /* * Off->On transition: calculate and accumulate the @@ -381,8 +346,9 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode) drmmode_crtc->interpolated_vblanks += delta_seq; } + + drmmode_crtc->dpms_mode = DPMSModeOn; } - drmmode_crtc->dpms_mode = mode; } static void @@ -393,8 +359,7 @@ drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode) /* Disable unused CRTCs */ if (!crtc->enabled || mode != DPMSModeOn) { - drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd, - drmmode_crtc->flip_pending); + drmmode_do_crtc_dpms(crtc, DPMSModeOff); drmModeSetCrtc(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 0, 0, NULL, 0, NULL); drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL); @@ -410,7 +375,7 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode, RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); RADEONInfoPtr info = RADEONPTR(pScrn); PixmapPtr pixmap = info->fbcon_pixmap; - struct radeon_bo *bo; + struct radeon_buffer *bo; drmModeFBPtr fbcon; struct drm_gem_flink flink; @@ -418,7 +383,7 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode, return pixmap; fbcon = drmModeGetFB(pRADEONEnt->fd, fbcon_id); - if (fbcon == NULL) + if (!fbcon) return NULL; if (fbcon->depth != pScrn->depth || @@ -433,18 +398,26 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode, goto out_free_fb; } - bo = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0); - if (bo == NULL) { + bo = calloc(1, sizeof(struct radeon_buffer)); + if (!bo) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, - "Couldn't allocate bo for fbcon handle\n"); + "Couldn't allocate BO for fbcon handle\n"); + goto out_free_fb; + } + bo->ref_count = 1; + + bo->bo.radeon = radeon_bo_open(drmmode->bufmgr, flink.name, 0, 0, 0, 0); + if (!bo) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Couldn't open BO for fbcon handle\n"); goto out_free_fb; } pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height, fbcon->depth, fbcon->bpp, fbcon->pitch, - bo, NULL); + bo); info->fbcon_pixmap = pixmap; - radeon_bo_unref(bo); + radeon_buffer_unref(&bo); out_free_fb: drmModeFreeFB(fbcon); return pixmap; @@ -458,8 +431,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) @@ -527,16 +506,21 @@ drmmode_crtc_scanout_destroy(drmmode_ptr drmmode, scanout->pixmap = NULL; } - if (scanout->bo) { - radeon_bo_unmap(scanout->bo); - radeon_bo_unref(scanout->bo); - scanout->bo = NULL; - } + radeon_buffer_unref(&scanout->bo); } void -drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc) +drmmode_crtc_scanout_free(xf86CrtcPtr crtc) { + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + if (drmmode_crtc->scanout_update_pending) { + radeon_drm_wait_pending_flip(crtc); + radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending); + drmmode_crtc->scanout_update_pending = 0; + radeon_drm_queue_handle_deferred(crtc); + } + drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, &drmmode_crtc->scanout[0]); drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode, @@ -579,7 +563,7 @@ drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout, width, height, pScrn->depth, pScrn->bitsPerPixel, - pitch, scanout->bo, NULL); + pitch, scanout->bo); if (!scanout->pixmap) { ErrorF("failed to create CRTC scanout pixmap\n"); goto error; @@ -691,13 +675,9 @@ drmmode_handle_transform(xf86CrtcPtr crtc) Bool ret; #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,15,99,903,0) - if (crtc->transformPresent || crtc->rotation != RR_Rotate_0) - crtc->driverIsPerformingTransform = XF86DriverTransformOutput; - else - crtc->driverIsPerformingTransform = XF86DriverTransformNone; + crtc->driverIsPerformingTransform = XF86DriverTransformOutput; #else crtc->driverIsPerformingTransform = !crtc->transformPresent && - crtc->rotation != RR_Rotate_0 && (crtc->rotation & 0xf) == RR_Rotate_0; #endif @@ -742,7 +722,7 @@ drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode, xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) { if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { - dirty->slave_dst = + dirty->secondary_dst = drmmode_crtc->scanout[scanout_id].pixmap; break; } @@ -757,8 +737,7 @@ drmmode_crtc_prime_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode, gc, 0, 0, mode->HDisplay, mode->VDisplay, 0, 0); FreeScratchGC(gc); - radeon_cs_flush_indirect(scrn); - radeon_bo_wait(drmmode_crtc->scanout[0].bo); + radeon_finish(scrn, drmmode_crtc->scanout[0].bo); } } @@ -788,8 +767,8 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode, if (drmmode_crtc->scanout[scanout_id].pixmap && (!drmmode_crtc->tear_free || drmmode_crtc->scanout[scanout_id ^ 1].pixmap)) { - RegionPtr region; - BoxPtr box; + BoxRec extents = { .x1 = 0, .y1 = 0, + .x2 = scrn->virtualX, .y2 = scrn->virtualY }; if (!drmmode_crtc->scanout_damage) { drmmode_crtc->scanout_damage = @@ -801,22 +780,20 @@ drmmode_crtc_scanout_update(xf86CrtcPtr crtc, DisplayModePtr mode, drmmode_crtc->scanout_damage); } - region = DamageRegion(drmmode_crtc->scanout_damage); - RegionUninit(region); - region->data = NULL; - box = RegionExtents(region); - box->x1 = 0; - box->y1 = 0; - box->x2 = max(box->x2, scrn->virtualX); - box->y2 = max(box->y2, scrn->virtualY); - *fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); *x = *y = 0; - radeon_scanout_do_update(crtc, scanout_id, - screen->GetWindowPixmap(screen->root), - box); - radeon_bo_wait(drmmode_crtc->scanout[scanout_id].bo); + if (radeon_scanout_do_update(crtc, scanout_id, + screen->GetWindowPixmap(screen->root), + extents)) { + RegionEmpty(DamageRegion(drmmode_crtc->scanout_damage)); + radeon_finish(scrn, drmmode_crtc->scanout[scanout_id].bo); + + if (!drmmode_crtc->flip_pending) { + radeon_drm_abort_entry(drmmode_crtc-> + scanout_update_pending); + } + } } } @@ -888,6 +865,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + Bool handle_deferred = FALSE; unsigned scanout_id = 0; drmmode_ptr drmmode = drmmode_crtc->drmmode; int saved_x, saved_y; @@ -920,9 +898,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, drmmode_crtc_update_tear_free(crtc); if (drmmode_crtc->tear_free) scanout_id = drmmode_crtc->scanout_id; - - drmmode_crtc_gamma_do_set(crtc, crtc->gamma_red, crtc->gamma_green, - crtc->gamma_blue, crtc->gamma_size); + else + drmmode_crtc->scanout_id = 0; if (drmmode_crtc->prime_scanout_pixmap) { drmmode_crtc_prime_scanout_update(crtc, mode, scanout_id, @@ -942,11 +919,10 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, if (!fb) fb = radeon_pixmap_get_fb(pScreen->GetWindowPixmap(pScreen->root)); if (!fb) { - fb = radeon_fb_create(pRADEONEnt->fd, pScrn->virtualX, - pScrn->virtualY, pScrn->depth, - pScrn->bitsPerPixel, + fb = radeon_fb_create(pScrn, pRADEONEnt->fd, + pScrn->virtualX, pScrn->virtualY, pScrn->displayWidth * info->pixel_bytes, - info->front_bo->handle); + info->front_buffer->bo.radeon->handle); /* Prevent refcnt of ad-hoc FBs from reaching 2 */ drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL); drmmode_crtc->fb = fb; @@ -956,8 +932,8 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode, goto done; } - drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd, - drmmode_crtc->flip_pending); + radeon_drm_wait_pending_flip(crtc); + handle_deferred = TRUE; if (!drmmode_set_mode(crtc, fb, mode, x, y)) goto done; @@ -1009,14 +985,17 @@ done: if (drmmode_crtc->scanout[scanout_id].pixmap && fb != radeon_pixmap_get_fb(drmmode_crtc-> - scanout[scanout_id].pixmap)) - drmmode_crtc_scanout_free(drmmode_crtc); - else if (!drmmode_crtc->tear_free) { + scanout[scanout_id].pixmap)) { + drmmode_crtc_scanout_free(crtc); + } else if (!drmmode_crtc->tear_free) { drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]); } } + if (handle_deferred) + radeon_drm_queue_handle_deferred(crtc); + return ret; } @@ -1040,6 +1019,9 @@ drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) } #endif + drmmode_crtc->cursor_x = x; + drmmode_crtc->cursor_y = y; + drmModeMoveCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); } @@ -1078,29 +1060,62 @@ drmmode_cursor_src_offset(Rotation rotation, int width, int height, #endif -static uint32_t -drmmode_cursor_gamma(xf86CrtcPtr crtc, uint32_t argb) +static Bool +drmmode_cursor_pixel(xf86CrtcPtr crtc, uint32_t *argb, Bool *premultiplied, + Bool *apply_gamma) { - uint32_t alpha = argb >> 24; + uint32_t alpha = *argb >> 24; uint32_t rgb[3]; int i; - if (!alpha) - return 0; + if (premultiplied) { +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1, 18, 4, 0, 0) + if (alpha == 0 && (*argb & 0xffffff) != 0) { + /* Doesn't look like premultiplied alpha */ + *premultiplied = FALSE; + return FALSE; + } +#endif - if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32) - return argb; + if (!(*apply_gamma)) + return TRUE; + + if (*argb > (alpha | alpha << 8 | alpha << 16 | alpha << 24)) { + /* Un-premultiplied R/G/B would overflow gamma LUT, + * don't apply gamma correction + */ + *apply_gamma = FALSE; + return FALSE; + } + } + + if (!alpha) { + *argb = 0; + return TRUE; + } - /* Un-premultiply alpha */ + /* Extract RGB */ for (i = 0; i < 3; i++) - rgb[i] = ((argb >> (i * 8)) & 0xff) * 0xff / alpha; + rgb[i] = (*argb >> (i * 8)) & 0xff; - /* Apply gamma correction and pre-multiply alpha */ - rgb[0] = (crtc->gamma_blue[rgb[0]] >> 8) * alpha / 0xff; - rgb[1] = (crtc->gamma_green[rgb[1]] >> 8) * alpha / 0xff; - rgb[2] = (crtc->gamma_red[rgb[2]] >> 8) * alpha / 0xff; + if (premultiplied) { + /* Un-premultiply alpha */ + for (i = 0; i < 3; i++) + rgb[i] = rgb[i] * 0xff / alpha; + } + + if (*apply_gamma) { + rgb[0] = crtc->gamma_blue[rgb[0]] >> 8; + rgb[1] = crtc->gamma_green[rgb[1]] >> 8; + rgb[2] = crtc->gamma_red[rgb[2]] >> 8; + } - return alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0]; + /* Premultiply alpha */ + for (i = 0; i < 3; i++) + rgb[i] = rgb[i] * alpha / 0xff; + + *argb = alpha << 24 | rgb[2] << 16 | rgb[1] << 8 | rgb[0]; + return TRUE; } static void @@ -1109,10 +1124,21 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) ScrnInfoPtr pScrn = crtc->scrn; RADEONInfoPtr info = RADEONPTR(pScrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + unsigned id = drmmode_crtc->cursor_id; + Bool premultiplied = TRUE; + Bool apply_gamma = TRUE; + uint32_t argb; uint32_t *ptr; + if (drmmode_crtc->cursor && + XF86_CRTC_CONFIG_PTR(pScrn)->cursor != drmmode_crtc->cursor) + id ^= 1; + /* cursor should be mapped already */ - ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr); + ptr = (uint32_t *)(drmmode_crtc->cursor_bo[id]->ptr); + + if (crtc->scrn->depth != 24 && crtc->scrn->depth != 32) + apply_gamma = FALSE; #if XF86_CRTC_VERSION < 7 if (crtc->driverIsPerformingTransform) { @@ -1120,16 +1146,19 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) int dstx, dsty; int srcoffset; +retry_transform: for (dsty = 0; dsty < cursor_h; dsty++) { for (dstx = 0; dstx < cursor_w; dstx++) { srcoffset = drmmode_cursor_src_offset(crtc->rotation, cursor_w, cursor_h, dstx, dsty); + argb = image[srcoffset]; + if (!drmmode_cursor_pixel(crtc, &argb, &premultiplied, + &apply_gamma)) + goto retry_transform; - ptr[dsty * info->cursor_w + dstx] = - cpu_to_le32(drmmode_cursor_gamma(crtc, - image[srcoffset])); + ptr[dsty * info->cursor_w + dstx] = cpu_to_le32(argb); } } } else @@ -1138,8 +1167,20 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) uint32_t cursor_size = info->cursor_w * info->cursor_h; int i; - for (i = 0; i < cursor_size; i++) - ptr[i] = cpu_to_le32(drmmode_cursor_gamma(crtc, image[i])); +retry: + for (i = 0; i < cursor_size; i++) { + argb = image[i]; + if (!drmmode_cursor_pixel(crtc, &argb, &premultiplied, + &apply_gamma)) + goto retry; + + ptr[i] = cpu_to_le32(argb); + } + } + + if (id != drmmode_crtc->cursor_id) { + drmmode_crtc->cursor_id = id; + crtc->funcs->show_cursor(crtc); } } @@ -1166,7 +1207,7 @@ drmmode_hide_cursor (xf86CrtcPtr crtc) drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, 0, info->cursor_w, info->cursor_h); - + drmmode_crtc->cursor = NULL; } static void @@ -1176,56 +1217,73 @@ drmmode_show_cursor (xf86CrtcPtr crtc) RADEONInfoPtr info = RADEONPTR(pScrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); - uint32_t handle = drmmode_crtc->cursor_bo->handle; + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + CursorPtr cursor = xf86_config->cursor; + int xhot = cursor->bits->xhot; + int yhot = cursor->bits->yhot; static Bool use_set_cursor2 = TRUE; + struct drm_mode_cursor2 arg; + + drmmode_crtc->cursor = xf86_config->cursor; + + memset(&arg, 0, sizeof(arg)); + + arg.handle = drmmode_crtc->cursor_bo[drmmode_crtc->cursor_id]->handle; + arg.flags = DRM_MODE_CURSOR_BO; + arg.crtc_id = drmmode_crtc->mode_crtc->crtc_id; + arg.width = info->cursor_w; + arg.height = info->cursor_h; + + if (crtc->rotation != RR_Rotate_0 && + crtc->rotation != (RR_Rotate_180 | RR_Reflect_X | + RR_Reflect_Y)) { + int t; + + /* Reflect & rotate hotspot position */ + if (crtc->rotation & RR_Reflect_X) + xhot = info->cursor_w - xhot - 1; + if (crtc->rotation & RR_Reflect_Y) + yhot = info->cursor_h - yhot - 1; + + switch (crtc->rotation & 0xf) { + case RR_Rotate_90: + t = xhot; + xhot = yhot; + yhot = info->cursor_w - t - 1; + break; + case RR_Rotate_180: + xhot = info->cursor_w - xhot - 1; + yhot = info->cursor_h - yhot - 1; + break; + case RR_Rotate_270: + t = xhot; + xhot = info->cursor_h - yhot - 1; + yhot = t; + } + } + + if (xhot != drmmode_crtc->cursor_xhot || yhot != drmmode_crtc->cursor_yhot) { + arg.flags |= DRM_MODE_CURSOR_MOVE; + arg.x = drmmode_crtc->cursor_x += drmmode_crtc->cursor_xhot - xhot; + arg.y = drmmode_crtc->cursor_y += drmmode_crtc->cursor_yhot - yhot; + drmmode_crtc->cursor_xhot = xhot; + drmmode_crtc->cursor_yhot = yhot; + } if (use_set_cursor2) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); - CursorPtr cursor = xf86_config->cursor; - int xhot = cursor->bits->xhot; - int yhot = cursor->bits->yhot; int ret; - if (crtc->rotation != RR_Rotate_0 && - crtc->rotation != (RR_Rotate_180 | RR_Reflect_X | - RR_Reflect_Y)) { - int t; - - /* Reflect & rotate hotspot position */ - if (crtc->rotation & RR_Reflect_X) - xhot = info->cursor_w - xhot - 1; - if (crtc->rotation & RR_Reflect_Y) - yhot = info->cursor_h - yhot - 1; - - switch (crtc->rotation & 0xf) { - case RR_Rotate_90: - t = xhot; - xhot = yhot; - yhot = info->cursor_w - t - 1; - break; - case RR_Rotate_180: - xhot = info->cursor_w - xhot - 1; - yhot = info->cursor_h - yhot - 1; - break; - case RR_Rotate_270: - t = xhot; - xhot = info->cursor_h - yhot - 1; - yhot = t; - } - } + arg.hot_x = xhot; + arg.hot_y = yhot; - ret = - drmModeSetCursor2(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, - handle, info->cursor_w, info->cursor_h, - xhot, yhot); - if (ret == -EINVAL) + ret = drmIoctl(pRADEONEnt->fd, DRM_IOCTL_MODE_CURSOR2, &arg); + if (ret == -1 && errno == EINVAL) use_set_cursor2 = FALSE; else return; } - drmModeSetCursor(pRADEONEnt->fd, drmmode_crtc->mode_crtc->crtc_id, handle, - info->cursor_w, info->cursor_h); + drmIoctl(pRADEONEnt->fd, DRM_IOCTL_MODE_CURSOR, &arg); } /* Xorg expects a non-NULL return value from drmmode_crtc_shadow_allocate, and @@ -1300,12 +1358,12 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) xorg_list_for_each_entry(dirty, &screen->pixmap_dirty_list, ent) { if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { - PixmapStopDirtyTracking(dirty->src, dirty->slave_dst); + PixmapStopDirtyTracking(dirty->src, dirty->secondary_dst); break; } } - drmmode_crtc_scanout_free(drmmode_crtc); + drmmode_crtc_scanout_free(crtc); drmmode_crtc->prime_scanout_pixmap = NULL; if (!ppix) @@ -1320,7 +1378,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix) !drmmode_crtc_scanout_create(crtc, &drmmode_crtc->scanout[1], ppix->drawable.width, ppix->drawable.height)) { - drmmode_crtc_scanout_free(drmmode_crtc); + drmmode_crtc_scanout_free(crtc); return FALSE; } @@ -1394,9 +1452,10 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res xf86CrtcPtr crtc; drmmode_crtc_private_ptr drmmode_crtc; RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + RADEONInfoPtr info = RADEONPTR(pScrn); - crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs); - if (crtc == NULL) + crtc = xf86CrtcCreate(pScrn, &info->drmmode_crtc_funcs); + if (!crtc) return 0; drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1); @@ -1414,6 +1473,72 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res return 1; } +/* + * Update all of the property values for an output + */ +static void +drmmode_output_update_properties(xf86OutputPtr output) +{ + drmmode_output_private_ptr drmmode_output = output->driver_private; + int i, j, k; + int err; + drmModeConnectorPtr koutput; + + /* Use the most recently fetched values from the kernel */ + koutput = drmmode_output->mode_output; + + if (!koutput) + return; + + for (i = 0; i < drmmode_output->num_props; i++) { + drmmode_prop_ptr p = &drmmode_output->props[i]; + + for (j = 0; j < koutput->count_props; j++) { + if (koutput->props[j] != p->mode_prop->prop_id) + continue; + + /* Check to see if the property value has changed */ + if (koutput->prop_values[j] == p->value) + break; + + p->value = koutput->prop_values[j]; + + if (p->mode_prop->flags & DRM_MODE_PROP_RANGE) { + INT32 value = p->value; + + err = RRChangeOutputProperty(output->randr_output, + p->atoms[0], XA_INTEGER, + 32, PropModeReplace, 1, + &value, FALSE, TRUE); + if (err != 0) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", + err); + } + } else if (p->mode_prop->flags & DRM_MODE_PROP_ENUM) { + for (k = 0; k < p->mode_prop->count_enums; k++) { + if (p->mode_prop->enums[k].value == p->value) + break; + } + if (k < p->mode_prop->count_enums) { + err = RRChangeOutputProperty(output->randr_output, + p->atoms[0], XA_ATOM, + 32, PropModeReplace, 1, + &p->atoms[k + 1], FALSE, + TRUE); + if (err != 0) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", + err); + } + } + } + + break; + } + } +} + static xf86OutputStatus drmmode_output_detect(xf86OutputPtr output) { @@ -1423,9 +1548,14 @@ drmmode_output_detect(xf86OutputPtr output) xf86OutputStatus status; drmModeFreeConnector(drmmode_output->mode_output); - drmmode_output->mode_output = drmModeGetConnector(pRADEONEnt->fd, drmmode_output->output_id); - if (!drmmode_output->mode_output) + drmmode_output->mode_output = + drmModeGetConnector(pRADEONEnt->fd, drmmode_output->output_id); + if (!drmmode_output->mode_output) { + drmmode_output->output_id = -1; return XF86OutputStatusDisconnected; + } + + drmmode_output_update_properties(output); switch (drmmode_output->mode_output->connection) { case DRM_MODE_CONNECTED: @@ -1448,6 +1578,96 @@ drmmode_output_mode_valid(xf86OutputPtr output, DisplayModePtr pModes) return MODE_OK; } +static void +drmmode_output_attach_tile(xf86OutputPtr output) +{ +#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1, 17, 99, 901, 0) + drmmode_output_private_ptr drmmode_output = output->driver_private; + drmModeConnectorPtr koutput = drmmode_output->mode_output; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); + struct xf86CrtcTileInfo tile_info, *set = NULL; + int i; + + if (!koutput) { + xf86OutputSetTile(output, NULL); + return; + } + + /* look for a TILE property */ + for (i = 0; i < koutput->count_props; i++) { + drmModePropertyPtr props; + props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[i]); + if (!props) + continue; + + if (!(props->flags & DRM_MODE_PROP_BLOB)) { + drmModeFreeProperty(props); + continue; + } + + if (!strcmp(props->name, "TILE")) { + drmModeFreePropertyBlob(drmmode_output->tile_blob); + drmmode_output->tile_blob = + drmModeGetPropertyBlob(pRADEONEnt->fd, + koutput->prop_values[i]); + } + drmModeFreeProperty(props); + } + if (drmmode_output->tile_blob) { + if (xf86OutputParseKMSTile(drmmode_output->tile_blob->data, + drmmode_output->tile_blob->length, + &tile_info) == TRUE) + set = &tile_info; + } + xf86OutputSetTile(output, set); +#endif +} + +static int +koutput_get_prop_idx(int fd, drmModeConnectorPtr koutput, + int type, const char *name) +{ + int idx = -1; + + for (int i = 0; i < koutput->count_props; i++) { + drmModePropertyPtr prop = drmModeGetProperty(fd, koutput->props[i]); + + if (!prop) + continue; + + if (drm_property_type_is(prop, type) && !strcmp(prop->name, name)) + idx = i; + + drmModeFreeProperty(prop); + + if (idx > -1) + break; + } + + return idx; +} + +static int +koutput_get_prop_id(int fd, drmModeConnectorPtr koutput, + int type, const char *name) +{ + int idx = koutput_get_prop_idx(fd, koutput, type, name); + + return (idx > -1) ? koutput->props[idx] : -1; +} + +static drmModePropertyBlobPtr +koutput_get_prop_blob(int fd, drmModeConnectorPtr koutput, const char *name) +{ + drmModePropertyBlobPtr blob = NULL; + int idx = koutput_get_prop_idx(fd, koutput, DRM_MODE_PROP_BLOB, name); + + if (idx > -1) + blob = drmModeGetPropertyBlob(fd, koutput->prop_values[idx]); + + return blob; +} + static DisplayModePtr drmmode_output_get_modes(xf86OutputPtr output) { @@ -1456,25 +1676,16 @@ drmmode_output_get_modes(xf86OutputPtr output) RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); int i; DisplayModePtr Modes = NULL, Mode; - drmModePropertyPtr props; xf86MonPtr mon = NULL; if (!koutput) return NULL; + drmModeFreePropertyBlob(drmmode_output->edid_blob); + /* look for an EDID property */ - for (i = 0; i < koutput->count_props; i++) { - props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[i]); - if (props && (props->flags & DRM_MODE_PROP_BLOB)) { - if (!strcmp(props->name, "EDID")) { - if (drmmode_output->edid_blob) - drmModeFreePropertyBlob(drmmode_output->edid_blob); - drmmode_output->edid_blob = drmModeGetPropertyBlob(pRADEONEnt->fd, koutput->prop_values[i]); - } - } - if (props) - drmModeFreeProperty(props); - } + drmmode_output->edid_blob = + koutput_get_prop_blob(pRADEONEnt->fd, koutput, "EDID"); if (drmmode_output->edid_blob) { mon = xf86InterpretEDID(output->scrn->scrnIndex, @@ -1484,6 +1695,8 @@ drmmode_output_get_modes(xf86OutputPtr output) } xf86OutputSetEDID(output, mon); + drmmode_output_attach_tile(output); + /* modes should already be available */ for (i = 0; i < koutput->count_modes; i++) { Mode = xnfalloc(sizeof(DisplayModeRec)); @@ -1501,8 +1714,11 @@ drmmode_output_destroy(xf86OutputPtr output) drmmode_output_private_ptr drmmode_output = output->driver_private; int i; - if (drmmode_output->edid_blob) - drmModeFreePropertyBlob(drmmode_output->edid_blob); + drmModeFreePropertyBlob(drmmode_output->edid_blob); +#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1, 17, 99, 901, 0) + drmModeFreePropertyBlob(drmmode_output->tile_blob); +#endif + for (i = 0; i < drmmode_output->num_props; i++) { drmModeFreeProperty(drmmode_output->props[i].mode_prop); free(drmmode_output->props[i].atoms); @@ -1571,6 +1787,28 @@ drmmode_output_create_resources(xf86OutputPtr output) RADEONEntPtr pRADEONEnt = RADEONEntPriv(output->scrn); drmModePropertyPtr drmmode_prop, tearfree_prop; int i, j, err; + Atom name; + + /* Create CONNECTOR_ID property */ + name = MakeAtom("CONNECTOR_ID", 12, TRUE); + if (name != BAD_RESOURCE) { + INT32 value = mode_output->connector_id; + + err = RRConfigureOutputProperty(output->randr_output, name, + FALSE, FALSE, TRUE, 1, &value); + if (err != Success) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRConfigureOutputProperty error, %d\n", err); + } + + err = RRChangeOutputProperty(output->randr_output, name, + XA_INTEGER, 32, PropModeReplace, 1, + &value, FALSE, FALSE); + if (err != Success) { + xf86DrvMsg(output->scrn->scrnIndex, X_ERROR, + "RRChangeOutputProperty error, %d\n", err); + } + } drmmode_output->props = calloc(mode_output->count_props + 1, sizeof(drmmode_prop_rec)); if (!drmmode_output->props) @@ -1592,14 +1830,14 @@ drmmode_output_create_resources(xf86OutputPtr output) /* Userspace-only property for TearFree */ tearfree_prop = calloc(1, sizeof(*tearfree_prop)); tearfree_prop->flags = DRM_MODE_PROP_ENUM; - strncpy(tearfree_prop->name, "TearFree", 8); + strcpy(tearfree_prop->name, "TearFree"); tearfree_prop->count_enums = 3; tearfree_prop->enums = calloc(tearfree_prop->count_enums, sizeof(*tearfree_prop->enums)); - strncpy(tearfree_prop->enums[0].name, "off", 3); - strncpy(tearfree_prop->enums[1].name, "on", 2); + strcpy(tearfree_prop->enums[0].name, "off"); + strcpy(tearfree_prop->enums[1].name, "on"); tearfree_prop->enums[1].value = 1; - strncpy(tearfree_prop->enums[2].name, "auto", 4); + strcpy(tearfree_prop->enums[2].name, "auto"); tearfree_prop->enums[2].value = 2; drmmode_output->props[j].mode_prop = tearfree_prop; drmmode_output->props[j].value = info->tear_free; @@ -1667,6 +1905,22 @@ drmmode_output_create_resources(xf86OutputPtr output) } } +static void +drmmode_output_set_tear_free(RADEONEntPtr pRADEONEnt, + drmmode_output_private_ptr drmmode_output, + xf86CrtcPtr crtc, int tear_free) +{ + if (drmmode_output->tear_free == tear_free) + return; + + drmmode_output->tear_free = tear_free; + + if (crtc) { + drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, + crtc->x, crtc->y); + } +} + static Bool drmmode_output_set_property(xf86OutputPtr output, Atom property, RRPropertyValuePtr value) @@ -1707,16 +1961,8 @@ drmmode_output_set_property(xf86OutputPtr output, Atom property, for (j = 0; j < p->mode_prop->count_enums; j++) { if (!strcmp(p->mode_prop->enums[j].name, name)) { if (i == (drmmode_output->num_props - 1)) { - if (drmmode_output->tear_free != j) { - xf86CrtcPtr crtc = output->crtc; - - drmmode_output->tear_free = j; - if (crtc) { - drmmode_set_mode_major(crtc, &crtc->mode, - crtc->rotation, - crtc->x, crtc->y); - } - } + drmmode_output_set_tear_free(pRADEONEnt, drmmode_output, + output->crtc, j); } else { drmModeConnectorSetProperty(pRADEONEnt->fd, drmmode_output->output_id, @@ -1744,15 +1990,6 @@ static const xf86OutputFuncsRec drmmode_output_funcs = { .create_resources = drmmode_output_create_resources, .set_property = drmmode_output_set_property, .get_property = drmmode_output_get_property, -#if 0 - - .save = drmmode_crt_save, - .restore = drmmode_crt_restore, - .mode_fixup = drmmode_crt_mode_fixup, - .prepare = drmmode_output_prepare, - .mode_set = drmmode_crt_mode_set, - .commit = drmmode_output_commit, -#endif .detect = drmmode_output_detect, .mode_valid = drmmode_output_mode_valid, @@ -1895,8 +2132,10 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r drmModeConnectorPtr koutput; drmModeEncoderPtr *kencoders = NULL; drmmode_output_private_ptr drmmode_output; - drmModePropertyPtr props; drmModePropertyBlobPtr path_blob = NULL; +#if XF86_CRTC_VERSION >= 8 + Bool nonDesktop = FALSE; +#endif char name[32]; int i; const char *s; @@ -1905,17 +2144,14 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r if (!koutput) return 0; - for (i = 0; i < koutput->count_props; i++) { - props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[i]); - if (props && (props->flags & DRM_MODE_PROP_BLOB)) { - if (!strcmp(props->name, "PATH")) { - path_blob = drmModeGetPropertyBlob(pRADEONEnt->fd, koutput->prop_values[i]); - drmModeFreeProperty(props); - break; - } - drmModeFreeProperty(props); - } - } + path_blob = koutput_get_prop_blob(pRADEONEnt->fd, koutput, "PATH"); + +#if XF86_CRTC_VERSION >= 8 + i = koutput_get_prop_idx(pRADEONEnt->fd, koutput, DRM_MODE_PROP_RANGE, + "non-desktop"); + if (i >= 0) + nonDesktop = koutput->prop_values[i] != 0; +#endif kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders); if (!kencoders) { @@ -1946,6 +2182,9 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r drmmode_output = output->driver_private; drmmode_output->output_id = mode_res->connectors[num]; drmmode_output->mode_output = koutput; +#if XF86_CRTC_VERSION >= 8 + output->non_desktop = nonDesktop; +#endif for (i = 0; i < koutput->count_encoders; i++) drmModeFreeEncoder(kencoders[i]); free(kencoders); @@ -1958,9 +2197,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r if (!RADEONZaphodStringMatches(pScrn, s, name)) goto out_free_encoders; } else { - if (!info->IsSecondary && (num != 0)) - goto out_free_encoders; - else if (info->IsSecondary && (num != 1)) + if (info->instance_id != num) goto out_free_encoders; } } @@ -1987,6 +2224,9 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r output->interlaceAllowed = TRUE; output->doubleScanAllowed = TRUE; output->driver_private = drmmode_output; +#if XF86_CRTC_VERSION >= 8 + output->non_desktop = nonDesktop; +#endif output->possible_crtcs = 0xffffffff; for (i = 0; i < koutput->count_encoders; i++) { @@ -1995,17 +2235,9 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_r /* work out the possible clones later */ output->possible_clones = 0; - for (i = 0; i < koutput->count_props; i++) { - props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[i]); - if (props && (props->flags & DRM_MODE_PROP_ENUM)) { - if (!strcmp(props->name, "DPMS")) { - drmmode_output->dpms_enum_id = koutput->props[i]; - drmModeFreeProperty(props); - break; - } - drmModeFreeProperty(props); - } - } + drmmode_output->dpms_enum_id = + koutput_get_prop_id(pRADEONEnt->fd, koutput, DRM_MODE_PROP_ENUM, + "DPMS"); if (dynamic) { output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output); @@ -2176,144 +2408,83 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); RADEONInfoPtr info = RADEONPTR(scrn); - struct radeon_bo *old_front = NULL; + struct radeon_buffer *old_front = NULL; ScreenPtr screen = xf86ScrnToScreen(scrn); int i, pitch, old_width, old_height, old_pitch; - int aligned_height; - uint32_t screen_size; + int usage = CREATE_PIXMAP_USAGE_BACKING_PIXMAP; int cpp = info->pixel_bytes; - struct radeon_bo *front_bo; - struct radeon_surface surface; - struct radeon_surface *psurface; - uint32_t tiling_flags = 0, base_align; + uint32_t tiling_flags; PixmapPtr ppix = screen->GetScreenPixmap(screen); void *fb_shadow; if (scrn->virtualX == width && scrn->virtualY == height) return TRUE; - front_bo = info->front_bo; - radeon_cs_flush_indirect(scrn); - - if (front_bo) - radeon_bo_wait(front_bo); - - if (info->allowColorTiling && !info->shadow_primary) { - if (info->ChipFamily >= CHIP_FAMILY_R600) { - if (info->allowColorTiling2D) { - tiling_flags |= RADEON_TILING_MACRO; - } else { - tiling_flags |= RADEON_TILING_MICRO; - } - } else - tiling_flags |= RADEON_TILING_MACRO; + if (width > xf86_config->maxWidth || height > xf86_config->maxHeight) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Xorg tried resizing screen to %dx%d, but maximum " + "supported is %dx%d\n", width, height, + xf86_config->maxWidth, xf86_config->maxHeight); + return FALSE; } - pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp; - aligned_height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags)); - screen_size = RADEON_ALIGN(pitch * aligned_height, RADEON_GPU_PAGE_SIZE); - base_align = 4096; - if (info->ChipFamily >= CHIP_FAMILY_R600) { - memset(&surface, 0, sizeof(struct radeon_surface)); - surface.npix_x = width; - surface.npix_y = height; - surface.npix_z = 1; - surface.blk_w = 1; - surface.blk_h = 1; - surface.blk_d = 1; - surface.array_size = 1; - surface.last_level = 0; - surface.bpe = cpp; - surface.nsamples = 1; - surface.flags = RADEON_SURF_SCANOUT; - /* we are requiring a recent enough libdrm version */ - surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX; - surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); - surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); - if (tiling_flags & RADEON_TILING_MICRO) { - surface.flags = RADEON_SURF_CLR(surface.flags, MODE); - surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); - } - if (tiling_flags & RADEON_TILING_MACRO) { - surface.flags = RADEON_SURF_CLR(surface.flags, MODE); - surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); - } - if (radeon_surface_best(info->surf_man, &surface)) { - return FALSE; - } - if (radeon_surface_init(info->surf_man, &surface)) { - return FALSE; - } - screen_size = surface.bo_size; - base_align = surface.bo_alignment; - pitch = surface.level[0].pitch_bytes; - tiling_flags = 0; - switch (surface.level[0].mode) { - case RADEON_SURF_MODE_2D: - tiling_flags |= RADEON_TILING_MACRO; - tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT; - tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT; - tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT; - if (surface.tile_split) - tiling_flags |= eg_tile_split(surface.tile_split) - << RADEON_TILING_EG_TILE_SPLIT_SHIFT; - break; - case RADEON_SURF_MODE_1D: - tiling_flags |= RADEON_TILING_MICRO; - break; - default: - break; - } - info->front_surface = surface; + if (info->allowColorTiling && !info->shadow_primary) { + if (info->ChipFamily < CHIP_FAMILY_R600 || info->allowColorTiling2D) + usage |= RADEON_CREATE_PIXMAP_TILING_MACRO; + else + usage |= RADEON_CREATE_PIXMAP_TILING_MICRO; } - xf86DrvMsg(scrn->scrnIndex, X_INFO, - "Allocate new frame buffer %dx%d stride %d\n", - width, height, pitch / cpp); + xf86DrvMsg(scrn->scrnIndex, X_INFO, "Allocate new frame buffer %dx%d\n", + width, height); old_width = scrn->virtualX; old_height = scrn->virtualY; old_pitch = scrn->displayWidth; - old_front = info->front_bo; + old_front = info->front_buffer; scrn->virtualX = width; scrn->virtualY = height; - scrn->displayWidth = pitch / cpp; - info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align, - info->shadow_primary ? - RADEON_GEM_DOMAIN_GTT : - RADEON_GEM_DOMAIN_VRAM, - tiling_flags ? RADEON_GEM_NO_CPU_ACCESS : 0); - if (!info->front_bo) + info->front_buffer = radeon_alloc_pixmap_bo(scrn, scrn->virtualX, + scrn->virtualY, scrn->depth, + usage, scrn->bitsPerPixel, + &pitch, + &info->front_surface, + &tiling_flags); + if (!info->front_buffer) goto fail; + 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_bo, tiling_flags, pitch); + if (tiling_flags) + radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch); + } if (!info->r600_shadow_fb) { - psurface = radeon_get_pixmap_surface(ppix); - *psurface = info->front_surface; + if (info->surf_man && !info->use_glamor) + *radeon_get_pixmap_surface(ppix) = info->front_surface; screen->ModifyPixmapHeader(ppix, width, height, -1, -1, pitch, NULL); } else { - if (radeon_bo_map(info->front_bo, 1)) + if (radeon_bo_map(info->front_buffer->bo.radeon, 1)) goto fail; - fb_shadow = calloc(1, screen_size); - if (fb_shadow == NULL) + fb_shadow = calloc(1, pitch * scrn->virtualY); + if (!fb_shadow) goto fail; free(info->fb_shadow); info->fb_shadow = fb_shadow; @@ -2326,13 +2497,12 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) radeon_glamor_create_screen_resources(scrn->pScreen); if (!info->r600_shadow_fb) { - if (!radeon_set_pixmap_bo(ppix, info->front_bo)) + if (!radeon_set_pixmap_bo(ppix, info->front_buffer)) goto fail; } radeon_pixmap_clear(ppix); - radeon_cs_flush_indirect(scrn); - radeon_bo_wait(info->front_bo); + radeon_finish(scrn, info->front_buffer); for (i = 0; i < xf86_config->num_crtc; i++) { xf86CrtcPtr crtc = xf86_config->crtc[i]; @@ -2344,16 +2514,14 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) crtc->rotation, crtc->x, crtc->y); } - if (old_front) - radeon_bo_unref(old_front); + radeon_buffer_unref(&old_front); - radeon_kms_update_vram_limit(scrn, screen_size); + radeon_kms_update_vram_limit(scrn, pitch * scrn->virtualY); return TRUE; fail: - if (info->front_bo) - radeon_bo_unref(info->front_bo); - info->front_bo = old_front; + radeon_buffer_unref(&info->front_buffer); + info->front_buffer = old_front; scrn->virtualX = old_width; scrn->virtualY = old_height; scrn->displayWidth = old_pitch; @@ -2361,8 +2529,139 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height) return FALSE; } +static void +drmmode_validate_leases(ScrnInfoPtr scrn) +{ +#ifdef XF86_LEASE_VERSION + ScreenPtr screen = scrn->pScreen; + rrScrPrivPtr scr_priv = rrGetScrPriv(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + drmModeLesseeListPtr lessees; + RRLeasePtr lease, next; + int l; + + /* We can't talk to the kernel about leases when VT switched */ + if (!scrn->vtSema) + return; + + lessees = drmModeListLessees(pRADEONEnt->fd); + if (!lessees) + return; + + xorg_list_for_each_entry_safe(lease, next, &scr_priv->leases, list) { + drmmode_lease_private_ptr lease_private = lease->devPrivate; + + for (l = 0; l < lessees->count; l++) { + if (lessees->lessees[l] == lease_private->lessee_id) + break; + } + + /* check to see if the lease has gone away */ + if (l == lessees->count) { + free(lease_private); + lease->devPrivate = NULL; + xf86CrtcLeaseTerminated(lease); + } + } + + free(lessees); +#endif +} + +#ifdef XF86_LEASE_VERSION + +static int +drmmode_create_lease(RRLeasePtr lease, int *fd) +{ + ScreenPtr screen = lease->screen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + drmmode_lease_private_ptr lease_private; + int noutput = lease->numOutputs; + int ncrtc = lease->numCrtcs; + uint32_t *objects; + size_t nobjects; + int lease_fd; + int c, o; + int i; + + nobjects = ncrtc + noutput; + if (nobjects == 0 || nobjects > (SIZE_MAX / 4) || + ncrtc > (SIZE_MAX - noutput)) + return BadValue; + + lease_private = calloc(1, sizeof (drmmode_lease_private_rec)); + if (!lease_private) + return BadAlloc; + + objects = malloc(nobjects * 4); + if (!objects) { + free(lease_private); + return BadAlloc; + } + + i = 0; + + /* Add CRTC ids */ + for (c = 0; c < ncrtc; c++) { + xf86CrtcPtr crtc = lease->crtcs[c]->devPrivate; + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + + objects[i++] = drmmode_crtc->mode_crtc->crtc_id; + } + + /* Add connector ids */ + for (o = 0; o < noutput; o++) { + xf86OutputPtr output = lease->outputs[o]->devPrivate; + drmmode_output_private_ptr drmmode_output = output->driver_private; + + objects[i++] = drmmode_output->mode_output->connector_id; + } + + /* call kernel to create lease */ + assert (i == nobjects); + + lease_fd = drmModeCreateLease(pRADEONEnt->fd, objects, nobjects, 0, + &lease_private->lessee_id); + + free(objects); + + if (lease_fd < 0) { + free(lease_private); + return BadMatch; + } + + lease->devPrivate = lease_private; + + xf86CrtcLeaseStarted(lease); + + *fd = lease_fd; + return Success; +} + +static void +drmmode_terminate_lease(RRLeasePtr lease) +{ + drmmode_lease_private_ptr lease_private = lease->devPrivate; + ScreenPtr screen = lease->screen; + ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + + if (drmModeRevokeLease(pRADEONEnt->fd, lease_private->lessee_id) == 0) { + free(lease_private); + lease->devPrivate = NULL; + xf86CrtcLeaseTerminated(lease); + } +} + +#endif // XF86_LEASE_VERSION + static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = { - drmmode_xf86crtc_resize + .resize = drmmode_xf86crtc_resize, +#ifdef XF86_LEASE_VERSION + .create_lease = drmmode_create_lease, + .terminate_lease = drmmode_terminate_lease +#endif }; static void @@ -2371,17 +2670,21 @@ drmmode_flip_abort(xf86CrtcPtr crtc, void *event_data) drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); drmmode_flipdata_ptr flipdata = event_data; + int crtc_id = drmmode_get_crtc_id(crtc); + struct drmmode_fb **fb = &flipdata->fb[crtc_id]; + + if (drmmode_crtc->flip_pending == *fb) { + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, + NULL); + } + drmmode_fb_reference(pRADEONEnt->fd, fb, NULL); if (--flipdata->flip_count == 0) { if (!flipdata->fe_crtc) flipdata->fe_crtc = crtc; flipdata->abort(flipdata->fe_crtc, flipdata->event_data); - drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL); free(flipdata); } - - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, - NULL); } static void @@ -2390,6 +2693,8 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); drmmode_flipdata_ptr flipdata = event_data; + int crtc_id = drmmode_get_crtc_id(crtc); + struct drmmode_fb **fb = &flipdata->fb[crtc_id]; /* Is this the event whose info shall be delivered to higher level? */ if (crtc == flipdata->fe_crtc) { @@ -2398,12 +2703,13 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even flipdata->fe_usec = usec; } - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, - flipdata->fb); - if (drmmode_crtc->tear_free || - drmmode_crtc->flip_pending == flipdata->fb) { - drmmode_fb_reference(pRADEONEnt->fd, - &drmmode_crtc->flip_pending, NULL); + if (*fb) { + if (drmmode_crtc->flip_pending == *fb) { + drmmode_fb_reference(pRADEONEnt->fd, + &drmmode_crtc->flip_pending, NULL); + } + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, *fb); + drmmode_fb_reference(pRADEONEnt->fd, fb, NULL); } if (--flipdata->flip_count == 0) { @@ -2416,7 +2722,6 @@ drmmode_flip_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, void *even else flipdata->handler(crtc, frame, usec, flipdata->event_data); - drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL); free(flipdata); } } @@ -2430,9 +2735,8 @@ static void drm_wakeup_handler(pointer data, int err, pointer p) #endif { - ScrnInfoPtr scrn = data; - RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); - RADEONInfoPtr info = RADEONPTR(scrn); + drmmode_ptr drmmode = data; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(drmmode->scrn); #if !HAVE_NOTIFY_FD fd_set *read_mask = p; @@ -2440,7 +2744,7 @@ drm_wakeup_handler(pointer data, int err, pointer p) if (err >= 0 && FD_ISSET(pRADEONEnt->fd, read_mask)) #endif { - drmHandleEvent(pRADEONEnt->fd, &info->drmmode.event_context); + radeon_drm_handle_event(pRADEONEnt->fd, &drmmode->event_context); } } @@ -2513,6 +2817,7 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) int i, num_dvi = 0, num_hdmi = 0; drmModeResPtr mode_res; unsigned int crtcs_needed = 0; + unsigned int crtcs_got = 0; char *bus_id_string, *provider_name; xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs); @@ -2530,26 +2835,47 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "%d crtcs needed for screen.\n", crtcs_needed); + /* Need per-screen drmmode_crtc_funcs, based on our global template, + * so we can disable some functions, depending on screen settings. + */ + info->drmmode_crtc_funcs = drmmode_crtc_funcs; + if (info->r600_shadow_fb) { /* Rotation requires hardware acceleration */ - drmmode_crtc_funcs.shadow_allocate = NULL; - drmmode_crtc_funcs.shadow_create = NULL; - drmmode_crtc_funcs.shadow_destroy = NULL; + info->drmmode_crtc_funcs.shadow_allocate = NULL; + info->drmmode_crtc_funcs.shadow_create = NULL; + info->drmmode_crtc_funcs.shadow_destroy = NULL; } + /* Hw gamma lut's are currently bypassed by the hw at color depth 30, + * so spare the server the effort to compute and update the cluts. + */ + if (pScrn->depth == 30) + info->drmmode_crtc_funcs.gamma_set = NULL; + drmmode->count_crtcs = mode_res->count_crtcs; xf86CrtcSetSizeRange(pScrn, 320, 200, mode_res->max_width, mode_res->max_height); - for (i = 0; i < mode_res->count_crtcs; i++) + for (i = 0; i < mode_res->count_crtcs; i++) { if (!xf86IsEntityShared(pScrn->entityList[0]) || - (crtcs_needed && !(pRADEONEnt->assigned_crtcs & (1 << i)))) - crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, i); + (crtcs_got < crtcs_needed && + !(pRADEONEnt->assigned_crtcs & (1 << i)))) + crtcs_got += drmmode_crtc_init(pScrn, drmmode, mode_res, i); + } /* All ZaphodHeads outputs provided with matching crtcs? */ - if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0)) + if (crtcs_got < crtcs_needed) { + if (crtcs_got == 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "No ZaphodHeads CRTC available, needed %u\n", + crtcs_needed); + return FALSE; + } + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "%d ZaphodHeads crtcs unavailable. Some outputs will stay off.\n", crtcs_needed); + } /* workout clones */ drmmode_clones_init(pScrn, drmmode, mode_res); @@ -2562,10 +2888,6 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp) xf86InitialConfiguration(pScrn, TRUE); - drmmode->event_context.version = 2; - drmmode->event_context.vblank_handler = radeon_drm_queue_handler; - drmmode->event_context.page_flip_handler = radeon_drm_queue_handler; - pRADEONEnt->has_page_flip_target = drmmode_probe_page_flip_target(pRADEONEnt); drmModeFreeResources(mode_res); @@ -2583,11 +2905,13 @@ void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode) info->drmmode_inited = TRUE; if (pRADEONEnt->fd_wakeup_registered != serverGeneration) { #if HAVE_NOTIFY_FD - SetNotifyFd(pRADEONEnt->fd, drm_notify_fd, X_NOTIFY_READ, pScrn); + SetNotifyFd(pRADEONEnt->fd, drm_notify_fd, X_NOTIFY_READ, + &info->drmmode); #else AddGeneralSocket(pRADEONEnt->fd); RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, - drm_wakeup_handler, pScrn); + drm_wakeup_handler, + &info->drmmode); #endif pRADEONEnt->fd_wakeup_registered = serverGeneration; pRADEONEnt->fd_wakeup_ref = 1; @@ -2605,6 +2929,9 @@ void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode) if (info->dri2.pKernelDRMVersion->version_minor < 4 || !info->drmmode_inited) return; + for (c = 0; c < config->num_crtc; c++) + drmmode_crtc_scanout_free(config->crtc[c]); + if (pRADEONEnt->fd_wakeup_registered == serverGeneration && !--pRADEONEnt->fd_wakeup_ref) { #if HAVE_NOTIFY_FD @@ -2615,9 +2942,6 @@ void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode) drm_wakeup_handler, pScrn); #endif } - - for (c = 0; c < config->num_crtc; c++) - drmmode_crtc_scanout_free(config->crtc[c]->driver_private); } @@ -2628,16 +2952,105 @@ Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo } +static void drmmode_sprite_do_set_cursor(struct radeon_device_priv *device_priv, + ScrnInfoPtr scrn, int x, int y) +{ + RADEONInfoPtr info = RADEONPTR(scrn); + CursorPtr cursor = device_priv->cursor; + Bool sprite_visible = device_priv->sprite_visible; + + if (cursor) { + x -= cursor->bits->xhot; + y -= cursor->bits->yhot; -void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo) + device_priv->sprite_visible = + x < scrn->virtualX && y < scrn->virtualY && + (x + cursor->bits->width > 0) && + (y + cursor->bits->height > 0); + } else { + device_priv->sprite_visible = FALSE; + } + + info->sprites_visible += device_priv->sprite_visible - sprite_visible; +} + +static void drmmode_sprite_set_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y) { - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); - xf86CrtcPtr crtc = xf86_config->crtc[id]; - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); + RADEONInfoPtr info = RADEONPTR(scrn); + struct radeon_device_priv *device_priv = + dixLookupScreenPrivate(&pDev->devPrivates, + &radeon_device_private_key, pScreen); + + device_priv->cursor = pCursor; + drmmode_sprite_do_set_cursor(device_priv, scrn, x, y); + + info->SpriteFuncs->SetCursor(pDev, pScreen, pCursor, x, y); +} + +static void drmmode_sprite_move_cursor(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); + RADEONInfoPtr info = RADEONPTR(scrn); + struct radeon_device_priv *device_priv = + dixLookupScreenPrivate(&pDev->devPrivates, + &radeon_device_private_key, pScreen); + + drmmode_sprite_do_set_cursor(device_priv, scrn, x, y); + + info->SpriteFuncs->MoveCursor(pDev, pScreen, x, y); +} + +static Bool drmmode_sprite_realize_realize_cursor(DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); + RADEONInfoPtr info = RADEONPTR(scrn); - drmmode_crtc->cursor_bo = bo; + return info->SpriteFuncs->RealizeCursor(pDev, pScreen, pCursor); } +static Bool drmmode_sprite_realize_unrealize_cursor(DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); + RADEONInfoPtr info = RADEONPTR(scrn); + + return info->SpriteFuncs->UnrealizeCursor(pDev, pScreen, pCursor); +} + +static Bool drmmode_sprite_device_cursor_initialize(DeviceIntPtr pDev, + ScreenPtr pScreen) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); + RADEONInfoPtr info = RADEONPTR(scrn); + + return info->SpriteFuncs->DeviceCursorInitialize(pDev, pScreen); +} + +static void drmmode_sprite_device_cursor_cleanup(DeviceIntPtr pDev, + ScreenPtr pScreen) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(pScreen); + RADEONInfoPtr info = RADEONPTR(scrn); + + info->SpriteFuncs->DeviceCursorCleanup(pDev, pScreen); +} + +miPointerSpriteFuncRec drmmode_sprite_funcs = { + .RealizeCursor = drmmode_sprite_realize_realize_cursor, + .UnrealizeCursor = drmmode_sprite_realize_unrealize_cursor, + .SetCursor = drmmode_sprite_set_cursor, + .MoveCursor = drmmode_sprite_move_cursor, + .DeviceCursorInitialize = drmmode_sprite_device_cursor_initialize, + .DeviceCursorCleanup = drmmode_sprite_device_cursor_cleanup, +}; + + void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); @@ -2654,27 +3067,30 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, Bool set_hw) { xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn); + unsigned num_desired = 0, num_on = 0; int c; + /* First, disable all unused CRTCs */ + if (set_hw) { + for (c = 0; c < config->num_crtc; c++) { + xf86CrtcPtr crtc = config->crtc[c]; + + /* Skip disabled CRTCs */ + if (crtc->enabled) + continue; + + drmmode_crtc_dpms(crtc, DPMSModeOff); + } + } + + /* Then, try setting the chosen mode on each CRTC */ for (c = 0; c < config->num_crtc; c++) { xf86CrtcPtr crtc = config->crtc[c]; - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; xf86OutputPtr output = NULL; int o; - /* Skip disabled CRTCs */ - if (!crtc->enabled) { - if (set_hw) { - drmmode_do_crtc_dpms(crtc, DPMSModeOff); - drmModeSetCrtc(pRADEONEnt->fd, - drmmode_crtc->mode_crtc->crtc_id, - 0, 0, 0, NULL, 0, NULL); - drmmode_fb_reference(pRADEONEnt->fd, - &drmmode_crtc->fb, NULL); - } + if (!crtc->enabled) continue; - } if (config->output[config->compat_output]->crtc == crtc) output = config->output[config->compat_output]; @@ -2691,14 +3107,19 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, if (!output) continue; + num_desired++; + /* Mark that we'll need to re-set the mode for sure */ memset(&crtc->mode, 0, sizeof(crtc->mode)); if (!crtc->desiredMode.CrtcHDisplay) { DisplayModePtr mode = xf86OutputFindClosestMode (output, pScrn->currentMode); - if (!mode) - return FALSE; + if (!mode) { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to find mode for CRTC %d\n", c); + continue; + } crtc->desiredMode = *mode; crtc->desiredRotation = RR_Rotate_0; crtc->desiredX = 0; @@ -2706,40 +3127,68 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, } if (set_hw) { - if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation, - crtc->desiredX, crtc->desiredY)) - return FALSE; + if (crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, + crtc->desiredRotation, + crtc->desiredX, + crtc->desiredY)) { + num_on++; + } else { + xf86DrvMsg(pScrn->scrnIndex, X_WARNING, + "Failed to set mode on CRTC %d\n", c); + RRCrtcSet(crtc->randr_crtc, NULL, crtc->x, crtc->y, + crtc->rotation, 0, NULL); + } } else { crtc->mode = crtc->desiredMode; crtc->rotation = crtc->desiredRotation; crtc->x = crtc->desiredX; crtc->y = crtc->desiredY; - if (!drmmode_handle_transform(crtc)) - return FALSE; + if (drmmode_handle_transform(crtc)) + num_on++; } } + + if (num_on == 0 && num_desired > 0) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to enable any CRTC\n"); + return FALSE; + } + + /* Validate leases on VT re-entry */ + if (dixPrivateKeyRegistered(rrPrivKey)) + drmmode_validate_leases(pScrn); + return TRUE; } Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + int i; if (xf86_config->num_crtc) { xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "Initializing kms color map\n"); if (!miCreateDefColormap(pScreen)) return FALSE; - /* all radeons support 10 bit CLUTs */ - if (!xf86HandleColormaps(pScreen, 256, 10, - NULL, NULL, - CMAP_PALETTED_TRUECOLOR -#if 0 /* This option messes up text mode! (eich@suse.de) */ - | CMAP_LOAD_EVEN_IF_OFFSCREEN -#endif - | CMAP_RELOAD_ON_MODE_SWITCH)) - return FALSE; + + /* All radeons support 10 bit CLUTs. They get bypassed at depth 30. */ + if (pScrn->depth != 30) { + if (!xf86HandleColormaps(pScreen, 256, 10, NULL, NULL, + CMAP_PALETTED_TRUECOLOR + | CMAP_RELOAD_ON_MODE_SWITCH)) + return FALSE; + + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + + drmmode_crtc_gamma_do_set(crtc, crtc->gamma_red, + crtc->gamma_green, + crtc->gamma_blue, + crtc->gamma_size); + } + } } + return TRUE; } @@ -2796,23 +3245,23 @@ radeon_mode_hotplug(ScrnInfoPtr scrn, drmmode_ptr drmmode) */ for (i = 0; i < config->num_output; i++) { xf86OutputPtr output = config->output[i]; + xf86CrtcPtr crtc = output->crtc; drmmode_output_private_ptr drmmode_output = output->driver_private; - uint32_t con_id = drmmode_output->mode_output->connector_id; - drmModeConnectorPtr koutput; + + drmmode_output_detect(output); + + if (!crtc || !drmmode_output->mode_output) + continue; /* Get an updated view of the properties for the current connector and * look for the link-status property */ - koutput = drmModeGetConnectorCurrent(pRADEONEnt->fd, con_id); - for (j = 0; koutput && j < koutput->count_props; j++) { - drmModePropertyPtr props; - props = drmModeGetProperty(pRADEONEnt->fd, koutput->props[j]); - if (props && props->flags & DRM_MODE_PROP_ENUM && - !strcmp(props->name, "link-status") && - koutput->prop_values[j] == DRM_MODE_LINK_STATUS_BAD) { - xf86CrtcPtr crtc = output->crtc; - if (!crtc) - continue; + for (j = 0; j < drmmode_output->num_props; j++) { + drmmode_prop_ptr p = &drmmode_output->props[j]; + + if (!strcmp(p->mode_prop->name, "link-status")) { + if (p->value != DRM_MODE_LINK_STATUS_BAD) + break; /* the connector got a link failure, re-set the current mode */ drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, @@ -2820,12 +3269,13 @@ radeon_mode_hotplug(ScrnInfoPtr scrn, drmmode_ptr drmmode) xf86DrvMsg(scrn->scrnIndex, X_WARNING, "hotplug event: connector %u's link-state is BAD, " - "tried resetting the current mode. You may be left " - "with a black screen if this fails...\n", con_id); + "tried resetting the current mode. You may be left" + "with a black screen if this fails...\n", + drmmode_output->mode_output->connector_id); + + break; } - drmModeFreeProperty(props); } - drmModeFreeConnector(koutput); } mode_res = drmModeGetResources(pRADEONEnt->fd); @@ -2860,13 +3310,14 @@ restart_destroy: /* find new output ids we don't have outputs for */ for (i = 0; i < mode_res->count_connectors; i++) { - if (drmmode_find_output(pRADEONEnt->primary_scrn, - mode_res->connectors[i], - &num_dvi, &num_hdmi) || - (pRADEONEnt->secondary_scrn && - drmmode_find_output(pRADEONEnt->secondary_scrn, - mode_res->connectors[i], - &num_dvi, &num_hdmi))) + for (j = 0; j < pRADEONEnt->num_scrns; j++) { + if (drmmode_find_output(pRADEONEnt->scrn[j], + mode_res->connectors[i], + &num_dvi, &num_hdmi)) + break; + } + + if (j < pRADEONEnt->num_scrns) continue; if (drmmode_output_init(scrn, drmmode, mode_res, i, &num_dvi, @@ -2874,7 +3325,10 @@ restart_destroy: changed = TRUE; } - if (changed && dixPrivateKeyRegistered(rrPrivKey)) { + /* Check to see if a lessee has disappeared */ + drmmode_validate_leases(scrn); + + if (changed) { #if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1,14,99,2,0) RRSetChanged(xf86ScrnToScreen(scrn)); #else @@ -2974,21 +3428,24 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); xf86CrtcPtr crtc = NULL; drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private; - int i; + int crtc_id; uint32_t flip_flags = flip_sync == FLIP_ASYNC ? DRM_MODE_PAGE_FLIP_ASYNC : 0; drmmode_flipdata_ptr flipdata; + Bool handle_deferred = FALSE; uintptr_t drm_queue_seq = 0; + struct drmmode_fb *fb; + int i = 0; - flipdata = calloc(1, sizeof(drmmode_flipdata_rec)); + flipdata = calloc(1, sizeof(*flipdata) + drmmode_crtc->drmmode->count_crtcs * + sizeof(flipdata->fb[0])); if (!flipdata) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue: data alloc failed.\n"); goto error; } - drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, - radeon_pixmap_get_fb(new_front)); - if (!flipdata->fb) { + fb = radeon_pixmap_get_fb(new_front); + if (!fb) { ErrorF("Failed to get FB for flip\n"); goto error; } @@ -3009,10 +3466,9 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, flipdata->fe_crtc = ref_crtc; for (i = 0; i < config->num_crtc; i++) { - struct drmmode_fb *fb = flipdata->fb; - crtc = config->crtc[i]; drmmode_crtc = crtc->driver_private; + crtc_id = drmmode_get_crtc_id(crtc); if (!drmmode_crtc_can_flip(crtc) || (drmmode_crtc->tear_free && crtc != ref_crtc)) @@ -3023,7 +3479,8 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, drm_queue_seq = radeon_drm_queue_alloc(crtc, client, id, flipdata, drmmode_flip_handler, - drmmode_flip_abort); + drmmode_flip_abort, + TRUE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM queue event entry failed.\n"); @@ -3046,23 +3503,31 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, goto next; } - fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); - if (!fb) { + drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[crtc_id], + radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); + if (!flipdata->fb[crtc_id]) { ErrorF("Failed to get FB for TearFree flip\n"); goto error; } radeon_scanout_do_update(crtc, scanout_id, new_front, - &extents); - - drmmode_crtc_wait_pending_event(drmmode_crtc, pRADEONEnt->fd, - drmmode_crtc->scanout_update_pending); + extents); + radeon_cs_flush_indirect(crtc->scrn); + + if (drmmode_crtc->scanout_update_pending) { + radeon_drm_wait_pending_flip(crtc); + handle_deferred = TRUE; + radeon_drm_abort_entry(drmmode_crtc->scanout_update_pending); + drmmode_crtc->scanout_update_pending = 0; + } + } else { + drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb[crtc_id], fb); } if (crtc == ref_crtc) { if (drmmode_page_flip_target_absolute(pRADEONEnt, drmmode_crtc, - fb->handle, + flipdata->fb[crtc_id]->handle, flip_flags, drm_queue_seq, target_msc) != 0) @@ -3070,7 +3535,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, } else { if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc, - fb->handle, + flipdata->fb[crtc_id]->handle, flip_flags, drm_queue_seq, 0) != 0) goto flip_error; @@ -3081,12 +3546,15 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client, drmmode_crtc->ignore_damage = TRUE; } + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, + flipdata->fb[crtc_id]); + next: - drmmode_fb_reference(pRADEONEnt->fd, - &drmmode_crtc->flip_pending, fb); drm_queue_seq = 0; } + if (handle_deferred) + radeon_drm_queue_handle_deferred(ref_crtc); if (flipdata->flip_count > 0) return TRUE; @@ -3101,11 +3569,12 @@ error: drmmode_flip_abort(crtc, flipdata); else { abort(NULL, data); - drmmode_fb_reference(pRADEONEnt->fd, &flipdata->fb, NULL); free(flipdata); } xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n", strerror(errno)); + if (handle_deferred) + radeon_drm_queue_handle_deferred(ref_crtc); return FALSE; } diff --git a/src/drmmode_display.h b/src/drmmode_display.h index 8387279f..8cd8a0a6 100644 --- a/src/drmmode_display.h +++ b/src/drmmode_display.h @@ -56,7 +56,6 @@ typedef struct { } drmmode_rec, *drmmode_ptr; typedef struct { - struct drmmode_fb *fb; void *event_data; int flip_count; unsigned int fe_frame; @@ -64,6 +63,7 @@ typedef struct { xf86CrtcPtr fe_crtc; radeon_drm_handler_proc handler; radeon_drm_abort_proc abort; + struct drmmode_fb *fb[0]; } drmmode_flipdata_rec, *drmmode_flipdata_ptr; struct drmmode_fb { @@ -71,8 +71,14 @@ struct drmmode_fb { uint32_t handle; }; +enum drmmode_scanout_status { + DRMMODE_SCANOUT_OK, + DRMMODE_SCANOUT_FLIP_FAILED = 1u << 0, + DRMMODE_SCANOUT_VBLANK_FAILED = 1u << 1, +}; + struct drmmode_scanout { - struct radeon_bo *bo; + struct radeon_buffer *bo; PixmapPtr pixmap; int width, height; }; @@ -81,15 +87,24 @@ typedef struct { drmmode_ptr drmmode; drmModeCrtcPtr mode_crtc; int hw_id; - struct radeon_bo *cursor_bo; + + CursorPtr cursor; + int cursor_x; + int cursor_y; + int cursor_xhot; + int cursor_yhot; + unsigned cursor_id; + struct radeon_bo *cursor_bo[2]; + struct drmmode_scanout rotate; struct drmmode_scanout scanout[2]; DamagePtr scanout_damage; Bool ignore_damage; RegionRec scanout_last_region; unsigned scanout_id; - Bool scanout_update_pending; + uintptr_t scanout_update_pending; Bool tear_free; + enum drmmode_scanout_status scanout_status; PixmapPtr prime_scanout_pixmap; @@ -103,18 +118,14 @@ typedef struct { * modeset) */ Bool need_modeset; + /* For keeping track of nested calls to drm_wait_pending_flip / + * drm_queue_handle_deferred + */ + int wait_flip_nesting_level; /* A flip to this FB is pending for this CRTC */ struct drmmode_fb *flip_pending; /* The FB currently being scanned out by this CRTC, if any */ struct drmmode_fb *fb; - -#ifdef HAVE_PRESENT_H - /* Deferred processing of Present vblank event */ - uint64_t present_vblank_event_id; - uint64_t present_vblank_usec; - unsigned present_vblank_msc; - Bool present_flip_expected; -#endif } drmmode_crtc_private_rec, *drmmode_crtc_private_ptr; typedef struct { @@ -131,6 +142,9 @@ typedef struct { drmModeConnectorPtr mode_output; drmModeEncoderPtr *mode_encoders; drmModePropertyBlobPtr edid_blob; +#if XORG_VERSION_CURRENT >= XORG_VERSION_NUMERIC(1, 17, 99, 901, 0) + drmModePropertyBlobPtr tile_blob; +#endif int dpms_enum_id; int num_props; drmmode_prop_ptr props; @@ -139,6 +153,10 @@ typedef struct { int tear_free; } drmmode_output_private_rec, *drmmode_output_private_ptr; +typedef struct { + uint32_t lessee_id; +} drmmode_lease_private_rec, *drmmode_lease_private_ptr; + enum drmmode_flip_sync { FLIP_VSYNC, @@ -206,7 +224,6 @@ extern Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp); extern void drmmode_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode); extern void drmmode_fini(ScrnInfoPtr pScrn, drmmode_ptr drmmode); extern Bool drmmode_set_bufmgr(ScrnInfoPtr pScrn, drmmode_ptr drmmode, struct radeon_bo_manager *bufmgr); -extern void drmmode_set_cursor(ScrnInfoPtr scrn, drmmode_ptr drmmode, int id, struct radeon_bo *bo); void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y); extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode, Bool set_hw); @@ -215,7 +232,7 @@ extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn); extern void drmmode_crtc_scanout_destroy(drmmode_ptr drmmode, struct drmmode_scanout *scanout); -void drmmode_crtc_scanout_free(drmmode_crtc_private_ptr drmmode_crtc); +void drmmode_crtc_scanout_free(xf86CrtcPtr crtc); PixmapPtr drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout, int width, int height); @@ -245,5 +262,8 @@ Bool drmmode_wait_vblank(xf86CrtcPtr crtc, drmVBlankSeqType type, uint64_t *ust, uint32_t *result_seq); +extern miPointerSpriteFuncRec drmmode_sprite_funcs; + + #endif diff --git a/src/evergreen_exa.c b/src/evergreen_exa.c index 90c9b6d9..447ed217 100644 --- a/src/evergreen_exa.c +++ b/src/evergreen_exa.c @@ -71,7 +71,7 @@ EVERGREENPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) if (!RADEONValidPM(pm, pPix->drawable.bitsPerPixel)) RADEON_FALLBACK(("invalid planemask\n")); - dst.bo = radeon_get_pixmap_bo(pPix); + dst.bo = radeon_get_pixmap_bo(pPix)->bo.radeon; dst.tiling_flags = radeon_get_pixmap_tiling(pPix); dst.surface = radeon_get_pixmap_surface(pPix); @@ -466,13 +466,13 @@ EVERGREENPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, accel_state->same_surface = FALSE; - src_obj.bo = radeon_get_pixmap_bo(pSrc); - dst_obj.bo = radeon_get_pixmap_bo(pDst); + src_obj.bo = radeon_get_pixmap_bo(pSrc)->bo.radeon; + dst_obj.bo = radeon_get_pixmap_bo(pDst)->bo.radeon; dst_obj.surface = radeon_get_pixmap_surface(pDst); src_obj.surface = radeon_get_pixmap_surface(pSrc); dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst); src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc); - if (radeon_get_pixmap_bo(pSrc) == radeon_get_pixmap_bo(pDst)) + if (src_obj.bo == dst_obj.bo) accel_state->same_surface = TRUE; src_obj.width = pSrc->drawable.width; @@ -511,7 +511,7 @@ EVERGREENPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, accel_state->copy_area_bo = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_VRAM, 0); - if (accel_state->copy_area_bo == NULL) + if (!accel_state->copy_area_bo) RADEON_FALLBACK(("temp copy surface alloc failed\n")); radeon_cs_space_add_persistent_bo(info->cs, accel_state->copy_area_bo, @@ -668,6 +668,10 @@ struct formatinfo { }; static struct formatinfo EVERGREENTexFormats[] = { + {PICT_a2r10g10b10, FMT_2_10_10_10}, + {PICT_x2r10g10b10, FMT_2_10_10_10}, + {PICT_a2b10g10r10, FMT_2_10_10_10}, + {PICT_x2b10g10r10, FMT_2_10_10_10}, {PICT_a8r8g8b8, FMT_8_8_8_8}, {PICT_x8r8g8b8, FMT_8_8_8_8}, {PICT_a8b8g8r8, FMT_8_8_8_8}, @@ -723,6 +727,12 @@ static uint32_t EVERGREENGetBlendCntl(int op, PicturePtr pMask, uint32_t dst_for static Bool EVERGREENGetDestFormat(PicturePtr pDstPicture, uint32_t *dst_format) { switch (pDstPicture->format) { + case PICT_a2r10g10b10: + case PICT_x2r10g10b10: + case PICT_a2b10g10r10: + case PICT_x2b10g10r10: + *dst_format = COLOR_2_10_10_10; + break; case PICT_a8r8g8b8: case PICT_x8r8g8b8: case PICT_a8b8g8r8: @@ -891,6 +901,7 @@ static Bool EVERGREENTextureSetup(PicturePtr pPict, PixmapPtr pPix, /* component swizzles */ switch (pPict->format) { + case PICT_a2r10g10b10: case PICT_a1r5g5b5: case PICT_a8r8g8b8: pix_r = SQ_SEL_Z; /* R */ @@ -898,12 +909,14 @@ static Bool EVERGREENTextureSetup(PicturePtr pPict, PixmapPtr pPix, pix_b = SQ_SEL_X; /* B */ pix_a = SQ_SEL_W; /* A */ break; + case PICT_a2b10g10r10: case PICT_a8b8g8r8: pix_r = SQ_SEL_X; /* R */ pix_g = SQ_SEL_Y; /* G */ pix_b = SQ_SEL_Z; /* B */ pix_a = SQ_SEL_W; /* A */ break; + case PICT_x2b10g10r10: case PICT_x8b8g8r8: pix_r = SQ_SEL_X; /* R */ pix_g = SQ_SEL_Y; /* G */ @@ -922,6 +935,7 @@ static Bool EVERGREENTextureSetup(PicturePtr pPict, PixmapPtr pPix, pix_b = SQ_SEL_W; /* B */ pix_a = SQ_SEL_1; /* A */ break; + case PICT_x2r10g10b10: case PICT_x1r5g5b5: case PICT_x8r8g8b8: case PICT_r5g6b5: @@ -1287,7 +1301,7 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture, return FALSE; if (pSrc) { - src_obj.bo = radeon_get_pixmap_bo(pSrc); + src_obj.bo = radeon_get_pixmap_bo(pSrc)->bo.radeon; src_obj.surface = radeon_get_pixmap_surface(pSrc); src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc); src_obj.pitch = exaGetPixmapPitch(pSrc) / (pSrc->drawable.bitsPerPixel / 8); @@ -1297,7 +1311,7 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture, src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT; } - dst_obj.bo = radeon_get_pixmap_bo(pDst); + dst_obj.bo = radeon_get_pixmap_bo(pDst)->bo.radeon; dst_obj.surface = radeon_get_pixmap_surface(pDst); dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst); dst_obj.pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8); @@ -1311,7 +1325,7 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture, if (pMaskPicture) { if (pMask) { - mask_obj.bo = radeon_get_pixmap_bo(pMask); + mask_obj.bo = radeon_get_pixmap_bo(pMask)->bo.radeon; mask_obj.tiling_flags = radeon_get_pixmap_tiling(pMask); mask_obj.pitch = exaGetPixmapPitch(pMask) / (pMask->drawable.bitsPerPixel / 8); mask_obj.surface = radeon_get_pixmap_surface(pMask); @@ -1425,6 +1439,8 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture, cb_conf.surface = accel_state->dst_obj.surface; switch (pDstPicture->format) { + case PICT_a2r10g10b10: + case PICT_x2r10g10b10: case PICT_a8r8g8b8: case PICT_x8r8g8b8: case PICT_a1r5g5b5: @@ -1432,6 +1448,8 @@ static Bool EVERGREENPrepareComposite(int op, PicturePtr pSrcPicture, default: cb_conf.comp_swap = 1; /* ARGB */ break; + case PICT_a2b10g10r10: + case PICT_x2b10g10r10: case PICT_a8b8g8r8: case PICT_x8b8g8r8: cb_conf.comp_swap = 0; /* ABGR */ @@ -1655,16 +1673,16 @@ EVERGREENUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, return FALSE; driver_priv = exaGetPixmapDriverPrivate(pDst); - if (!driver_priv || !driver_priv->bo) + if (!driver_priv || !driver_priv->bo->bo.radeon) return FALSE; /* If we know the BO won't be busy / in VRAM, don't bother with a scratch */ - copy_dst = driver_priv->bo; + copy_dst = driver_priv->bo->bo.radeon; copy_pitch = pDst->devKind; if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { - if (!radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { + if (!radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) { flush = FALSE; - if (!radeon_bo_is_busy(driver_priv->bo, &dst_domain) && + if (!radeon_bo_is_busy(driver_priv->bo->bo.radeon, &dst_domain) && !(dst_domain & RADEON_GEM_DOMAIN_VRAM)) goto copy; } @@ -1675,7 +1693,7 @@ EVERGREENUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, base_align = drmmode_get_base_align(pScrn, (bpp / 8), 0); size = scratch_pitch * height * (bpp / 8); scratch = radeon_bo_open(info->bufmgr, 0, size, base_align, RADEON_GEM_DOMAIN_GTT, 0); - if (scratch == NULL) { + if (!scratch) { goto copy; } @@ -1693,7 +1711,7 @@ EVERGREENUploadToScreen(PixmapPtr pDst, int x, int y, int w, int h, dst_obj.height = pDst->drawable.height; dst_obj.bpp = bpp; dst_obj.domain = RADEON_GEM_DOMAIN_VRAM; - dst_obj.bo = radeon_get_pixmap_bo(pDst); + dst_obj.bo = radeon_get_pixmap_bo(pDst)->bo.radeon; dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst); dst_obj.surface = radeon_get_pixmap_surface(pDst); @@ -1721,7 +1739,7 @@ copy: r = TRUE; size = w * bpp / 8; dst = copy_dst->ptr; - if (copy_dst == driver_priv->bo) + if (copy_dst == driver_priv->bo->bo.radeon) dst += y * copy_pitch + x * bpp / 8; for (i = 0; i < h; i++) { memcpy(dst + i * copy_pitch, src, size); @@ -1771,15 +1789,15 @@ EVERGREENDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, return FALSE; driver_priv = exaGetPixmapDriverPrivate(pSrc); - if (!driver_priv || !driver_priv->bo) + if (!driver_priv || !driver_priv->bo->bo.radeon) return FALSE; /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */ - copy_src = driver_priv->bo; + copy_src = driver_priv->bo->bo.radeon; copy_pitch = pSrc->devKind; if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { - if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { - src_domain = radeon_bo_get_src_domain(driver_priv->bo); + if (radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) { + src_domain = radeon_bo_get_src_domain(driver_priv->bo->bo.radeon); if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) == (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) src_domain = 0; @@ -1788,7 +1806,7 @@ EVERGREENDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, } if (!src_domain) - radeon_bo_is_busy(driver_priv->bo, &src_domain); + radeon_bo_is_busy(driver_priv->bo->bo.radeon, &src_domain); if (src_domain & ~(uint32_t)RADEON_GEM_DOMAIN_VRAM) goto copy; @@ -1803,7 +1821,7 @@ EVERGREENDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, base_align = drmmode_get_base_align(pScrn, (bpp / 8), 0); size = scratch_pitch * height * (bpp / 8); scratch = radeon_bo_open(info->bufmgr, 0, size, base_align, RADEON_GEM_DOMAIN_GTT, 0); - if (scratch == NULL) { + if (!scratch) { goto copy; } radeon_cs_space_reset_bos(info->cs); @@ -1823,7 +1841,7 @@ EVERGREENDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w, src_obj.height = pSrc->drawable.height; src_obj.bpp = bpp; src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT; - src_obj.bo = radeon_get_pixmap_bo(pSrc); + src_obj.bo = radeon_get_pixmap_bo(pSrc)->bo.radeon; src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc); src_obj.surface = radeon_get_pixmap_surface(pSrc); @@ -1865,7 +1883,7 @@ copy: } r = TRUE; w *= bpp / 8; - if (copy_src == driver_priv->bo) + if (copy_src == driver_priv->bo->bo.radeon) size = y * copy_pitch + x * bpp / 8; else size = 0; @@ -1909,7 +1927,7 @@ EVERGREENAllocShaders(ScrnInfoPtr pScrn, ScreenPtr pScreen) accel_state->shaders_bo = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_VRAM, 0); - if (accel_state->shaders_bo == NULL) { + if (!accel_state->shaders_bo) { ErrorF("Allocating shader failed\n"); return FALSE; } @@ -2028,7 +2046,7 @@ EVERGREENDrawInit(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->accel_state->exa == NULL) { + if (!info->accel_state->exa) { xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map not set up\n"); return FALSE; } @@ -2047,7 +2065,6 @@ EVERGREENDrawInit(ScreenPtr pScreen) info->accel_state->exa->MarkSync = EVERGREENMarkSync; info->accel_state->exa->WaitMarker = EVERGREENSync; - info->accel_state->exa->CreatePixmap = RADEONEXACreatePixmap; info->accel_state->exa->DestroyPixmap = RADEONEXADestroyPixmap; info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen; info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS; diff --git a/src/evergreen_state.h b/src/evergreen_state.h index 795d4472..34ba87b6 100644 --- a/src/evergreen_state.h +++ b/src/evergreen_state.h @@ -345,14 +345,12 @@ R600SetAccelState(ScrnInfoPtr pScrn, extern Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index); extern void RADEONFinishAccess_CS(PixmapPtr pPix, int index); -extern void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align); extern void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height, int depth, int usage_hint, int bitsPerPixel, int *new_pitch); extern void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv); -extern struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix); extern Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix); -extern Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **handle_p); +extern Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr secondary, void **handle_p); extern Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *handle); #endif diff --git a/src/evergreen_textured_videofuncs.c b/src/evergreen_textured_videofuncs.c index 20805ff4..53675600 100644 --- a/src/evergreen_textured_videofuncs.c +++ b/src/evergreen_textured_videofuncs.c @@ -140,7 +140,7 @@ EVERGREENDisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) CLEAR (vs_const_conf); CLEAR (ps_const_conf); - dst_obj.bo = radeon_get_pixmap_bo(pPixmap); + dst_obj.bo = radeon_get_pixmap_bo(pPixmap)->bo.radeon; dst_obj.tiling_flags = radeon_get_pixmap_tiling(pPixmap); dst_obj.surface = radeon_get_pixmap_surface(pPixmap); diff --git a/src/r600_exa.c b/src/r600_exa.c index 22d4b316..99db0c40 100644 --- a/src/r600_exa.c +++ b/src/r600_exa.c @@ -150,7 +150,7 @@ R600PrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) if (!RADEONValidPM(pm, pPix->drawable.bitsPerPixel)) RADEON_FALLBACK(("invalid planemask\n")); - dst.bo = radeon_get_pixmap_bo(pPix); + dst.bo = radeon_get_pixmap_bo(pPix)->bo.radeon; dst.tiling_flags = radeon_get_pixmap_tiling(pPix); dst.surface = radeon_get_pixmap_surface(pPix); @@ -534,13 +534,13 @@ R600PrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, accel_state->same_surface = FALSE; - src_obj.bo = radeon_get_pixmap_bo(pSrc); - dst_obj.bo = radeon_get_pixmap_bo(pDst); + src_obj.bo = radeon_get_pixmap_bo(pSrc)->bo.radeon; + dst_obj.bo = radeon_get_pixmap_bo(pDst)->bo.radeon; dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst); src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc); src_obj.surface = radeon_get_pixmap_surface(pSrc); dst_obj.surface = radeon_get_pixmap_surface(pDst); - if (radeon_get_pixmap_bo(pSrc) == radeon_get_pixmap_bo(pDst)) + if (src_obj.bo == dst_obj.bo) accel_state->same_surface = TRUE; src_obj.width = pSrc->drawable.width; @@ -575,7 +575,7 @@ R600PrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, accel_state->copy_area_bo = radeon_bo_open(info->bufmgr, 0, size, align, RADEON_GEM_DOMAIN_VRAM, 0); - if (accel_state->copy_area_bo == NULL) + if (!accel_state->copy_area_bo) RADEON_FALLBACK(("temp copy surface alloc failed\n")); radeon_cs_space_add_persistent_bo(info->cs, accel_state->copy_area_bo, @@ -727,6 +727,10 @@ struct formatinfo { }; static struct formatinfo R600TexFormats[] = { + {PICT_a2r10g10b10, FMT_2_10_10_10}, + {PICT_x2r10g10b10, FMT_2_10_10_10}, + {PICT_a2b10g10r10, FMT_2_10_10_10}, + {PICT_x2b10g10r10, FMT_2_10_10_10}, {PICT_a8r8g8b8, FMT_8_8_8_8}, {PICT_x8r8g8b8, FMT_8_8_8_8}, {PICT_a8b8g8r8, FMT_8_8_8_8}, @@ -782,6 +786,12 @@ static uint32_t R600GetBlendCntl(int op, PicturePtr pMask, uint32_t dst_format) static Bool R600GetDestFormat(PicturePtr pDstPicture, uint32_t *dst_format) { switch (pDstPicture->format) { + case PICT_a2r10g10b10: + case PICT_x2r10g10b10: + case PICT_a2b10g10r10: + case PICT_x2b10g10r10: + *dst_format = COLOR_2_10_10_10; + break; case PICT_a8r8g8b8: case PICT_x8r8g8b8: case PICT_a8b8g8r8: @@ -906,6 +916,7 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix, /* component swizzles */ switch (pPict->format) { + case PICT_a2r10g10b10: case PICT_a1r5g5b5: case PICT_a8r8g8b8: pix_r = SQ_SEL_Z; /* R */ @@ -913,12 +924,14 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix, pix_b = SQ_SEL_X; /* B */ pix_a = SQ_SEL_W; /* A */ break; + case PICT_a2b10g10r10: case PICT_a8b8g8r8: pix_r = SQ_SEL_X; /* R */ pix_g = SQ_SEL_Y; /* G */ pix_b = SQ_SEL_Z; /* B */ pix_a = SQ_SEL_W; /* A */ break; + case PICT_x2b10g10r10: case PICT_x8b8g8r8: pix_r = SQ_SEL_X; /* R */ pix_g = SQ_SEL_Y; /* G */ @@ -937,6 +950,7 @@ static Bool R600TextureSetup(PicturePtr pPict, PixmapPtr pPix, pix_b = SQ_SEL_W; /* B */ pix_a = SQ_SEL_1; /* A */ break; + case PICT_x2r10g10b10: case PICT_x1r5g5b5: case PICT_x8r8g8b8: case PICT_r5g6b5: @@ -1330,7 +1344,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture, return FALSE; if (pSrc) { - src_obj.bo = radeon_get_pixmap_bo(pSrc); + src_obj.bo = radeon_get_pixmap_bo(pSrc)->bo.radeon; src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc); src_obj.surface = radeon_get_pixmap_surface(pSrc); src_obj.pitch = exaGetPixmapPitch(pSrc) / (pSrc->drawable.bitsPerPixel / 8); @@ -1340,7 +1354,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture, src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT; } - dst_obj.bo = radeon_get_pixmap_bo(pDst); + dst_obj.bo = radeon_get_pixmap_bo(pDst)->bo.radeon; dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst); dst_obj.surface = radeon_get_pixmap_surface(pDst); dst_obj.pitch = exaGetPixmapPitch(pDst) / (pDst->drawable.bitsPerPixel / 8); @@ -1354,7 +1368,7 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture, if (pMaskPicture) { if (pMask) { - mask_obj.bo = radeon_get_pixmap_bo(pMask); + mask_obj.bo = radeon_get_pixmap_bo(pMask)->bo.radeon; mask_obj.tiling_flags = radeon_get_pixmap_tiling(pMask); mask_obj.surface = radeon_get_pixmap_surface(pMask); mask_obj.pitch = exaGetPixmapPitch(pMask) / (pMask->drawable.bitsPerPixel / 8); @@ -1464,6 +1478,8 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture, cb_conf.surface = accel_state->dst_obj.surface; switch (pDstPicture->format) { + case PICT_a2r10g10b10: + case PICT_x2r10g10b10: case PICT_a8r8g8b8: case PICT_x8r8g8b8: case PICT_a1r5g5b5: @@ -1471,6 +1487,8 @@ static Bool R600PrepareComposite(int op, PicturePtr pSrcPicture, default: cb_conf.comp_swap = 1; /* ARGB */ break; + case PICT_a2b10g10r10: + case PICT_x2b10g10r10: case PICT_a8b8g8r8: case PICT_x8b8g8r8: cb_conf.comp_swap = 0; /* ABGR */ @@ -1682,16 +1700,16 @@ R600UploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h, return FALSE; driver_priv = exaGetPixmapDriverPrivate(pDst); - if (!driver_priv || !driver_priv->bo) + if (!driver_priv || !driver_priv->bo->bo.radeon) return FALSE; /* If we know the BO won't be busy / in VRAM, don't bother with a scratch */ - copy_dst = driver_priv->bo; + copy_dst = driver_priv->bo->bo.radeon; copy_pitch = pDst->devKind; if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { - if (!radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { + if (!radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) { flush = FALSE; - if (!radeon_bo_is_busy(driver_priv->bo, &dst_domain) && + if (!radeon_bo_is_busy(driver_priv->bo->bo.radeon, &dst_domain) && !(dst_domain & RADEON_GEM_DOMAIN_VRAM)) goto copy; } @@ -1705,7 +1723,7 @@ R600UploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h, base_align = drmmode_get_base_align(pScrn, (bpp / 8), 0); size = scratch_pitch * height * (bpp / 8); scratch = radeon_bo_open(info->bufmgr, 0, size, base_align, RADEON_GEM_DOMAIN_GTT, 0); - if (scratch == NULL) { + if (!scratch) { goto copy; } @@ -1723,7 +1741,7 @@ R600UploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h, dst_obj.height = pDst->drawable.height; dst_obj.bpp = bpp; dst_obj.domain = RADEON_GEM_DOMAIN_VRAM; - dst_obj.bo = radeon_get_pixmap_bo(pDst); + dst_obj.bo = radeon_get_pixmap_bo(pDst)->bo.radeon; dst_obj.tiling_flags = radeon_get_pixmap_tiling(pDst); dst_obj.surface = radeon_get_pixmap_surface(pDst); @@ -1751,7 +1769,7 @@ copy: r = TRUE; size = w * bpp / 8; dst = copy_dst->ptr; - if (copy_dst == driver_priv->bo) + if (copy_dst == driver_priv->bo->bo.radeon) dst += y * copy_pitch + x * bpp / 8; for (i = 0; i < h; i++) { memcpy(dst + i * copy_pitch, src, size); @@ -1801,15 +1819,15 @@ R600DownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, return FALSE; driver_priv = exaGetPixmapDriverPrivate(pSrc); - if (!driver_priv || !driver_priv->bo) + if (!driver_priv || !driver_priv->bo->bo.radeon) return FALSE; /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */ - copy_src = driver_priv->bo; + copy_src = driver_priv->bo->bo.radeon; copy_pitch = pSrc->devKind; if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { - if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { - src_domain = radeon_bo_get_src_domain(driver_priv->bo); + if (radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) { + src_domain = radeon_bo_get_src_domain(driver_priv->bo->bo.radeon); if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) == (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) src_domain = 0; @@ -1818,7 +1836,7 @@ R600DownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, } if (!src_domain) - radeon_bo_is_busy(driver_priv->bo, &src_domain); + radeon_bo_is_busy(driver_priv->bo->bo.radeon, &src_domain); if (src_domain & ~(uint32_t)RADEON_GEM_DOMAIN_VRAM) goto copy; @@ -1829,7 +1847,7 @@ R600DownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, base_align = drmmode_get_base_align(pScrn, (bpp / 8), 0); size = scratch_pitch * height * (bpp / 8); scratch = radeon_bo_open(info->bufmgr, 0, size, base_align, RADEON_GEM_DOMAIN_GTT, 0); - if (scratch == NULL) { + if (!scratch) { goto copy; } radeon_cs_space_reset_bos(info->cs); @@ -1849,7 +1867,7 @@ R600DownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, src_obj.height = pSrc->drawable.height; src_obj.bpp = bpp; src_obj.domain = RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT; - src_obj.bo = radeon_get_pixmap_bo(pSrc); + src_obj.bo = radeon_get_pixmap_bo(pSrc)->bo.radeon; src_obj.tiling_flags = radeon_get_pixmap_tiling(pSrc); src_obj.surface = radeon_get_pixmap_surface(pSrc); @@ -1891,7 +1909,7 @@ copy: } r = TRUE; w *= bpp / 8; - if (copy_src == driver_priv->bo) + if (copy_src == driver_priv->bo->bo.radeon) size = y * copy_pitch + x * bpp / 8; else size = 0; @@ -1942,7 +1960,7 @@ R600AllocShaders(ScrnInfoPtr pScrn, ScreenPtr pScreen) accel_state->shaders_bo = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_VRAM, 0); - if (accel_state->shaders_bo == NULL) { + if (!accel_state->shaders_bo) { ErrorF("Allocating shader failed\n"); return FALSE; } @@ -2007,7 +2025,7 @@ R600DrawInit(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->accel_state->exa == NULL) { + if (!info->accel_state->exa) { xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map not set up\n"); return FALSE; } @@ -2026,7 +2044,6 @@ R600DrawInit(ScreenPtr pScreen) info->accel_state->exa->MarkSync = R600MarkSync; info->accel_state->exa->WaitMarker = R600Sync; - info->accel_state->exa->CreatePixmap = RADEONEXACreatePixmap; info->accel_state->exa->DestroyPixmap = RADEONEXADestroyPixmap; info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen; info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS; diff --git a/src/r600_state.h b/src/r600_state.h index fda297d3..567c3ca2 100644 --- a/src/r600_state.h +++ b/src/r600_state.h @@ -316,13 +316,11 @@ R600SetAccelState(ScrnInfoPtr pScrn, extern Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index); extern void RADEONFinishAccess_CS(PixmapPtr pPix, int index); -extern void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align); extern void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height, int depth, int usage_hint, int bitsPerPixel, int *new_pitch); extern void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv); -extern struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix); extern Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix); -extern Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **handle_p); +extern Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr secondary, void **handle_p); extern Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *handle); #endif diff --git a/src/r600_textured_videofuncs.c b/src/r600_textured_videofuncs.c index d20df7e2..c8a9b197 100644 --- a/src/r600_textured_videofuncs.c +++ b/src/r600_textured_videofuncs.c @@ -152,7 +152,7 @@ R600DisplayTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) CLEAR (vs_conf); CLEAR (ps_conf); - dst_obj.bo = radeon_get_pixmap_bo(pPixmap); + dst_obj.bo = radeon_get_pixmap_bo(pPixmap)->bo.radeon; dst_obj.tiling_flags = radeon_get_pixmap_tiling(pPixmap); dst_obj.surface = radeon_get_pixmap_surface(pPixmap); diff --git a/src/radeon.h b/src/radeon.h index d54e4990..68d7756a 100644 --- a/src/radeon.h +++ b/src/radeon.h @@ -83,6 +83,7 @@ #include "radeon_dri2.h" #include "drmmode_display.h" #include "radeon_surface.h" +#include "radeon_bo_helper.h" /* Render support */ #ifdef RENDER @@ -181,34 +182,34 @@ typedef enum { static inline ScreenPtr -radeon_master_screen(ScreenPtr screen) +radeon_primary_screen(ScreenPtr screen) { - if (screen->current_master) - return screen->current_master; + if (screen->current_primary) + return screen->current_primary; return screen; } static inline ScreenPtr -radeon_dirty_master(PixmapDirtyUpdatePtr dirty) +radeon_dirty_primary(PixmapDirtyUpdatePtr dirty) +{ + return radeon_primary_screen(dirty->secondary_dst->drawable.pScreen); +} + +static inline DrawablePtr +radeon_dirty_src_drawable(PixmapDirtyUpdatePtr dirty) { #ifdef HAS_DIRTYTRACKING_DRAWABLE_SRC - ScreenPtr screen = dirty->src->pScreen; + return dirty->src; #else - ScreenPtr screen = dirty->src->drawable.pScreen; + return &dirty->src->drawable; #endif - - return radeon_master_screen(screen); } static inline Bool radeon_dirty_src_equals(PixmapDirtyUpdatePtr dirty, PixmapPtr pixmap) { -#ifdef HAS_DIRTYTRACKING_DRAWABLE_SRC - return dirty->src == &pixmap->drawable; -#else - return dirty->src == pixmap; -#endif + return radeon_dirty_src_drawable(dirty) == &pixmap->drawable; } @@ -300,17 +301,15 @@ radeon_dirty_src_equals(PixmapDirtyUpdatePtr dirty, PixmapPtr pixmap) #define CURSOR_WIDTH_CIK 128 #define CURSOR_HEIGHT_CIK 128 - #ifdef USE_GLAMOR struct radeon_pixmap { - struct radeon_surface surface; - uint_fast32_t gpu_read; uint_fast32_t gpu_write; - struct radeon_bo *bo; + struct radeon_buffer *bo; struct drmmode_fb *fb; + Bool fb_failed; uint32_t tiling_flags; @@ -335,7 +334,7 @@ static inline void radeon_set_pixmap_private(PixmapPtr pixmap, struct radeon_pix struct radeon_exa_pixmap_priv { - struct radeon_bo *bo; + struct radeon_buffer *bo; struct drmmode_fb *fb; uint32_t tiling_flags; struct radeon_surface surface; @@ -500,6 +499,13 @@ struct radeon_client_priv { uint_fast32_t needs_flush; }; +struct radeon_device_priv { + CursorPtr cursor; + Bool sprite_visible; +}; + +extern DevScreenPrivateKeyRec radeon_device_private_key; + typedef struct { EntityInfoPtr pEnt; pciVideoPtr PciInfo; @@ -550,20 +556,23 @@ typedef struct { CreateScreenResourcesProcPtr CreateScreenResources; CreateWindowProcPtr CreateWindow; WindowExposuresProcPtr WindowExposures; + miPointerSpriteFuncPtr SpriteFuncs; + + /* Number of SW cursors currently visible on this screen */ + int sprites_visible; - Bool IsSecondary; + int instance_id; Bool r600_shadow_fb; void *fb_shadow; void (*reemit_current2d)(ScrnInfoPtr pScrn, int op); // emit the current 2D state into the IB struct radeon_2d_state state_2d; - struct radeon_bo *front_bo; + struct radeon_buffer *front_buffer; struct radeon_bo_manager *bufmgr; struct radeon_cs_manager *csm; struct radeon_cs *cs; - struct radeon_bo *cursor_bo[32]; uint64_t vram_size; uint64_t gart_size; drmmode_rec drmmode; @@ -597,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, @@ -622,6 +633,8 @@ typedef struct { SetSharedPixmapBackingProcPtr SavedSetSharedPixmapBacking; } glamor; #endif /* USE_GLAMOR */ + + xf86CrtcFuncsRec drmmode_crtc_funcs; } RADEONInfoRec, *RADEONInfoPtr; /* radeon_accel.c */ @@ -632,6 +645,11 @@ extern void RADEONInit3DEngine(ScrnInfoPtr pScrn); extern int radeon_cs_space_remaining(ScrnInfoPtr pScrn); /* radeon_bo_helper.c */ +extern Bool +radeon_surface_initialize(RADEONInfoPtr info, struct radeon_surface *surface, + int width, int height, int cpp, uint32_t tiling_flags, + int usage_hint); + extern Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle); /* radeon_commonfuncs.c */ @@ -659,7 +677,7 @@ Bool radeon_dri3_screen_init(ScreenPtr screen); /* radeon_kms.c */ Bool radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id, - PixmapPtr src_pix, BoxPtr extents); + PixmapPtr src_pix, BoxRec extents); void RADEONWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion #if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,16,99,901,0) , RegionPtr pBSRegion @@ -690,38 +708,25 @@ extern RADEONEntPtr RADEONEntPriv(ScrnInfoPtr pScrn); static inline struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix) { -#ifdef USE_GLAMOR - RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen)); - - if (info->use_glamor) { - struct radeon_pixmap *priv; - priv = radeon_get_pixmap_private(pPix); - return priv ? &priv->surface : NULL; - } else -#endif - { - struct radeon_exa_pixmap_priv *driver_priv; - driver_priv = exaGetPixmapDriverPrivate(pPix); - return &driver_priv->surface; - } + struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix); - return NULL; + return &driver_priv->surface; } uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix); -static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo) +static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_buffer *bo) { -#ifdef USE_GLAMOR ScrnInfoPtr scrn = xf86ScreenToScrn(pPix->drawable.pScreen); RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); +#ifdef USE_GLAMOR RADEONInfoPtr info = RADEONPTR(scrn); if (info->use_glamor) { struct radeon_pixmap *priv; priv = radeon_get_pixmap_private(pPix); - if (priv == NULL && bo == NULL) + if (!priv && !bo) return TRUE; if (priv) { @@ -729,7 +734,8 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo) if (priv->bo == bo) return TRUE; - radeon_bo_unref(priv->bo); + radeon_buffer_unref(&priv->bo); + priv->handle_valid = FALSE; } drmmode_fb_reference(pRADEONEnt->fd, &priv->fb, NULL); @@ -741,21 +747,18 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo) } if (bo) { - uint32_t pitch; - if (!priv) { priv = calloc(1, sizeof (struct radeon_pixmap)); if (!priv) return FALSE; } - radeon_bo_ref(bo); + radeon_buffer_ref(bo); priv->bo = bo; - - radeon_bo_get_tiling(bo, &priv->tiling_flags, &pitch); } radeon_set_pixmap_private(pPix, priv); + radeon_get_pixmap_tiling_flags(pPix); return TRUE; } else #endif /* USE_GLAMOR */ @@ -766,15 +769,18 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo) if (driver_priv) { uint32_t pitch; - if (driver_priv->bo) - radeon_bo_unref(driver_priv->bo); - + radeon_buffer_unref(&driver_priv->bo); drmmode_fb_reference(pRADEONEnt->fd, &driver_priv->fb, NULL); - radeon_bo_ref(bo); driver_priv->bo = bo; - radeon_bo_get_tiling(bo, &driver_priv->tiling_flags, &pitch); + if (bo) { + radeon_buffer_ref(bo); + radeon_bo_get_tiling(bo->bo.radeon, &driver_priv->tiling_flags, + &pitch); + } else + driver_priv->tiling_flags = 0; + return TRUE; } @@ -782,10 +788,10 @@ static inline Bool radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo) } } -static inline struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix) +static inline struct radeon_buffer *radeon_get_pixmap_bo(PixmapPtr pPix) { -#ifdef USE_GLAMOR RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen)); +#ifdef USE_GLAMOR if (info->use_glamor) { struct radeon_pixmap *priv; @@ -793,7 +799,7 @@ static inline struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix) return priv ? priv->bo : NULL; } else #endif - { + if (info->accelOn) { struct radeon_exa_pixmap_priv *driver_priv; driver_priv = exaGetPixmapDriverPrivate(pPix); return driver_priv ? driver_priv->bo : NULL; @@ -821,8 +827,8 @@ static inline Bool radeon_get_pixmap_shared(PixmapPtr pPix) } static inline struct drmmode_fb* -radeon_fb_create(int drm_fd, uint32_t width, uint32_t height, uint8_t depth, - uint8_t bpp, uint32_t pitch, uint32_t handle) +radeon_fb_create(ScrnInfoPtr scrn, int drm_fd, uint32_t width, uint32_t height, + uint32_t pitch, uint32_t handle) { struct drmmode_fb *fb = malloc(sizeof(*fb)); @@ -830,8 +836,8 @@ radeon_fb_create(int drm_fd, uint32_t width, uint32_t height, uint8_t depth, return NULL; fb->refcnt = 1; - if (drmModeAddFB(drm_fd, width, height, depth, bpp, pitch, handle, - &fb->handle) == 0) + if (drmModeAddFB(drm_fd, width, height, scrn->depth, scrn->bitsPerPixel, + pitch, handle, &fb->handle) == 0) return fb; free(fb); @@ -872,27 +878,28 @@ static inline struct drmmode_fb* radeon_pixmap_get_fb(PixmapPtr pix) { struct drmmode_fb **fb_ptr = radeon_pixmap_get_fb_ptr(pix); - - if (!fb_ptr) - return NULL; - - if (!*fb_ptr) { - uint32_t handle; - - if (radeon_get_pixmap_handle(pix, &handle)) { - ScrnInfoPtr scrn = xf86ScreenToScrn(pix->drawable.pScreen); - RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); - - *fb_ptr = radeon_fb_create(pRADEONEnt->fd, pix->drawable.width, - pix->drawable.height, pix->drawable.depth, - pix->drawable.bitsPerPixel, pix->devKind, - handle); - } + uint32_t handle; + + if (fb_ptr && *fb_ptr) + return *fb_ptr; + + if (radeon_get_pixmap_handle(pix, &handle)) { + ScrnInfoPtr scrn = xf86ScreenToScrn(pix->drawable.pScreen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); + + if (!fb_ptr) + fb_ptr = radeon_pixmap_get_fb_ptr(pix); + + *fb_ptr = radeon_fb_create(scrn, pRADEONEnt->fd, + pix->drawable.width, + pix->drawable.height, pix->devKind, + handle); } - return *fb_ptr; + return fb_ptr ? *fb_ptr : NULL; } + #define CP_PACKET0(reg, n) \ (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2)) #define CP_PACKET1(reg0, reg1) \ @@ -1001,7 +1008,7 @@ do { \ #define EMIT_OFFSET(reg, value, pPix, rd, wd) do { \ driver_priv = exaGetPixmapDriverPrivate(pPix); \ OUT_RING_REG((reg), (value)); \ - OUT_RING_RELOC(driver_priv->bo, (rd), (wd)); \ + OUT_RING_RELOC(driver_priv->bo->bo.radeon, (rd), (wd)); \ } while(0) #define EMIT_READ_OFFSET(reg, value, pPix) EMIT_OFFSET(reg, value, pPix, (RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT), 0) @@ -1015,7 +1022,7 @@ do { \ #define EMIT_COLORPITCH(reg, value, pPix) do { \ driver_priv = exaGetPixmapDriverPrivate(pPix); \ OUT_RING_REG((reg), value); \ - OUT_RING_RELOC(driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); \ + OUT_RING_RELOC(driver_priv->bo->bo.radeon, 0, RADEON_GEM_DOMAIN_VRAM); \ } while(0) static __inline__ void RADEON_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn) diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c index 0366f613..8b3e5797 100644 --- a/src/radeon_bo_helper.c +++ b/src/radeon_bo_helper.c @@ -28,6 +28,39 @@ #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 15: + return GBM_FORMAT_ARGB1555; + 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 */ @@ -59,10 +92,93 @@ static Bool RADEONMacroSwitch(int width, int height, int bpp, } } +static unsigned eg_tile_split_opp(unsigned tile_split) +{ + switch (tile_split) { + case 0: tile_split = 64; break; + case 1: tile_split = 128; break; + case 2: tile_split = 256; break; + case 3: tile_split = 512; break; + default: + case 4: tile_split = 1024; break; + case 5: tile_split = 2048; break; + case 6: tile_split = 4096; break; + } + return tile_split; +} + +Bool +radeon_surface_initialize(RADEONInfoPtr info, struct radeon_surface *surface, + int width, int height, int cpp, uint32_t tiling_flags, + int usage_hint) +{ + memset(surface, 0, sizeof(struct radeon_surface)); + + surface->npix_x = width; + /* need to align height to 8 for old kernel */ + surface->npix_y = RADEON_ALIGN(height, 8); + surface->npix_z = 1; + surface->blk_w = 1; + surface->blk_h = 1; + surface->blk_d = 1; + surface->array_size = 1; + surface->last_level = 0; + surface->bpe = cpp; + surface->nsamples = 1; + if (height < 128) { + /* disable 2d tiling for small surface to work around + * the fact that ddx align height to 8 pixel for old + * obscure reason i can't remember + */ + tiling_flags &= ~RADEON_TILING_MACRO; + } + + surface->flags = RADEON_SURF_SCANOUT | RADEON_SURF_HAS_TILE_MODE_INDEX | + RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); + + if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) { + surface->flags |= RADEON_SURF_ZBUFFER; + surface->flags |= RADEON_SURF_SBUFFER; + } + + if ((tiling_flags & RADEON_TILING_MACRO)) { + surface->flags = RADEON_SURF_CLR(surface->flags, MODE); + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); + } else if ((tiling_flags & RADEON_TILING_MICRO)) { + surface->flags = RADEON_SURF_CLR(surface->flags, MODE); + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); + } else + surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); + + if (info->ChipFamily >= CHIP_FAMILY_CEDAR) { + surface->bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & + RADEON_TILING_EG_BANKW_MASK; + surface->bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & + RADEON_TILING_EG_BANKH_MASK; + surface->tile_split = eg_tile_split_opp((tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & + RADEON_TILING_EG_TILE_SPLIT_MASK); + if (surface->flags & RADEON_SURF_SBUFFER) { + surface->stencil_tile_split = + (tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) & + RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK; + } + surface->mtilea = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & + RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK; + } + + if (radeon_surface_best(info->surf_man, surface)) + return FALSE; + + if (radeon_surface_init(info->surf_man, surface)) + return FALSE; + + return TRUE; +} + /* Calculate appropriate tiling and pitch for a pixmap and allocate a BO that * can hold it. */ -struct radeon_bo* +struct radeon_buffer * radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, int usage_hint, int bitsPerPixel, int *new_pitch, struct radeon_surface *new_surface, uint32_t *new_tiling) @@ -73,8 +189,48 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, int cpp = bitsPerPixel / 8; uint32_t tiling = 0, flags = 0; struct radeon_surface surface; - struct radeon_bo *bo; + 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) @@ -107,88 +263,73 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp; base_align = drmmode_get_base_align(pScrn, cpp, tiling); size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE); - memset(&surface, 0, sizeof(struct radeon_surface)); - - if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) { - if (width) { - surface.npix_x = width; - /* need to align height to 8 for old kernel */ - surface.npix_y = RADEON_ALIGN(height, 8); - surface.npix_z = 1; - surface.blk_w = 1; - surface.blk_h = 1; - surface.blk_d = 1; - surface.array_size = 1; - surface.last_level = 0; - surface.bpe = cpp; - surface.nsamples = 1; - if (height < 128) { - /* disable 2d tiling for small surface to work around - * the fact that ddx align height to 8 pixel for old - * obscure reason i can't remember - */ - tiling &= ~RADEON_TILING_MACRO; - } - surface.flags = RADEON_SURF_SCANOUT; - /* we are requiring a recent enough libdrm version */ - surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX; - surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); - surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE); - if ((tiling & RADEON_TILING_MICRO)) { - surface.flags = RADEON_SURF_CLR(surface.flags, MODE); - surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); - } - if ((tiling & RADEON_TILING_MACRO)) { - surface.flags = RADEON_SURF_CLR(surface.flags, MODE); - surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); - } - if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) { - surface.flags |= RADEON_SURF_ZBUFFER; - surface.flags |= RADEON_SURF_SBUFFER; - } - if (radeon_surface_best(info->surf_man, &surface)) { - return NULL; - } - if (radeon_surface_init(info->surf_man, &surface)) { - return NULL; - } - size = surface.bo_size; - base_align = surface.bo_alignment; - pitch = surface.level[0].pitch_bytes; - tiling = 0; - switch (surface.level[0].mode) { - case RADEON_SURF_MODE_2D: - tiling |= RADEON_TILING_MACRO; - tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT; - tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT; - tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT; - if (surface.tile_split) - tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT; - tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT; - break; - case RADEON_SURF_MODE_1D: - tiling |= RADEON_TILING_MICRO; - break; - default: - break; - } - } + + if (width && info->surf_man) { + if (!radeon_surface_initialize(info, &surface, width, height, cpp, + tiling, usage_hint)) + return NULL; + + size = surface.bo_size; + base_align = surface.bo_alignment; + pitch = surface.level[0].pitch_bytes; + tiling = 0; + switch (surface.level[0].mode) { + case RADEON_SURF_MODE_2D: + tiling |= RADEON_TILING_MACRO; + tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT; + tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT; + tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT; + if (surface.tile_split) + tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT; + if (surface.flags & RADEON_SURF_SBUFFER) + tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT; + break; + case RADEON_SURF_MODE_1D: + tiling |= RADEON_TILING_MICRO; + break; + default: + break; } + if (new_surface) + *new_surface = surface; + } + if (tiling) flags |= RADEON_GEM_NO_CPU_ACCESS; - bo = radeon_bo_open(info->bufmgr, 0, size, base_align, - domain, flags); + bo = calloc(1, sizeof(struct radeon_buffer)); + if (!bo) + return NULL; + + bo->ref_count = 1; + bo->bo.radeon = radeon_bo_open(info->bufmgr, 0, size, base_align, + domain, flags); - if (bo && tiling && radeon_bo_set_tiling(bo, tiling, pitch) == 0) + if (bo && tiling && radeon_bo_set_tiling(bo->bo.radeon, tiling, pitch) == 0) *new_tiling = tiling; - *new_surface = surface; *new_pitch = pitch; return bo; } + +/* Flush and wait for the BO to become idle */ +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); +} + + /* Clear the pixmap contents to black */ void radeon_pixmap_clear(PixmapPtr pixmap) @@ -213,7 +354,7 @@ radeon_pixmap_clear(PixmapPtr pixmap) /* Get GEM handle for the pixmap */ Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle) { - struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap); + struct radeon_buffer *bo = radeon_get_pixmap_bo(pixmap); #ifdef USE_GLAMOR ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); @@ -221,8 +362,8 @@ Bool radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle) RADEONInfoPtr info = RADEONPTR(scrn); #endif - if (bo) { - *handle = bo->handle; + if (bo && !(bo->flags & RADEON_BO_FLAGS_GBM)) { + *handle = bo->bo.radeon->handle; return TRUE; } @@ -305,87 +446,85 @@ Bool radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p) return TRUE; } -static unsigned eg_tile_split_opp(unsigned tile_split) -{ - switch (tile_split) { - case 0: tile_split = 64; break; - case 1: tile_split = 128; break; - case 2: tile_split = 256; break; - case 3: tile_split = 512; break; - default: - case 4: tile_split = 1024; break; - case 5: tile_split = 2048; break; - case 6: tile_split = 4096; break; - } - return tile_split; -} - Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle, struct radeon_surface *surface) { ScrnInfoPtr pScrn = xf86ScreenToScrn(ppix->drawable.pScreen); RADEONInfoPtr info = RADEONPTR(pScrn); - struct radeon_bo *bo; + struct radeon_buffer *bo; int ihandle = (int)(long)fd_handle; uint32_t size = ppix->devKind * ppix->drawable.height; Bool ret = FALSE; - bo = radeon_gem_bo_open_prime(info->bufmgr, ihandle, size); + if (ihandle == -1) + return radeon_set_pixmap_bo(ppix, NULL); + + bo = (struct radeon_buffer *)calloc(1, sizeof(struct radeon_buffer)); if (!bo) - goto error; + goto error; - memset(surface, 0, sizeof(struct radeon_surface)); +#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; + + bo->ref_count = 1; ret = radeon_set_pixmap_bo(ppix, bo); if (!ret) goto error; - if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) { + if (surface) { + struct radeon_exa_pixmap_priv *driver_priv; uint32_t tiling_flags; -#ifdef USE_GLAMOR - if (info->use_glamor) { - tiling_flags = radeon_get_pixmap_private(ppix)->tiling_flags; - } else -#endif - { - struct radeon_exa_pixmap_priv *driver_priv; - - driver_priv = exaGetPixmapDriverPrivate(ppix); - tiling_flags = driver_priv->tiling_flags; - } + driver_priv = exaGetPixmapDriverPrivate(ppix); + tiling_flags = driver_priv->tiling_flags; - surface->npix_x = ppix->drawable.width; - surface->npix_y = ppix->drawable.height; - surface->npix_z = 1; - surface->blk_w = 1; - surface->blk_h = 1; - surface->blk_d = 1; - surface->array_size = 1; - surface->bpe = ppix->drawable.bitsPerPixel / 8; - surface->nsamples = 1; - /* we are requiring a recent enough libdrm version */ - surface->flags |= RADEON_SURF_HAS_TILE_MODE_INDEX; - surface->flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); - if (tiling_flags & RADEON_TILING_MACRO) - surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); - else if (tiling_flags & RADEON_TILING_MICRO) - surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); - else - surface->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); - surface->bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK; - surface->bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK; - surface->tile_split = eg_tile_split_opp((tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK); - surface->stencil_tile_split = (tiling_flags >> RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK; - surface->mtilea = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK; - if (radeon_surface_best(info->surf_man, surface)) { - ret = FALSE; - goto error; - } - if (radeon_surface_init(info->surf_man, surface)) { + if (!radeon_surface_initialize(info, surface, ppix->drawable.width, + ppix->drawable.height, + ppix->drawable.bitsPerPixel / 8, + tiling_flags, 0)) { ret = FALSE; goto error; } + /* we have to post hack the surface to reflect the actual size of the shared pixmap */ surface->level[0].pitch_bytes = ppix->devKind; @@ -396,6 +535,6 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle, close(ihandle); /* we have a reference from the alloc and one from set pixmap bo, drop one */ - radeon_bo_unref(bo); + radeon_buffer_unref(&bo); return ret; } diff --git a/src/radeon_bo_helper.h b/src/radeon_bo_helper.h index e1856adb..cc3d1d3b 100644 --- a/src/radeon_bo_helper.h +++ b/src/radeon_bo_helper.h @@ -23,12 +23,32 @@ #ifndef RADEON_BO_HELPER_H #define RADEON_BO_HELPER_H 1 -extern struct radeon_bo* +#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 * radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth, int usage_hint, int bitsPerPixel, int *new_pitch, struct radeon_surface *new_surface, uint32_t *new_tiling); extern void +radeon_finish(ScrnInfoPtr scrn, struct radeon_buffer *bo); + +extern void radeon_pixmap_clear(PixmapPtr pixmap); extern uint32_t @@ -57,4 +77,37 @@ static inline PixmapPtr get_drawable_pixmap(DrawablePtr drawable) return drawable->pScreen->GetWindowPixmap((WindowPtr)drawable); } +static inline void +radeon_buffer_ref(struct radeon_buffer *buffer) +{ + buffer->ref_count++; +} + +static inline void +radeon_buffer_unref(struct radeon_buffer **buffer) +{ + struct radeon_buffer *buf = *buffer; + + if (!buf) + return; + + if (buf->ref_count > 1) { + buf->ref_count--; + return; + } + +#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; +} + #endif /* RADEON_BO_HELPER_H */ diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c index b569bb4f..17983779 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); + 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) @@ -125,6 +126,7 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen, cpp = 2; break; case 24: + case 30: cpp = 4; break; default: @@ -232,37 +234,42 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen, flags | RADEON_CREATE_PIXMAP_DRI2); } + if (!pixmap) + return NULL; + buffers = calloc(1, sizeof *buffers); - if (buffers == NULL) + if (!buffers) goto error; - if (pixmap) { - if (!info->use_glamor) { - info->exa_force_create = TRUE; - exaMoveInPixmap(pixmap); - info->exa_force_create = FALSE; - if (exaGetPixmapDriverPrivate(pixmap) == NULL) { - /* this happen if pixmap is non accelerable */ - goto error; - } - } else if (is_glamor_pixmap) { - pixmap = radeon_glamor_set_pixmap_bo(drawable, pixmap); - pixmap->refcnt++; + if (!info->use_glamor) { + info->exa_force_create = TRUE; + exaMoveInPixmap(pixmap); + info->exa_force_create = FALSE; + if (!exaGetPixmapDriverPrivate(pixmap)) { + /* this happen if pixmap is non accelerable */ + goto error; } + } else if (is_glamor_pixmap) { + pixmap = radeon_glamor_set_pixmap_bo(drawable, pixmap); + pixmap->refcnt++; - if (!radeon_get_flink_name(pRADEONEnt, pixmap, &buffers->name)) - goto error; + /* The copy operation from radeon_glamor_set_pixmap_bo needs to + * be flushed to the kernel driver before the client starts + * using the pixmap storage for direct rendering. + */ + radeon_cs_flush_indirect(pScrn); } + if (!radeon_get_flink_name(pRADEONEnt, pixmap, &buffers->name)) + goto error; + privates = calloc(1, sizeof(struct dri2_buffer_priv)); - if (privates == NULL) + if (!privates) goto error; buffers->attachment = attachment; - if (pixmap) { - buffers->pitch = pixmap->devKind; - buffers->cpp = cpp; - } + buffers->pitch = pixmap->devKind; + buffers->cpp = cpp; buffers->driverPrivate = privates; buffers->format = format; buffers->flags = 0; /* not tiled */ @@ -274,8 +281,7 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen, error: free(buffers); - if (pixmap) - (*pScreen->DestroyPixmap)(pixmap); + (*pScreen->DestroyPixmap)(pixmap); return NULL; } @@ -337,9 +343,7 @@ radeon_dri2_copy_region2(ScreenPtr pScreen, Bool vsync; Bool translate = FALSE; int off_x = 0, off_y = 0; - PixmapPtr dst_ppix; - dst_ppix = dst_private->pixmap; src_drawable = &src_private->pixmap->drawable; dst_drawable = &dst_private->pixmap->drawable; @@ -356,7 +360,6 @@ radeon_dri2_copy_region2(ScreenPtr pScreen, dst_drawable = DRI2UpdatePrime(drawable, dest_buffer); if (!dst_drawable) return; - dst_ppix = (PixmapPtr)dst_drawable; if (dst_drawable != drawable) translate = TRUE; } else @@ -380,26 +383,7 @@ radeon_dri2_copy_region2(ScreenPtr pScreen, (*gc->funcs->ChangeClip) (gc, CT_REGION, copy_clip, 0); ValidateGC(dst_drawable, gc); - /* If this is a full buffer swap or frontbuffer flush, throttle on the - * previous one - */ - if (dst_private->attachment == DRI2BufferFrontLeft) { - if (REGION_NUM_RECTS(region) == 1) { - BoxPtr extents = REGION_EXTENTS(pScreen, region); - - if (extents->x1 == 0 && extents->y1 == 0 && - extents->x2 == drawable->width && - extents->y2 == drawable->height) { - struct radeon_bo *bo = radeon_get_pixmap_bo(dst_ppix); - - if (bo) - radeon_bo_wait(bo); - } - } - } - vsync = info->accel_state->vsync; - /* Driver option "SwapbuffersWait" defines if we vsync DRI2 copy-swaps. */ info->accel_state->vsync = info->swapBuffersWait; info->accel_state->force = TRUE; @@ -525,18 +509,20 @@ static Bool radeon_dri2_get_crtc_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc) } static -xf86CrtcPtr radeon_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled) +xf86CrtcPtr radeon_dri2_drawable_crtc(DrawablePtr pDraw) { ScreenPtr pScreen = pDraw->pScreen; ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); - xf86CrtcPtr crtc = radeon_pick_best_crtc(pScrn, consider_disabled, + xf86CrtcPtr crtc = radeon_pick_best_crtc(pScrn, TRUE, pDraw->x, pDraw->x + pDraw->width, pDraw->y, pDraw->y + pDraw->height); - if (crtc && pDraw->type == DRAWABLE_WINDOW) { + if (pDraw->type == DRAWABLE_WINDOW) { struct dri2_window_priv *priv = get_dri2_window_priv((WindowPtr)pDraw); - if (priv->crtc && priv->crtc != crtc) { + if (!crtc) { + crtc = priv->crtc; + } else if (priv->crtc && priv->crtc != crtc) { CARD64 ust, mscold, mscnew; if (radeon_dri2_get_crtc_msc(priv->crtc, &ust, &mscold) && @@ -723,7 +709,7 @@ can_flip(xf86CrtcPtr crtc, DrawablePtr draw, if (draw->type != DRAWABLE_WINDOW || !info->allowPageFlip || - info->hwcursor_disabled || + info->sprites_visible > 0 || info->drmmode.present_flipping || !pScrn->vtSema || !DRI2CanFlip(draw)) @@ -742,9 +728,9 @@ radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPt { struct dri2_buffer_priv *front_priv = front->driverPrivate; struct dri2_buffer_priv *back_priv = back->driverPrivate; - struct radeon_bo *front_bo, *back_bo; - ScreenPtr screen; - RADEONInfoPtr info; +#ifdef USE_GLAMOR + RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(draw->pScreen)); +#endif RegionRec region; int tmp; @@ -759,23 +745,28 @@ radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPt front->name = back->name; back->name = tmp; - /* Swap pixmap bos */ - front_bo = radeon_get_pixmap_bo(front_priv->pixmap); - back_bo = radeon_get_pixmap_bo(back_priv->pixmap); - radeon_set_pixmap_bo(front_priv->pixmap, back_bo); - radeon_set_pixmap_bo(back_priv->pixmap, front_bo); - - /* Do we need to update the Screen? */ - screen = draw->pScreen; - info = RADEONPTR(xf86ScreenToScrn(screen)); - if (front_bo == info->front_bo) { - radeon_bo_ref(back_bo); - radeon_bo_unref(info->front_bo); - info->front_bo = back_bo; - radeon_set_pixmap_bo(screen->GetScreenPixmap(screen), back_bo); - } + /* Swap pixmap privates */ +#ifdef USE_GLAMOR + if (info->use_glamor) { + struct radeon_pixmap *front_pix, *back_pix; - radeon_glamor_exchange_buffers(front_priv->pixmap, back_priv->pixmap); + front_pix = radeon_get_pixmap_private(front_priv->pixmap); + back_pix = radeon_get_pixmap_private(back_priv->pixmap); + radeon_set_pixmap_private(front_priv->pixmap, back_pix); + radeon_set_pixmap_private(back_priv->pixmap, front_pix); + + radeon_glamor_exchange_buffers(front_priv->pixmap, back_priv->pixmap); + } else +#endif + { + struct radeon_exa_pixmap_priv driver_priv = *(struct radeon_exa_pixmap_priv*) + exaGetPixmapDriverPrivate(front_priv->pixmap); + + *(struct radeon_exa_pixmap_priv*)exaGetPixmapDriverPrivate(front_priv->pixmap) = + *(struct radeon_exa_pixmap_priv*)exaGetPixmapDriverPrivate(back_priv->pixmap); + *(struct radeon_exa_pixmap_priv*)exaGetPixmapDriverPrivate(back_priv->pixmap) = + driver_priv; + } DamageRegionProcessPending(&front_priv->pixmap->drawable); } @@ -938,10 +929,10 @@ CARD32 radeon_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 *target_msc, */ static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc) { - xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE); + xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw); /* Drawable not displayed, make up a value */ - if (crtc == NULL) { + if (!crtc) { *ust = 0; *msc = 0; return TRUE; @@ -986,32 +977,45 @@ CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data) scrn = crtc->scrn; pRADEONEnt = RADEONEntPriv(scrn); + drmmode_crtc = event_info->crtc->driver_private; ret = drmmode_get_current_ust(pRADEONEnt->fd, &drm_now); if (ret) { xf86DrvMsg(scrn->scrnIndex, X_ERROR, "%s cannot get current time\n", __func__); - if (event_info->drm_queue_seq) - radeon_drm_queue_handler(pRADEONEnt->fd, 0, 0, 0, - (void*)event_info->drm_queue_seq); - else + + if (event_info->drm_queue_seq) { + drmmode_crtc->drmmode->event_context. + vblank_handler(pRADEONEnt->fd, 0, 0, 0, + (void*)event_info->drm_queue_seq); + drmmode_crtc->wait_flip_nesting_level++; + radeon_drm_queue_handle_deferred(crtc); + + } else { radeon_dri2_frame_event_handler(crtc, 0, 0, data); + } + return 0; } /* * calculate the frame number from current time * that would come from CRTC if it were running */ - drmmode_crtc = event_info->crtc->driver_private; delta_t = drm_now - (CARD64)drmmode_crtc->dpms_last_ust; delta_seq = delta_t * drmmode_crtc->dpms_last_fps; delta_seq /= 1000000; frame = (CARD64)drmmode_crtc->dpms_last_seq + delta_seq; - if (event_info->drm_queue_seq) - radeon_drm_queue_handler(pRADEONEnt->fd, frame, drm_now / 1000000, - drm_now % 1000000, - (void*)event_info->drm_queue_seq); - else + + if (event_info->drm_queue_seq) { + drmmode_crtc->drmmode->event_context. + vblank_handler(pRADEONEnt->fd, frame, drm_now / 1000000, + drm_now % 1000000, + (void*)event_info->drm_queue_seq); + drmmode_crtc->wait_flip_nesting_level++; + radeon_drm_queue_handle_deferred(crtc); + } else { radeon_dri2_frame_event_handler(crtc, frame, drm_now, data); + } + return 0; } @@ -1040,7 +1044,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, ScrnInfoPtr scrn = xf86ScreenToScrn(screen); DRI2FrameEventPtr wait_info = NULL; uintptr_t drm_queue_seq = 0; - xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE); + xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw); uint32_t msc_delta; uint32_t seq; CARD64 current_msc; @@ -1052,7 +1056,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, remainder &= 0xffffffff; /* Drawable not visible, return immediately */ - if (crtc == NULL) + if (!crtc) goto out_complete; msc_delta = radeon_get_msc_delta(draw, crtc); @@ -1092,7 +1096,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, drm_queue_seq = radeon_drm_queue_alloc(crtc, client, RADEON_DRM_QUEUE_ID_DEFAULT, wait_info, radeon_dri2_frame_event_handler, - radeon_dri2_frame_event_abort); + radeon_dri2_frame_event_abort, FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM queue event entry failed.\n"); @@ -1155,6 +1159,9 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw, out_complete: if (wait_info) radeon_dri2_deferred_event(NULL, 0, wait_info); + else + DRI2WaitMSCComplete(client, draw, 0, 0, 0); + return TRUE; } @@ -1186,7 +1193,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, { ScreenPtr screen = draw->pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE); + xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw); uint32_t msc_delta; drmVBlankSeqType type; uint32_t seq; @@ -1211,7 +1218,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, radeon_dri2_ref_buffer(back); /* either off-screen or CRTC not usable... just complete the swap */ - if (crtc == NULL) + if (!crtc) goto blit_fallback; msc_delta = radeon_get_msc_delta(draw, crtc); @@ -1231,7 +1238,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw, drm_queue_seq = radeon_drm_queue_alloc(crtc, client, RADEON_DRM_QUEUE_ID_DEFAULT, swap_info, radeon_dri2_frame_event_handler, - radeon_dri2_frame_event_abort); + radeon_dri2_frame_event_abort, FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM queue entry failed.\n"); diff --git a/src/radeon_dri3.c b/src/radeon_dri3.c index 3e689ffd..f8f91c4b 100644 --- a/src/radeon_dri3.c +++ b/src/radeon_dri3.c @@ -37,6 +37,7 @@ #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> +#include <gbm.h> #include <errno.h> #include <libgen.h> @@ -169,6 +170,7 @@ static PixmapPtr radeon_dri3_pixmap_from_fd(ScreenPtr screen, if (priv) { radeon_set_pixmap_private(pixmap, priv); + pixmap->usage_hint |= RADEON_CREATE_PIXMAP_DRI2; return pixmap; } @@ -211,19 +213,28 @@ static int radeon_dri3_fd_from_pixmap(ScreenPtr screen, CARD16 *stride, CARD32 *size) { - struct radeon_bo *bo; + struct radeon_buffer *bo; int fd; - - bo = radeon_get_pixmap_bo(pixmap); - 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) { + int ret = glamor_fd_from_pixmap(screen, pixmap, stride, size); - if (info->use_glamor) - return glamor_fd_from_pixmap(screen, pixmap, stride, size); + /* Any pending drawing operations need to be flushed to the + * kernel driver before the client starts using the pixmap + * storage for direct rendering. + */ + if (ret >= 0) + radeon_cs_flush_indirect(scrn); + + return ret; + } #endif + bo = radeon_get_pixmap_bo(pixmap); + if (!bo) { exaMoveInPixmap(pixmap); bo = radeon_get_pixmap_bo(pixmap); if (!bo) @@ -233,11 +244,11 @@ static int radeon_dri3_fd_from_pixmap(ScreenPtr screen, if (pixmap->devKind > UINT16_MAX) return -1; - if (radeon_gem_prime_share_bo(bo, &fd) < 0) + if (radeon_gem_prime_share_bo(bo->bo.radeon, &fd) < 0) return -1; *stride = pixmap->devKind; - *size = bo->size; + *size = bo->bo.radeon->size; return fd; } diff --git a/src/radeon_drm_queue.c b/src/radeon_drm_queue.c index 869f95c3..fc043605 100644 --- a/src/radeon_drm_queue.c +++ b/src/radeon_drm_queue.c @@ -30,6 +30,8 @@ #include "config.h" #endif +#include <errno.h> + #include <xorg-server.h> #include <X11/Xdefs.h> #include <list.h> @@ -40,6 +42,7 @@ struct radeon_drm_queue_entry { struct xorg_list list; + uint64_t usec; uint64_t id; uintptr_t seq; void *data; @@ -47,36 +50,123 @@ struct radeon_drm_queue_entry { xf86CrtcPtr crtc; radeon_drm_handler_proc handler; radeon_drm_abort_proc abort; + Bool is_flip; + unsigned int frame; }; static int radeon_drm_queue_refcnt; static struct xorg_list radeon_drm_queue; +static struct xorg_list radeon_drm_flip_signalled; +static struct xorg_list radeon_drm_vblank_signalled; +static struct xorg_list radeon_drm_vblank_deferred; static uintptr_t radeon_drm_queue_seq; /* - * Handle a DRM event + * Process a DRM event */ -void +static void +radeon_drm_queue_handle_one(struct radeon_drm_queue_entry *e) +{ + xorg_list_del(&e->list); + if (e->handler) { + e->handler(e->crtc, e->frame, e->usec, e->data); + } else + e->abort(e->crtc, e->data); + free(e); +} + +/* + * Abort one queued DRM entry, removing it + * from the list, calling the abort function and + * freeing the memory + */ +static void +radeon_drm_abort_one(struct radeon_drm_queue_entry *e) +{ + xorg_list_del(&e->list); + e->abort(e->crtc, e->data); + free(e); +} + +static void radeon_drm_queue_handler(int fd, unsigned int frame, unsigned int sec, unsigned int usec, void *user_ptr) { - uintptr_t seq = (uintptr_t)user_ptr; - struct radeon_drm_queue_entry *e, *tmp; - - xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) { - if (e->seq == seq) { - xorg_list_del(&e->list); - if (e->handler) - e->handler(e->crtc, frame, - (uint64_t)sec * 1000000 + usec, - e->data); - else - e->abort(e->crtc, e->data); - free(e); - break; - } + uintptr_t seq = (uintptr_t)user_ptr; + struct radeon_drm_queue_entry *e, *tmp; + + xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) { + if (e->seq == seq) { + if (!e->handler) { + radeon_drm_abort_one(e); + break; + } + + xorg_list_del(&e->list); + e->usec = (uint64_t)sec * 1000000 + usec; + e->frame = frame; + xorg_list_append(&e->list, e->is_flip ? + &radeon_drm_flip_signalled : + &radeon_drm_vblank_signalled); + break; + } + } +} + +/* + * Handle signalled vblank events. If we're waiting for a flip event, + * put events for that CRTC in the vblank_deferred list. + */ +static void +radeon_drm_handle_vblank_signalled(void) +{ + drmmode_crtc_private_ptr drmmode_crtc; + struct radeon_drm_queue_entry *e; + + while (!xorg_list_is_empty(&radeon_drm_vblank_signalled)) { + e = xorg_list_first_entry(&radeon_drm_vblank_signalled, + struct radeon_drm_queue_entry, list); + drmmode_crtc = e->crtc->driver_private; + + if (drmmode_crtc->wait_flip_nesting_level == 0) { + radeon_drm_queue_handle_one(e); + continue; } + + xorg_list_del(&e->list); + xorg_list_append(&e->list, &radeon_drm_vblank_deferred); + } +} + +/* + * Handle deferred DRM vblank events + * + * This function must be called after radeon_drm_wait_pending_flip, once + * it's safe to attempt queueing a flip again + */ +void +radeon_drm_queue_handle_deferred(xf86CrtcPtr crtc) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + struct radeon_drm_queue_entry *e, *tmp; + + if (drmmode_crtc->wait_flip_nesting_level == 0 || + --drmmode_crtc->wait_flip_nesting_level > 0) + return; + + /* Put previously deferred vblank events for this CRTC back in the + * signalled queue + */ + xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_deferred, list) { + if (e->crtc != crtc) + continue; + + xorg_list_del(&e->list); + xorg_list_append(&e->list, &radeon_drm_vblank_signalled); + } + + radeon_drm_handle_vblank_signalled(); } /* @@ -87,7 +177,8 @@ uintptr_t radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client, uint64_t id, void *data, radeon_drm_handler_proc handler, - radeon_drm_abort_proc abort) + radeon_drm_abort_proc abort, + Bool is_flip) { struct radeon_drm_queue_entry *e; @@ -105,6 +196,7 @@ radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client, e->data = data; e->handler = handler; e->abort = abort; + e->is_flip = is_flip; xorg_list_append(&e->list, &radeon_drm_queue); @@ -112,19 +204,6 @@ radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client, } /* - * Abort one queued DRM entry, removing it - * from the list, calling the abort function and - * freeing the memory - */ -static void -radeon_drm_abort_one(struct radeon_drm_queue_entry *e) -{ - xorg_list_del(&e->list); - e->abort(e->crtc, e->data); - free(e); -} - -/* * Abort drm queue entries for a client * * NOTE: This keeps the entries in the list until the DRM event arrives, @@ -150,6 +229,23 @@ radeon_drm_abort_entry(uintptr_t seq) { struct radeon_drm_queue_entry *e, *tmp; + if (seq == RADEON_DRM_QUEUE_ERROR) + return; + + xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_signalled, list) { + if (e->seq == seq) { + radeon_drm_abort_one(e); + return; + } + } + + xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_vblank_deferred, list) { + if (e->seq == seq) { + radeon_drm_abort_one(e); + return; + } + } + xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) { if (e->seq == seq) { radeon_drm_abort_one(e); @@ -175,15 +271,83 @@ radeon_drm_abort_id(uint64_t id) } /* + * drmHandleEvent wrapper + */ +int +radeon_drm_handle_event(int fd, drmEventContext *event_context) +{ + struct radeon_drm_queue_entry *e; + int r; + + /* Retry drmHandleEvent if it was interrupted by a signal in read() */ + do { + r = drmHandleEvent(fd, event_context); + } while (r < 0 && (errno == EINTR || errno == EAGAIN)); + + if (r < 0) { + static Bool printed; + + if (!printed) { + ErrorF("%s: drmHandleEvent returned %d, errno=%d (%s)\n", + __func__, r, errno, strerror(errno)); + printed = TRUE; + } + } + + while (!xorg_list_is_empty(&radeon_drm_flip_signalled)) { + e = xorg_list_first_entry(&radeon_drm_flip_signalled, + struct radeon_drm_queue_entry, list); + radeon_drm_queue_handle_one(e); + } + + radeon_drm_handle_vblank_signalled(); + + return r; +} + +/* + * Wait for pending page flip on given CRTC to complete + */ +void radeon_drm_wait_pending_flip(xf86CrtcPtr crtc) +{ + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); + struct radeon_drm_queue_entry *e; + + drmmode_crtc->wait_flip_nesting_level++; + + while (drmmode_crtc->flip_pending && + !xorg_list_is_empty(&radeon_drm_flip_signalled)) { + e = xorg_list_first_entry(&radeon_drm_flip_signalled, + struct radeon_drm_queue_entry, list); + radeon_drm_queue_handle_one(e); + } + + while (drmmode_crtc->flip_pending + && radeon_drm_handle_event(pRADEONEnt->fd, + &drmmode_crtc->drmmode->event_context) >= 0); +} + +/* * Initialize the DRM event queue */ void -radeon_drm_queue_init() +radeon_drm_queue_init(ScrnInfoPtr scrn) { + RADEONInfoPtr info = RADEONPTR(scrn); + drmmode_ptr drmmode = &info->drmmode; + + drmmode->event_context.version = 2; + drmmode->event_context.vblank_handler = radeon_drm_queue_handler; + drmmode->event_context.page_flip_handler = radeon_drm_queue_handler; + if (radeon_drm_queue_refcnt++) return; xorg_list_init(&radeon_drm_queue); + xorg_list_init(&radeon_drm_flip_signalled); + xorg_list_init(&radeon_drm_vblank_signalled); + xorg_list_init(&radeon_drm_vblank_deferred); } /* diff --git a/src/radeon_drm_queue.h b/src/radeon_drm_queue.h index c3e2076d..19d42e93 100644 --- a/src/radeon_drm_queue.h +++ b/src/radeon_drm_queue.h @@ -40,17 +40,18 @@ typedef void (*radeon_drm_handler_proc)(xf86CrtcPtr crtc, uint32_t seq, uint64_t usec, void *data); typedef void (*radeon_drm_abort_proc)(xf86CrtcPtr crtc, void *data); -void radeon_drm_queue_handler(int fd, unsigned int frame, - unsigned int tv_sec, unsigned int tv_usec, - void *user_ptr); +void radeon_drm_queue_handle_deferred(xf86CrtcPtr crtc); uintptr_t radeon_drm_queue_alloc(xf86CrtcPtr crtc, ClientPtr client, uint64_t id, void *data, radeon_drm_handler_proc handler, - radeon_drm_abort_proc abort); + radeon_drm_abort_proc abort, + Bool is_flip); void radeon_drm_abort_client(ClientPtr client); void radeon_drm_abort_entry(uintptr_t seq); void radeon_drm_abort_id(uint64_t id); -void radeon_drm_queue_init(); +int radeon_drm_handle_event(int fd, drmEventContext *event_context); +void radeon_drm_wait_pending_flip(xf86CrtcPtr crtc); +void radeon_drm_queue_init(ScrnInfoPtr scrn); void radeon_drm_queue_close(ScrnInfoPtr scrn); #endif /* _RADEON_DRM_QUEUE_H_ */ diff --git a/src/radeon_exa.c b/src/radeon_exa.c index 9106d5c6..320ff992 100644 --- a/src/radeon_exa.c +++ b/src/radeon_exa.c @@ -150,7 +150,7 @@ Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix, uint32_t *pitch_offset) */ Bool radeon_transform_is_affine_or_scaled(PictTransformPtr t) { - if (t == NULL) + if (!t) return TRUE; /* the shaders don't handle scaling either */ return t->matrix[2][0] == 0 && t->matrix[2][1] == 0 && t->matrix[2][2] == IntToxFixed(1); @@ -184,11 +184,11 @@ Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index) return FALSE; /* if we have more refs than just the BO then flush */ - if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { + if (radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) { flush = TRUE; if (can_fail) { - possible_domains = radeon_bo_get_src_domain(driver_priv->bo); + possible_domains = radeon_bo_get_src_domain(driver_priv->bo->bo.radeon); if (possible_domains == RADEON_GEM_DOMAIN_VRAM) return FALSE; /* use DownloadFromScreen */ } @@ -196,7 +196,7 @@ Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index) /* if the BO might end up in VRAM, prefer DownloadFromScreen */ if (can_fail && (possible_domains & RADEON_GEM_DOMAIN_VRAM)) { - radeon_bo_is_busy(driver_priv->bo, ¤t_domain); + radeon_bo_is_busy(driver_priv->bo->bo.radeon, ¤t_domain); if (current_domain & possible_domains) { if (current_domain == RADEON_GEM_DOMAIN_VRAM) @@ -209,14 +209,14 @@ Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index) radeon_cs_flush_indirect(pScrn); /* flush IB */ - ret = radeon_bo_map(driver_priv->bo, 1); + ret = radeon_bo_map(driver_priv->bo->bo.radeon, 1); if (ret) { FatalError("failed to map pixmap %d\n", ret); return FALSE; } driver_priv->bo_mapped = TRUE; - pPix->devPrivate.ptr = driver_priv->bo->ptr; + pPix->devPrivate.ptr = driver_priv->bo->bo.radeon->ptr; return TRUE; } @@ -229,41 +229,12 @@ void RADEONFinishAccess_CS(PixmapPtr pPix, int index) if (!driver_priv || !driver_priv->bo_mapped) return; - radeon_bo_unmap(driver_priv->bo); + radeon_bo_unmap(driver_priv->bo->bo.radeon); driver_priv->bo_mapped = FALSE; pPix->devPrivate.ptr = NULL; } -void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align) -{ - ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); - RADEONInfoPtr info = RADEONPTR(pScrn); - struct radeon_exa_pixmap_priv *new_priv; - - if (size != 0 && !info->exa_force_create && - info->exa_pixmaps == FALSE) - return NULL; - - new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv)); - if (!new_priv) - return NULL; - - if (size == 0) - return new_priv; - - new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, align, - RADEON_GEM_DOMAIN_VRAM, 0); - if (!new_priv->bo) { - free(new_priv); - ErrorF("Failed to alloc memory\n"); - return NULL; - } - - return new_priv; - -} - void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height, int depth, int usage_hint, int bitsPerPixel, int *new_pitch) @@ -306,17 +277,16 @@ void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv) if (!driverPriv) return; - if (driver_priv->bo) - radeon_bo_unref(driver_priv->bo); + radeon_buffer_unref(&driver_priv->bo); drmmode_fb_reference(pRADEONEnt->fd, &driver_priv->fb, NULL); free(driverPriv); } -Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **fd_handle) +Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr seconndary, void **fd_handle) { struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(ppix); - if (!radeon_share_pixmap_backing(driver_priv->bo, fd_handle)) + if (!radeon_share_pixmap_backing(driver_priv->bo->bo.radeon, fd_handle)) return FALSE; driver_priv->shared = TRUE; @@ -326,11 +296,12 @@ Bool RADEONEXASharePixmapBacking(PixmapPtr ppix, ScreenPtr slave, void **fd_hand Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle) { struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(ppix); + int ihandle = (int)(long)fd_handle; if (!radeon_set_shared_pixmap_backing(ppix, fd_handle, &driver_priv->surface)) return FALSE; - driver_priv->shared = TRUE; + driver_priv->shared = ihandle != -1; return TRUE; } diff --git a/src/radeon_exa_funcs.c b/src/radeon_exa_funcs.c index da0524ed..b3200cc9 100644 --- a/src/radeon_exa_funcs.c +++ b/src/radeon_exa_funcs.c @@ -138,7 +138,8 @@ RADEONPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) radeon_cs_space_reset_bos(info->cs); driver_priv = exaGetPixmapDriverPrivate(pPix); - radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); + radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 0, + RADEON_GEM_DOMAIN_VRAM); ret = radeon_cs_space_check(info->cs); if (ret) @@ -146,7 +147,7 @@ RADEONPrepareSolid(PixmapPtr pPix, int alu, Pixel pm, Pixel fg) driver_priv = exaGetPixmapDriverPrivate(pPix); if (driver_priv) { - info->state_2d.dst_bo = driver_priv->bo; + info->state_2d.dst_bo = driver_priv->bo->bo.radeon; info->state_2d.dst_domain = driver_priv->shared ? RADEON_GEM_DOMAIN_GTT : RADEON_GEM_DOMAIN_VRAM; } @@ -256,13 +257,15 @@ RADEONPrepareCopy(PixmapPtr pSrc, PixmapPtr pDst, radeon_cs_space_reset_bos(info->cs); driver_priv = exaGetPixmapDriverPrivate(pSrc); - radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); - info->state_2d.src_bo = driver_priv->bo; + radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, + RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); + info->state_2d.src_bo = driver_priv->bo->bo.radeon; driver_priv = exaGetPixmapDriverPrivate(pDst); - info->state_2d.dst_bo = driver_priv->bo; + info->state_2d.dst_bo = driver_priv->bo->bo.radeon; info->state_2d.dst_domain = driver_priv->shared ? RADEON_GEM_DOMAIN_GTT : RADEON_GEM_DOMAIN_VRAM; - radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, info->state_2d.dst_domain); + radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 0, + info->state_2d.dst_domain); ret = radeon_cs_space_check(info->cs); if (ret) @@ -328,7 +331,7 @@ RADEONBlitChunk(ScrnInfoPtr pScrn, struct radeon_bo *src_bo, if (src_bo && dst_bo) { BEGIN_ACCEL_RELOC(6, 2); - } else if (src_bo && dst_bo == NULL) { + } else if (src_bo && !dst_bo) { BEGIN_ACCEL_RELOC(6, 1); } else { BEGIN_RING(2*6); @@ -389,7 +392,7 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h, return FALSE; driver_priv = exaGetPixmapDriverPrivate(pDst); - if (!driver_priv || !driver_priv->bo) + if (!driver_priv || !driver_priv->bo->bo.radeon) return FALSE; #if X_BYTE_ORDER == X_BIG_ENDIAN @@ -404,12 +407,12 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h, #endif /* If we know the BO won't be busy / in VRAM, don't bother with a scratch */ - copy_dst = driver_priv->bo; + copy_dst = driver_priv->bo->bo.radeon; copy_pitch = pDst->devKind; if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { - if (!radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { + if (!radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) { flush = FALSE; - if (!radeon_bo_is_busy(driver_priv->bo, &dst_domain) && + if (!radeon_bo_is_busy(driver_priv->bo->bo.radeon, &dst_domain) && !(dst_domain & RADEON_GEM_DOMAIN_VRAM)) goto copy; } @@ -420,7 +423,7 @@ RADEONUploadToScreenCS(PixmapPtr pDst, int x, int y, int w, int h, size = scratch_pitch * h; scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0); - if (scratch == NULL) { + if (!scratch) { goto copy; } radeon_cs_space_reset_bos(info->cs); @@ -446,7 +449,7 @@ copy: r = TRUE; size = w * bpp / 8; dst = copy_dst->ptr; - if (copy_dst == driver_priv->bo) + if (copy_dst == driver_priv->bo->bo.radeon) dst += y * copy_pitch + x * bpp / 8; for (i = 0; i < h; i++) { RADEONCopySwap(dst + i * copy_pitch, (uint8_t*)src, size, swap); @@ -458,7 +461,7 @@ copy: RADEONGetDatatypeBpp(pDst->drawable.bitsPerPixel, &datatype); RADEONGetPixmapOffsetPitch(pDst, &dst_pitch_offset); RADEON_SWITCH_TO_2D(); - RADEONBlitChunk(pScrn, scratch, driver_priv->bo, datatype, scratch_pitch << 16, + RADEONBlitChunk(pScrn, scratch, driver_priv->bo->bo.radeon, datatype, scratch_pitch << 16, dst_pitch_offset, 0, 0, x, y, w, h, RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_VRAM); } @@ -493,7 +496,7 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, return FALSE; driver_priv = exaGetPixmapDriverPrivate(pSrc); - if (!driver_priv || !driver_priv->bo) + if (!driver_priv || !driver_priv->bo->bo.radeon) return FALSE; #if X_BYTE_ORDER == X_BIG_ENDIAN @@ -508,11 +511,11 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, #endif /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */ - copy_src = driver_priv->bo; + copy_src = driver_priv->bo->bo.radeon; copy_pitch = pSrc->devKind; if (!(driver_priv->tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) { - if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { - src_domain = radeon_bo_get_src_domain(driver_priv->bo); + if (radeon_bo_is_referenced_by_cs(driver_priv->bo->bo.radeon, info->cs)) { + src_domain = radeon_bo_get_src_domain(driver_priv->bo->bo.radeon); if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) == (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) src_domain = 0; @@ -521,14 +524,14 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, } if (!src_domain) - radeon_bo_is_busy(driver_priv->bo, &src_domain); + radeon_bo_is_busy(driver_priv->bo->bo.radeon, &src_domain); if (src_domain & ~(uint32_t)RADEON_GEM_DOMAIN_VRAM) goto copy; } size = scratch_pitch * h; scratch = radeon_bo_open(info->bufmgr, 0, size, 0, RADEON_GEM_DOMAIN_GTT, 0); - if (scratch == NULL) { + if (!scratch) { goto copy; } radeon_cs_space_reset_bos(info->cs); @@ -541,8 +544,8 @@ RADEONDownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w, RADEONGetDatatypeBpp(pSrc->drawable.bitsPerPixel, &datatype); RADEONGetPixmapOffsetPitch(pSrc, &src_pitch_offset); RADEON_SWITCH_TO_2D(); - RADEONBlitChunk(pScrn, driver_priv->bo, scratch, datatype, src_pitch_offset, - scratch_pitch << 16, x, y, 0, 0, w, h, + RADEONBlitChunk(pScrn, driver_priv->bo->bo.radeon, scratch, datatype, + src_pitch_offset, scratch_pitch << 16, x, y, 0, 0, w, h, RADEON_GEM_DOMAIN_VRAM | RADEON_GEM_DOMAIN_GTT, RADEON_GEM_DOMAIN_GTT); copy_src = scratch; @@ -561,7 +564,7 @@ copy: } r = TRUE; w *= bpp / 8; - if (copy_src == driver_priv->bo) + if (copy_src == driver_priv->bo->bo.radeon) size = y * copy_pitch + x * bpp / 8; else size = 0; @@ -581,7 +584,7 @@ Bool RADEONDrawInit(ScreenPtr pScreen) { RINFO_FROM_SCREEN(pScreen); - if (info->accel_state->exa == NULL) { + if (!info->accel_state->exa) { xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map not set up\n"); return FALSE; } @@ -638,7 +641,6 @@ Bool RADEONDrawInit(ScreenPtr pScreen) } #endif - info->accel_state->exa->CreatePixmap = RADEONEXACreatePixmap; info->accel_state->exa->DestroyPixmap = RADEONEXADestroyPixmap; info->accel_state->exa->PixmapIsOffscreen = RADEONEXAPixmapIsOffscreen; info->accel_state->exa->PrepareAccess = RADEONPrepareAccess_CS; diff --git a/src/radeon_exa_render.c b/src/radeon_exa_render.c index 9510f7f4..c61d83f4 100644 --- a/src/radeon_exa_render.c +++ b/src/radeon_exa_render.c @@ -630,7 +630,7 @@ static Bool R100PrepareComposite(int op, return FALSE; pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE; - if (pMask != NULL) { + if (pMask) { if (!R100TextureSetup(pMaskPicture, pMask, 1)) return FALSE; pp_cntl |= RADEON_TEX_1_ENABLE; @@ -992,7 +992,7 @@ static Bool R200PrepareComposite(int op, PicturePtr pSrcPicture, return FALSE; pp_cntl = RADEON_TEX_0_ENABLE | RADEON_TEX_BLEND_0_ENABLE; - if (pMask != NULL) { + if (pMask) { if (!R200TextureSetup(pMaskPicture, pMask, 1)) return FALSE; pp_cntl |= RADEON_TEX_1_ENABLE; @@ -1484,7 +1484,7 @@ static Bool R300PrepareComposite(int op, PicturePtr pSrcPicture, return FALSE; txenable = R300_TEX_0_ENABLE; - if (pMask != NULL) { + if (pMask) { if (!R300TextureSetup(pMaskPicture, pMask, 1)) return FALSE; txenable |= R300_TEX_1_ENABLE; diff --git a/src/radeon_exa_shared.c b/src/radeon_exa_shared.c index cca1c67e..94238a5a 100644 --- a/src/radeon_exa_shared.c +++ b/src/radeon_exa_shared.c @@ -129,7 +129,7 @@ PixmapPtr RADEONSolidPixmap(ScreenPtr pScreen, uint32_t solid) struct radeon_bo *bo; exaMoveInPixmap(pPix); - bo = radeon_get_pixmap_bo(pPix); + bo = radeon_get_pixmap_bo(pPix)->bo.radeon; if (radeon_bo_map(bo, 1)) { pScreen->DestroyPixmap(pPix); diff --git a/src/radeon_exa_shared.h b/src/radeon_exa_shared.h index 3df7fa20..fe28c230 100644 --- a/src/radeon_exa_shared.h +++ b/src/radeon_exa_shared.h @@ -66,7 +66,8 @@ static inline void radeon_add_pixmap(struct radeon_cs *cs, PixmapPtr pPix, int r { struct radeon_exa_pixmap_priv *driver_priv = exaGetPixmapDriverPrivate(pPix); - radeon_cs_space_add_persistent_bo(cs, driver_priv->bo, read_domains, write_domain); + radeon_cs_space_add_persistent_bo(cs, driver_priv->bo->bo.radeon, + read_domains, write_domain); } extern void radeon_ib_discard(ScrnInfoPtr pScrn); diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c index 5f378743..ccf99941 100644 --- a/src/radeon_glamor.c +++ b/src/radeon_glamor.c @@ -50,6 +50,7 @@ radeon_glamor_exchange_buffers(PixmapPtr src, Bool radeon_glamor_create_screen_resources(ScreenPtr screen) { + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); ScrnInfoPtr scrn = xf86ScreenToScrn(screen); RADEONInfoPtr info = RADEONPTR(scrn); @@ -61,13 +62,8 @@ radeon_glamor_create_screen_resources(ScreenPtr screen) return FALSE; #endif - if (!glamor_egl_create_textured_screen(screen, - info->front_bo->handle, - scrn->displayWidth * - info->pixel_bytes)) - return FALSE; - - return TRUE; + return radeon_glamor_create_textured_pixmap(screen_pixmap, + info->front_buffer); } @@ -113,9 +109,22 @@ radeon_glamor_pre_init(ScrnInfoPtr scrn) "glamor may not work (well) with GPUs < RV515.\n"); } +#if XORG_VERSION_CURRENT < XORG_VERSION_NUMERIC(1,20,99,0,0) if (scrn->depth < 24) { +#else + if (scrn->depth < 15) { +#endif xf86DrvMsg(scrn->scrnIndex, s ? X_ERROR : X_WARNING, - "glamor requires depth >= 24, disabling.\n"); + "Depth %d not supported with glamor, disabling\n", + scrn->depth); + return FALSE; + } + + if (scrn->depth == 30 && + xorgGetVersion() < XORG_VERSION_NUMERIC(1,19,99,1,0)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Depth 30 is not supported by GLAMOR with Xorg < " + "1.19.99.1\n"); return FALSE; } @@ -128,6 +137,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); @@ -156,10 +172,26 @@ 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->handle, - pixmap->devKind); + ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); + RADEONInfoPtr info = RADEONPTR(scrn); + + if (!info->use_glamor) + return TRUE; + + if (bo->flags & RADEON_BO_FLAGS_GBM) { + return glamor_egl_create_textured_pixmap_from_gbm_bo(pixmap, + bo->bo.gbm +#if XORG_VERSION_CURRENT > XORG_VERSION_NUMERIC(1,19,99,903,0) + , FALSE +#endif + ); + } else { + return glamor_egl_create_textured_pixmap(pixmap, + bo->bo.radeon->handle, + pixmap->devKind); + } } static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap) @@ -171,13 +203,6 @@ static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap) #endif if (pixmap->refcnt == 1) { - if (pixmap->devPrivate.ptr) { - struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap); - - if (bo) - radeon_bo_unmap(bo); - } - #ifdef HAVE_GLAMOR_EGL_DESTROY_TEXTURED_PIXMAP glamor_egl_destroy_textured_pixmap(pixmap); #endif @@ -206,6 +231,9 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, struct radeon_pixmap *priv; PixmapPtr pixmap, new_pixmap = NULL; + if (!xf86GetPixFormat(scrn, depth)) + return NULL; + if (!RADEON_CREATE_PIXMAP_SHARED(usage)) { if (info->shadow_primary) { if (usage != CREATE_PIXMAP_USAGE_BACKING_PIXMAP) @@ -234,13 +262,12 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, int stride; priv = calloc(1, sizeof (struct radeon_pixmap)); - if (priv == NULL) + if (!priv) goto fallback_pixmap; priv->bo = radeon_alloc_pixmap_bo(scrn, w, h, depth, usage, pixmap->drawable.bitsPerPixel, - &stride, - &priv->surface, + &stride, NULL, &priv->tiling_flags); if (!priv->bo) goto fallback_priv; @@ -249,7 +276,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; @@ -279,7 +306,7 @@ fallback_glamor: * afterwards. */ new_pixmap = glamor_create_pixmap(screen, w, h, depth, usage); - radeon_bo_unref(priv->bo); + radeon_buffer_unref(&priv->bo); fallback_priv: free(priv); fallback_pixmap: @@ -339,7 +366,7 @@ radeon_glamor_set_pixmap_bo(DrawablePtr drawable, PixmapPtr pixmap) static Bool -radeon_glamor_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr slave, +radeon_glamor_share_pixmap_backing(PixmapPtr pixmap, ScreenPtr secondary, void **handle_p) { ScreenPtr screen = pixmap->drawable.pScreen; @@ -380,16 +407,14 @@ radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle) { ScreenPtr screen = pixmap->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); - struct radeon_surface surface; - struct radeon_pixmap *priv; + int ihandle = (int)(long)handle; - if (!radeon_set_shared_pixmap_backing(pixmap, handle, &surface)) + if (!radeon_set_shared_pixmap_backing(pixmap, handle, NULL)) return FALSE; - priv = radeon_get_pixmap_private(pixmap); - priv->surface = surface; - - if (!radeon_glamor_create_textured_pixmap(pixmap, priv)) { + if (ihandle != -1 && + !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..61d54e36 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->pScreen); + 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_glamor_wrappers.c b/src/radeon_glamor_wrappers.c index d7374252..edffd9ad 100644 --- a/src/radeon_glamor_wrappers.c +++ b/src/radeon_glamor_wrappers.c @@ -55,17 +55,17 @@ radeon_glamor_prepare_access_cpu(ScrnInfoPtr scrn, RADEONInfoPtr info, PixmapPtr pixmap, struct radeon_pixmap *priv, Bool need_sync) { - struct radeon_bo *bo = priv->bo; + struct radeon_buffer *bo = priv->bo; int ret; - /* When falling back to swrast, flush all pending operations */ - if (need_sync) { - glamor_block_handler(scrn->pScreen); - info->gpu_flushed++; - } - if (!pixmap->devPrivate.ptr) { - ret = radeon_bo_map(bo, 1); + /* When falling back to swrast, flush all pending operations */ + if (need_sync) { + glamor_block_handler(scrn->pScreen); + info->gpu_flushed++; + } + + ret = radeon_bo_map(bo->bo.radeon, 1); if (ret) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: bo map (tiling_flags %d) failed: %s\n", @@ -75,12 +75,11 @@ radeon_glamor_prepare_access_cpu(ScrnInfoPtr scrn, RADEONInfoPtr info, return FALSE; } - pixmap->devPrivate.ptr = bo->ptr; - info->gpu_synced = info->gpu_flushed; - } else if (need_sync) { - radeon_bo_wait(bo); - info->gpu_synced = info->gpu_flushed; - } + pixmap->devPrivate.ptr = bo->bo.radeon->ptr; + } else if (need_sync) + radeon_finish(scrn, bo); + + info->gpu_synced = info->gpu_flushed; return TRUE; } @@ -133,7 +132,7 @@ radeon_glamor_finish_access_cpu(PixmapPtr pixmap) static Bool radeon_glamor_prepare_access_gpu(struct radeon_pixmap *priv) { - return priv != NULL; + return !!priv; } static void @@ -202,7 +201,7 @@ radeon_glamor_picture_prepare_access_cpu_ro(ScrnInfoPtr scrn, PixmapPtr pixmap; struct radeon_pixmap *priv; - if (picture->pDrawable == NULL) + if (!picture->pDrawable) return TRUE; pixmap = get_drawable_pixmap(picture->pDrawable); diff --git a/src/radeon_kms.c b/src/radeon_kms.c index 9ef51693..62962d61 100644 --- a/src/radeon_kms.c +++ b/src/radeon_kms.c @@ -38,6 +38,7 @@ #include "radeon_reg.h" #include "radeon_probe.h" #include "micmap.h" +#include "mipointrst.h" #include "radeon_version.h" #include "shadow.h" @@ -66,6 +67,7 @@ #include "radeon_vbo.h" static DevScreenPrivateKeyRec radeon_client_private_key; +DevScreenPrivateKeyRec radeon_device_private_key; extern SymTabRec RADEONChipsets[]; static Bool radeon_setup_kernel_mem(ScreenPtr pScreen); @@ -192,17 +194,38 @@ static Bool RADEONGetRec(ScrnInfoPtr pScrn) /* Free our private RADEONInfoRec */ static void RADEONFreeRec(ScrnInfoPtr pScrn) { + DevUnion *pPriv; RADEONEntPtr pRADEONEnt; RADEONInfoPtr info; + EntityInfoPtr pEnt; - if (!pScrn || !pScrn->driverPrivate) return; + if (!pScrn) + return; + + pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); + pPriv = xf86GetEntityPrivate(pEnt->index, gRADEONEntityIndex); + pRADEONEnt = pPriv->ptr; info = RADEONPTR(pScrn); + if (info) { + if (info->fbcon_pixmap) + pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap); - if (info->fbcon_pixmap) - pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap); + if (info->accel_state) { + free(info->accel_state); + info->accel_state = NULL; + } + +#ifdef USE_GLAMOR + if (info->gbm) + gbm_device_destroy(info->gbm); +#endif - pRADEONEnt = RADEONEntPriv(pScrn); + pRADEONEnt->scrn[info->instance_id] = NULL; + pRADEONEnt->num_scrns--; + free(pScrn->driverPrivate); + pScrn->driverPrivate = NULL; + } if (pRADEONEnt->fd > 0) { DevUnion *pPriv; @@ -218,17 +241,12 @@ static void RADEONFreeRec(ScrnInfoPtr pScrn) pRADEONEnt->platform_dev->flags & XF86_PDEV_SERVER_FD)) #endif drmClose(pRADEONEnt->fd); - pRADEONEnt->fd = 0; + free(pPriv->ptr); + pPriv->ptr = NULL; } } - if (info->accel_state) { - free(info->accel_state); - info->accel_state = NULL; - } - - free(pScrn->driverPrivate); - pScrn->driverPrivate = NULL; + free(pEnt); } static void * @@ -242,7 +260,7 @@ radeonShadowWindow(ScreenPtr screen, CARD32 row, CARD32 offset, int mode, stride = (pScrn->displayWidth * pScrn->bitsPerPixel) / 8; *size = stride; - return ((uint8_t *)info->front_bo->ptr + row * stride + offset); + return ((uint8_t *)info->front_buffer->bo.radeon->ptr + row * stride + offset); } static void @@ -314,7 +332,6 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); RADEONInfoPtr info = RADEONPTR(pScrn); PixmapPtr pixmap; - struct radeon_surface *surface; pScreen->CreateScreenResources = info->CreateScreenResources; if (!(*pScreen->CreateScreenResources)(pScreen)) @@ -332,13 +349,13 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen) RROutputChanged(rrScrPriv->primaryOutput, FALSE); rrScrPriv->layoutChanged = TRUE; } + + drmmode_uevent_init(pScrn, &info->drmmode); } if (!drmmode_set_desired_modes(pScrn, &info->drmmode, pScreen->isGPU)) return FALSE; - drmmode_uevent_init(pScrn, &info->drmmode); - if (info->r600_shadow_fb) { pixmap = pScreen->GetScreenPixmap(pScreen); @@ -348,14 +365,13 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen) } if (info->dri2.enabled || info->use_glamor) { - if (info->front_bo) { + if (info->front_buffer) { PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen); - if (!radeon_set_pixmap_bo(pPix, info->front_bo)) + if (!radeon_set_pixmap_bo(pPix, info->front_buffer)) return FALSE; - surface = radeon_get_pixmap_surface(pPix); - if (surface) { - *surface = info->front_surface; - } + + if (info->surf_man && !info->use_glamor) + *radeon_get_pixmap_surface(pPix) = info->front_surface; } } @@ -510,10 +526,14 @@ radeon_scanout_flip_abort(xf86CrtcPtr crtc, void *event_data) { RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + struct drmmode_fb *fb = event_data; - drmmode_crtc->scanout_update_pending = FALSE; - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, - NULL); + drmmode_crtc->scanout_update_pending = 0; + + if (drmmode_crtc->flip_pending == fb) { + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, + NULL); + } } static void @@ -522,19 +542,10 @@ radeon_scanout_flip_handler(xf86CrtcPtr crtc, uint32_t msc, uint64_t usec, { RADEONEntPtr pRADEONEnt = RADEONEntPriv(crtc->scrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + struct drmmode_fb *fb = event_data; - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, - drmmode_crtc->flip_pending); + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, fb); radeon_scanout_flip_abort(crtc, event_data); - -#ifdef HAVE_PRESENT_H - if (drmmode_crtc->present_vblank_event_id) { - present_event_notify(drmmode_crtc->present_vblank_event_id, - drmmode_crtc->present_vblank_usec, - drmmode_crtc->present_vblank_msc); - drmmode_crtc->present_vblank_event_id = 0; - } -#endif } @@ -548,8 +559,8 @@ dirty_region(PixmapDirtyUpdatePtr dirty) if (dirty->rotation != RR_Rotate_0) { dstregion = transform_region(damageregion, &dirty->f_inverse, - dirty->slave_dst->drawable.width, - dirty->slave_dst->drawable.height); + dirty->secondary_dst->drawable.width, + dirty->secondary_dst->drawable.height); } else #endif { @@ -557,7 +568,7 @@ dirty_region(PixmapDirtyUpdatePtr dirty) dstregion = RegionDuplicate(damageregion); RegionTranslate(dstregion, -dirty->x, -dirty->y); - PixmapRegionInit(&pixregion, dirty->slave_dst); + PixmapRegionInit(&pixregion, dirty->secondary_dst); RegionIntersect(dstregion, dstregion, &pixregion); RegionUninit(&pixregion); } @@ -568,13 +579,14 @@ dirty_region(PixmapDirtyUpdatePtr dirty) static void redisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region) { - ScrnInfoPtr pScrn = xf86ScreenToScrn(dirty->slave_dst->drawable.pScreen); + ScrnInfoPtr src_scrn = + xf86ScreenToScrn(radeon_dirty_src_drawable(dirty)->pScreen); if (RegionNil(region)) goto out; - if (dirty->slave_dst->master_pixmap) - DamageRegionAppend(&dirty->slave_dst->drawable, region); + if (dirty->secondary_dst->primary_pixmap) + DamageRegionAppend(&dirty->secondary_dst->drawable, region); #ifdef HAS_DIRTYTRACKING_ROTATION PixmapSyncDirtyHelper(dirty); @@ -582,9 +594,9 @@ redisplay_dirty(PixmapDirtyUpdatePtr dirty, RegionPtr region) PixmapSyncDirtyHelper(dirty, region); #endif - radeon_cs_flush_indirect(pScrn); - if (dirty->slave_dst->master_pixmap) - DamageRegionProcessPending(&dirty->slave_dst->drawable); + radeon_cs_flush_indirect(src_scrn); + if (dirty->secondary_dst->primary_pixmap) + DamageRegionProcessPending(&dirty->secondary_dst->drawable); out: DamageEmpty(dirty->damage); @@ -595,18 +607,18 @@ radeon_prime_scanout_update_abort(xf86CrtcPtr crtc, void *event_data) { drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; - drmmode_crtc->scanout_update_pending = FALSE; + drmmode_crtc->scanout_update_pending = 0; } void radeon_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) { - ScreenPtr master_screen = radeon_dirty_master(dirty); + ScreenPtr primary_screen = radeon_dirty_primary(dirty); PixmapDirtyUpdatePtr ent; RegionPtr region; - xorg_list_for_each_entry(ent, &master_screen->pixmap_dirty_list, ent) { - if (!radeon_dirty_src_equals(dirty, ent->slave_dst)) + xorg_list_for_each_entry(ent, &primary_screen->pixmap_dirty_list, ent) { + if (!radeon_dirty_src_equals(dirty, ent->secondary_dst)) continue; region = dirty_region(ent); @@ -619,45 +631,45 @@ radeon_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) #if HAS_SYNC_SHARED_PIXMAP static Bool -master_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) +primary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) { - ScreenPtr master_screen = radeon_dirty_master(dirty); + ScreenPtr primary_screen = radeon_dirty_primary(dirty); - return master_screen->SyncSharedPixmap != NULL; + return !!primary_screen->SyncSharedPixmap; } static Bool -slave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) +secondary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) { - ScreenPtr slave_screen = dirty->slave_dst->drawable.pScreen; + ScreenPtr secondary_screen = dirty->secondary_dst->drawable.pScreen; - return slave_screen->SyncSharedPixmap != NULL; + return !!secondary_screen->SyncSharedPixmap; } static void call_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) { - ScreenPtr master_screen = radeon_dirty_master(dirty); + ScreenPtr primary_screen = radeon_dirty_primary(dirty); - master_screen->SyncSharedPixmap(dirty); + primary_screen->SyncSharedPixmap(dirty); } #else /* !HAS_SYNC_SHARED_PIXMAP */ static Bool -master_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) +primary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) { - ScrnInfoPtr master_scrn = xf86ScreenToScrn(radeon_dirty_master(dirty)); + ScrnInfoPtr primary_scrn = xf86ScreenToScrn(radeon_dirty_primary(dirty)); - return master_scrn->driverName == scrn->driverName; + return primary_scrn->driverName == scrn->driverName; } static Bool -slave_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) +secondary_has_sync_shared_pixmap(ScrnInfoPtr scrn, PixmapDirtyUpdatePtr dirty) { - ScrnInfoPtr slave_scrn = xf86ScreenToScrn(dirty->slave_dst->drawable.pScreen); + ScrnInfoPtr secondary_scrn = xf86ScreenToScrn(dirty->secondary_dst->drawable.pScreen); - return slave_scrn->driverName == scrn->driverName; + return secondary_scrn->driverName == scrn->driverName; } static void @@ -672,12 +684,12 @@ call_sync_shared_pixmap(PixmapDirtyUpdatePtr dirty) static xf86CrtcPtr radeon_prime_dirty_to_crtc(PixmapDirtyUpdatePtr dirty) { - ScreenPtr screen = dirty->slave_dst->drawable.pScreen; + ScreenPtr screen = dirty->secondary_dst->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); int c; - /* Find the CRTC which is scanning out from this slave pixmap */ + /* Find the CRTC which is scanning out from this secondary pixmap */ for (c = 0; c < xf86_config->num_crtc; c++) { xf86CrtcPtr xf86_crtc = xf86_config->crtc[c]; drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; @@ -702,7 +714,7 @@ radeon_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id) if (radeon_dirty_src_equals(dirty, drmmode_crtc->prime_scanout_pixmap)) { RegionPtr region; - if (master_has_sync_shared_pixmap(scrn, dirty)) + if (primary_has_sync_shared_pixmap(scrn, dirty)) call_sync_shared_pixmap(dirty); region = dirty_region(dirty); @@ -715,7 +727,7 @@ radeon_prime_scanout_do_update(xf86CrtcPtr crtc, unsigned scanout_id) radeon_cs_flush_indirect(scrn); RegionCopy(&drmmode_crtc->scanout_last_region, region); RegionTranslate(region, -crtc->x, -crtc->y); - dirty->slave_dst = drmmode_crtc->scanout[scanout_id].pixmap; + dirty->secondary_dst = drmmode_crtc->scanout[scanout_id].pixmap; } redisplay_dirty(dirty, region); @@ -736,14 +748,15 @@ radeon_prime_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t u drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; radeon_prime_scanout_do_update(crtc, 0); - drmmode_crtc->scanout_update_pending = FALSE; + drmmode_crtc->scanout_update_pending = 0; } static void radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty) { - ScreenPtr screen = dirty->slave_dst->drawable.pScreen; + ScreenPtr screen = dirty->secondary_dst->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); xf86CrtcPtr xf86_crtc = radeon_prime_dirty_to_crtc(dirty); drmmode_crtc_private_ptr drmmode_crtc; uintptr_t drm_queue_seq; @@ -761,81 +774,112 @@ radeon_prime_scanout_update(PixmapDirtyUpdatePtr dirty) RADEON_DRM_QUEUE_CLIENT_DEFAULT, RADEON_DRM_QUEUE_ID_DEFAULT, NULL, radeon_prime_scanout_update_handler, - radeon_prime_scanout_update_abort); + radeon_prime_scanout_update_abort, + FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "radeon_drm_queue_alloc failed for PRIME update\n"); + radeon_prime_scanout_update_handler(xf86_crtc, 0, 0, NULL); return; } + drmmode_crtc->scanout_update_pending = drm_queue_seq; + if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, 1, drm_queue_seq, NULL, NULL)) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "drmmode_wait_vblank failed for PRIME update: %s\n", - strerror(errno)); - radeon_drm_abort_entry(drm_queue_seq); + if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "drmmode_wait_vblank failed for PRIME update: %s\n", + strerror(errno)); + drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED; + } + + drmmode_crtc->drmmode->event_context.vblank_handler(pRADEONEnt->fd, + 0, 0, 0, + (void*)drm_queue_seq); + drmmode_crtc->wait_flip_nesting_level++; + radeon_drm_queue_handle_deferred(xf86_crtc); return; } - drmmode_crtc->scanout_update_pending = TRUE; + if (drmmode_crtc->scanout_status == + (DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) { + /* The page flip and vblank ioctls failed before, but the vblank + * ioctl is working again, so we can try re-enabling TearFree + */ + xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode, + xf86_crtc->rotation, + xf86_crtc->x, xf86_crtc->y); + } + + drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED; } static void radeon_prime_scanout_flip(PixmapDirtyUpdatePtr ent) { - ScreenPtr screen = ent->slave_dst->drawable.pScreen; + ScreenPtr screen = ent->secondary_dst->drawable.pScreen; ScrnInfoPtr scrn = xf86ScreenToScrn(screen); RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); xf86CrtcPtr crtc = radeon_prime_dirty_to_crtc(ent); drmmode_crtc_private_ptr drmmode_crtc; uintptr_t drm_queue_seq; unsigned scanout_id; + struct drmmode_fb *fb; if (!crtc || !crtc->enabled) return; drmmode_crtc = crtc->driver_private; + scanout_id = drmmode_crtc->scanout_id ^ 1; if (drmmode_crtc->scanout_update_pending || - !drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap || + !drmmode_crtc->scanout[scanout_id].pixmap || drmmode_crtc->dpms_mode != DPMSModeOn) return; - scanout_id = drmmode_crtc->scanout_id ^ 1; if (!radeon_prime_scanout_do_update(crtc, scanout_id)) return; + fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); + if (!fb) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Failed to get FB for PRIME flip.\n"); + return; + } + drm_queue_seq = radeon_drm_queue_alloc(crtc, RADEON_DRM_QUEUE_CLIENT_DEFAULT, - RADEON_DRM_QUEUE_ID_DEFAULT, - NULL, + RADEON_DRM_QUEUE_ID_DEFAULT, fb, radeon_scanout_flip_handler, - radeon_scanout_flip_abort); + radeon_scanout_flip_abort, TRUE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM event queue entry failed for PRIME flip.\n"); return; } - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, - radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); - if (!drmmode_crtc->flip_pending) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "Failed to get FB for PRIME flip.\n"); + if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc, + fb->handle, 0, drm_queue_seq, 1) + != 0) { + if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "flip queue failed in %s: %s, TearFree inactive\n", + __func__, strerror(errno)); + drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED; + } + radeon_drm_abort_entry(drm_queue_seq); return; } - if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc, - drmmode_crtc->flip_pending->handle, - 0, drm_queue_seq, 0) != 0) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n", - __func__, strerror(errno)); - radeon_drm_abort_entry(drm_queue_seq); - return; + if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n"); + drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED; } drmmode_crtc->scanout_id = scanout_id; - drmmode_crtc->scanout_update_pending = TRUE; + drmmode_crtc->scanout_update_pending = drm_queue_seq; + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, fb); } static void @@ -849,11 +893,11 @@ radeon_dirty_update(ScrnInfoPtr scrn) if (screen->isGPU) { PixmapDirtyUpdatePtr region_ent = ent; - if (master_has_sync_shared_pixmap(scrn, ent)) { - ScreenPtr master_screen = radeon_dirty_master(ent); + if (primary_has_sync_shared_pixmap(scrn, ent)) { + ScreenPtr primary_screen = radeon_dirty_primary(ent); - xorg_list_for_each_entry(region_ent, &master_screen->pixmap_dirty_list, ent) { - if (radeon_dirty_src_equals(ent, region_ent->slave_dst)) + xorg_list_for_each_entry(region_ent, &primary_screen->pixmap_dirty_list, ent) { + if (radeon_dirty_src_equals(ent, region_ent->secondary_dst)) break; } } @@ -877,7 +921,7 @@ radeon_dirty_update(ScrnInfoPtr scrn) RegionDestroy(region); } else { - if (slave_has_sync_shared_pixmap(scrn, ent)) + if (secondary_has_sync_shared_pixmap(scrn, ent)) continue; region = dirty_region(ent); @@ -890,10 +934,10 @@ radeon_dirty_update(ScrnInfoPtr scrn) Bool radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id, - PixmapPtr src_pix, BoxPtr extents) + PixmapPtr src_pix, BoxRec extents) { drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; - RegionRec region = { .extents = *extents, .data = NULL }; + RegionRec region = { .extents = extents, .data = NULL }; ScrnInfoPtr scrn = xf86_crtc->scrn; ScreenPtr pScreen = scrn->pScreen; RADEONInfoPtr info = RADEONPTR(scrn); @@ -902,11 +946,11 @@ radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id, if (!xf86_crtc->enabled || !drmmode_crtc->scanout[scanout_id].pixmap || - extents->x1 >= extents->x2 || extents->y1 >= extents->y2) + extents.x1 >= extents.x2 || extents.y1 >= extents.y2) return FALSE; pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable; - if (!radeon_scanout_extents_intersect(xf86_crtc, extents)) + if (!radeon_scanout_extents_intersect(xf86_crtc, &extents)) return FALSE; if (drmmode_crtc->tear_free) { @@ -952,9 +996,9 @@ radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id, pScreen->SourceValidate = NULL; CompositePicture(PictOpSrc, src, NULL, dst, - extents->x1, extents->y1, 0, 0, extents->x1, - extents->y1, extents->x2 - extents->x1, - extents->y2 - extents->y1); + extents.x1, extents.y1, 0, 0, extents.x1, + extents.y1, extents.x2 - extents.x1, + extents.y2 - extents.y1); pScreen->SourceValidate = SourceValidate; free_dst: @@ -968,14 +1012,12 @@ radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id, ValidateGC(pDraw, gc); (*gc->ops->CopyArea)(&src_pix->drawable, pDraw, gc, - xf86_crtc->x + extents->x1, xf86_crtc->y + extents->y1, - extents->x2 - extents->x1, extents->y2 - extents->y1, - extents->x1, extents->y1); + xf86_crtc->x + extents.x1, xf86_crtc->y + extents.y1, + extents.x2 - extents.x1, extents.y2 - extents.y1, + extents.x1, extents.y1); FreeScratchGC(gc); } - radeon_cs_flush_indirect(scrn); - info->accel_state->force = force; return TRUE; @@ -986,7 +1028,7 @@ radeon_scanout_update_abort(xf86CrtcPtr crtc, void *event_data) { drmmode_crtc_private_ptr drmmode_crtc = event_data; - drmmode_crtc->scanout_update_pending = FALSE; + drmmode_crtc->scanout_update_pending = 0; } static void @@ -1002,8 +1044,10 @@ radeon_scanout_update_handler(xf86CrtcPtr crtc, uint32_t frame, uint64_t usec, drmmode_crtc->dpms_mode == DPMSModeOn) { if (radeon_scanout_do_update(crtc, drmmode_crtc->scanout_id, screen->GetWindowPixmap(screen->root), - ®ion->extents)) + region->extents)) { + radeon_cs_flush_indirect(crtc->scrn); RegionEmpty(region); + } } radeon_scanout_update_abort(crtc, event_data); @@ -1013,8 +1057,9 @@ static void radeon_scanout_update(xf86CrtcPtr xf86_crtc) { drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; + ScrnInfoPtr scrn = xf86_crtc->scrn; + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); uintptr_t drm_queue_seq; - ScrnInfoPtr scrn; DamagePtr pDamage; RegionPtr pRegion; BoxRec extents; @@ -1039,29 +1084,50 @@ radeon_scanout_update(xf86CrtcPtr xf86_crtc) return; } - scrn = xf86_crtc->scrn; drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc, RADEON_DRM_QUEUE_CLIENT_DEFAULT, RADEON_DRM_QUEUE_ID_DEFAULT, drmmode_crtc, radeon_scanout_update_handler, - radeon_scanout_update_abort); + radeon_scanout_update_abort, + FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "radeon_drm_queue_alloc failed for scanout update\n"); + radeon_scanout_update_handler(xf86_crtc, 0, 0, drmmode_crtc); return; } + drmmode_crtc->scanout_update_pending = drm_queue_seq; + if (!drmmode_wait_vblank(xf86_crtc, DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, 1, drm_queue_seq, NULL, NULL)) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "drmmode_wait_vblank failed for scanout update: %s\n", - strerror(errno)); - radeon_drm_abort_entry(drm_queue_seq); + if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_VBLANK_FAILED)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "drmmode_wait_vblank failed for scanout update: %s\n", + strerror(errno)); + drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_VBLANK_FAILED; + } + + drmmode_crtc->drmmode->event_context.vblank_handler(pRADEONEnt->fd, + 0, 0, 0, + (void*)drm_queue_seq); + drmmode_crtc->wait_flip_nesting_level++; + radeon_drm_queue_handle_deferred(xf86_crtc); return; } - drmmode_crtc->scanout_update_pending = TRUE; + if (drmmode_crtc->scanout_status == + (DRMMODE_SCANOUT_FLIP_FAILED | DRMMODE_SCANOUT_VBLANK_FAILED)) { + /* The page flip and vblank ioctls failed before, but the vblank + * ioctl is working again, so we can try re-enabling TearFree + */ + xf86_crtc->funcs->set_mode_major(xf86_crtc, &xf86_crtc->mode, + xf86_crtc->rotation, + xf86_crtc->x, xf86_crtc->y); + } + + drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_VBLANK_FAILED; } static void @@ -1074,6 +1140,7 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info, RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); uintptr_t drm_queue_seq; unsigned scanout_id; + struct drmmode_fb *fb; if (drmmode_crtc->scanout_update_pending || drmmode_crtc->flip_pending || @@ -1083,37 +1150,40 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info, scanout_id = drmmode_crtc->scanout_id ^ 1; if (!radeon_scanout_do_update(xf86_crtc, scanout_id, pScreen->GetWindowPixmap(pScreen->root), - ®ion->extents)) + region->extents)) return; + + radeon_cs_flush_indirect(scrn); RegionEmpty(region); + fb = radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap); + if (!fb) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Failed to get FB for scanout flip.\n"); + return; + } + drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc, RADEON_DRM_QUEUE_CLIENT_DEFAULT, - RADEON_DRM_QUEUE_ID_DEFAULT, - NULL, + RADEON_DRM_QUEUE_ID_DEFAULT, fb, radeon_scanout_flip_handler, - radeon_scanout_flip_abort); + radeon_scanout_flip_abort, TRUE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Allocating DRM event queue entry failed.\n"); return; } - drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, - radeon_pixmap_get_fb(drmmode_crtc->scanout[scanout_id].pixmap)); - if (!drmmode_crtc->flip_pending) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "Failed to get FB for scanout flip.\n"); - radeon_drm_abort_entry(drm_queue_seq); - return; - } - if (drmmode_page_flip_target_relative(pRADEONEnt, drmmode_crtc, - drmmode_crtc->flip_pending->handle, - 0, drm_queue_seq, 0) != 0) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s, " - "TearFree inactive until next modeset\n", - __func__, strerror(errno)); + fb->handle, 0, drm_queue_seq, 1) + != 0) { + if (!(drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED)) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "flip queue failed in %s: %s, TearFree inactive\n", + __func__, strerror(errno)); + drmmode_crtc->scanout_status |= DRMMODE_SCANOUT_FLIP_FAILED; + } + radeon_drm_abort_entry(drm_queue_seq); RegionCopy(DamageRegion(drmmode_crtc->scanout_damage), &drmmode_crtc->scanout_last_region); @@ -1125,8 +1195,14 @@ radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info, return; } + if (drmmode_crtc->scanout_status & DRMMODE_SCANOUT_FLIP_FAILED) { + xf86DrvMsg(scrn->scrnIndex, X_INFO, "TearFree active again\n"); + drmmode_crtc->scanout_status &= ~DRMMODE_SCANOUT_FLIP_FAILED; + } + drmmode_crtc->scanout_id = scanout_id; - drmmode_crtc->scanout_update_pending = TRUE; + drmmode_crtc->scanout_update_pending = drm_queue_seq; + drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->flip_pending, fb); } static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) @@ -1140,7 +1216,7 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) (*pScreen->BlockHandler) (BLOCKHANDLER_ARGS); pScreen->BlockHandler = RADEONBlockHandler_KMS; - if (!xf86ScreenToScrn(radeon_master_screen(pScreen))->vtSema) + if (!xf86ScreenToScrn(radeon_primary_screen(pScreen))->vtSema) return; if (!pScreen->isGPU) @@ -1149,6 +1225,9 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL) xf86CrtcPtr crtc = xf86_config->crtc[c]; drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + if (drmmode_crtc->rotate.pixmap) + continue; + if (drmmode_crtc->tear_free) radeon_scanout_flip(pScreen, info, crtc); else if (drmmode_crtc->scanout[drmmode_crtc->scanout_id].pixmap) @@ -1245,6 +1324,7 @@ static Bool RADEONPreInitVisual(ScrnInfoPtr pScrn) case 15: case 16: case 24: + case 30: break; default: @@ -1667,8 +1747,7 @@ void RADEONWindowExposures_oneshot(WindowPtr pWin, RegionPtr pRegion pScreen->WindowExposures(pWin, pRegion); #endif - radeon_cs_flush_indirect(pScrn); - radeon_bo_wait(info->front_bo); + radeon_finish(pScrn, info->front_buffer); drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE); } @@ -1677,7 +1756,6 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) RADEONInfoPtr info; RADEONEntPtr pRADEONEnt; MessageType from; - DevUnion* pPriv; Gamma zeros = { 0.0, 0.0, 0.0 }; uint32_t tiling = 0; int cpp; @@ -1688,79 +1766,84 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "RADEONPreInit_KMS\n"); if (pScrn->numEntities != 1) return FALSE; + + pRADEONEnt = xf86GetEntityPrivate(pScrn->entityList[0], + getRADEONEntityIndex())->ptr; + if (pRADEONEnt->num_scrns == ARRAY_SIZE(pRADEONEnt->scrn)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Only up to %u Zaphod instances supported\n", + (unsigned)ARRAY_SIZE(pRADEONEnt->scrn)); + return FALSE; + } + if (!RADEONGetRec(pScrn)) return FALSE; info = RADEONPTR(pScrn); - info->IsSecondary = FALSE; + + info->instance_id = pRADEONEnt->num_scrns++; + pRADEONEnt->scrn[info->instance_id] = pScrn; + info->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]); if (info->pEnt->location.type != BUS_PCI #ifdef XSERVER_PLATFORM_BUS && info->pEnt->location.type != BUS_PLATFORM #endif ) - goto fail; - - pPriv = xf86GetEntityPrivate(pScrn->entityList[0], - getRADEONEntityIndex()); - pRADEONEnt = pPriv->ptr; + return FALSE; - if(xf86IsEntityShared(pScrn->entityList[0])) - { - if(xf86IsPrimInitDone(pScrn->entityList[0])) - { - info->IsSecondary = TRUE; - } - else - { - xf86SetPrimInitDone(pScrn->entityList[0]); - } + if (xf86IsEntityShared(pScrn->entityList[0]) && + info->instance_id == 0) { + xf86SetPrimInitDone(pScrn->entityList[0]); } - if (info->IsSecondary) - pRADEONEnt->secondary_scrn = pScrn; - else - pRADEONEnt->primary_scrn = pScrn; - info->PciInfo = xf86GetPciInfoForEntity(info->pEnt->index); pScrn->monitor = pScrn->confScreen->monitor; if (!RADEONPreInitVisual(pScrn)) - goto fail; + return FALSE; xf86CollectOptions(pScrn, NULL); if (!(info->Options = malloc(sizeof(RADEONOptions_KMS)))) - goto fail; + return FALSE; memcpy(info->Options, RADEONOptions_KMS, sizeof(RADEONOptions_KMS)); xf86ProcessOptions(pScrn->scrnIndex, pScrn->options, info->Options); if (!RADEONPreInitWeight(pScrn)) - goto fail; + return FALSE; if (!RADEONPreInitChipType_KMS(pScrn)) - goto fail; + return FALSE; if (radeon_open_drm_master(pScrn) == FALSE) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n"); - goto fail; + return FALSE; } info->dri2.available = FALSE; info->dri2.enabled = FALSE; info->dri2.pKernelDRMVersion = drmGetVersion(pRADEONEnt->fd); - if (info->dri2.pKernelDRMVersion == NULL) { + if (!info->dri2.pKernelDRMVersion) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "RADEONDRIGetVersion failed to get the DRM version\n"); - goto fail; + return FALSE; } /* Get ScreenInit function */ if (!xf86LoadSubModule(pScrn, "fb")) return FALSE; - if (!RADEONPreInitAccel_KMS(pScrn)) goto fail; + if (!RADEONPreInitAccel_KMS(pScrn)) + return FALSE; - radeon_drm_queue_init(); + /* Depth 30 only supported since Linux 3.16 / kms driver minor version 39 */ + if (pScrn->depth == 30 && info->dri2.pKernelDRMVersion->version_minor < 39) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, + "Depth 30 is not supported. Kernel too old. Needs Linux 3.16+\n"); + return FALSE; + } + + radeon_drm_queue_init(pScrn); info->allowColorTiling2D = FALSE; @@ -1834,19 +1917,15 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) if (!pScrn->is_gpu) { if (info->dri2.pKernelDRMVersion->version_minor >= 8) { - Bool sw_cursor = xf86ReturnOptValBool(info->Options, - OPTION_SW_CURSOR, FALSE); - info->allowPageFlip = xf86ReturnOptValBool(info->Options, OPTION_PAGE_FLIP, TRUE); - if (sw_cursor || info->shadow_primary) { + if (info->shadow_primary) { xf86DrvMsg(pScrn->scrnIndex, info->allowPageFlip ? X_WARNING : X_DEFAULT, "KMS Pageflipping: disabled%s\n", info->allowPageFlip ? - (sw_cursor ? " because of SWcursor" : - " because of ShadowPrimary") : ""); + " because of ShadowPrimary" : ""); info->allowPageFlip = FALSE; } else { xf86DrvMsg(pScrn->scrnIndex, X_INFO, @@ -1870,7 +1949,7 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) == FALSE) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n"); - goto fail; + return FALSE; } RADEONSetupCapabilities(pScrn); @@ -1895,7 +1974,7 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) xf86OutputPtr output = xf86_config->output[i]; /* XXX: double check crtc mode */ - if ((output->probed_modes != NULL) && (output->crtc == NULL)) + if (output->probed_modes && !output->crtc) output->crtc = xf86_config->crtc[0]; } } @@ -1958,20 +2037,16 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags) if (!xf86LoadSubModule(pScrn, "ramdac")) return FALSE; } - if (pScrn->modes == NULL + if (!pScrn->modes #ifdef XSERVER_PLATFORM_BUS && !pScrn->is_gpu #endif ) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No modes.\n"); - goto fail; - } + return FALSE; + } return TRUE; - fail: - RADEONFreeRec(pScrn); - return FALSE; - } static Bool RADEONCursorInit_KMS(ScreenPtr pScreen) @@ -1979,12 +2054,44 @@ static Bool RADEONCursorInit_KMS(ScreenPtr pScreen) ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen); RADEONInfoPtr info = RADEONPTR(pScrn); - return xf86_cursors_init (pScreen, info->cursor_w, info->cursor_h, - (HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | - HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | - HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | - HARDWARE_CURSOR_UPDATE_UNHIDDEN | - HARDWARE_CURSOR_ARGB)); + xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, + "Initializing Cursor\n"); + + /* Set Silken Mouse */ + xf86SetSilkenMouse(pScreen); + + /* Cursor setup */ + miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); + + if (info->allowPageFlip) { + miPointerScreenPtr PointPriv = + dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); + + if (!dixRegisterScreenPrivateKey(&radeon_device_private_key, pScreen, + PRIVATE_DEVICE, + sizeof(struct radeon_device_priv))) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "dixRegisterScreenPrivateKey failed\n"); + return FALSE; + } + + info->SpriteFuncs = PointPriv->spriteFuncs; + PointPriv->spriteFuncs = &drmmode_sprite_funcs; + } + + if (xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) + return TRUE; + + if (!xf86_cursors_init(pScreen, info->cursor_w, info->cursor_h, + HARDWARE_CURSOR_TRUECOLOR_AT_8BPP | + HARDWARE_CURSOR_AND_SOURCE_WITH_MASK | + HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_1 | + HARDWARE_CURSOR_UPDATE_UNHIDDEN | + HARDWARE_CURSOR_ARGB)) { + xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "xf86_cursors_init failed\n"); + return FALSE; + } + + return TRUE; } void @@ -2041,7 +2148,7 @@ static Bool RADEONSaveScreen_KMS(ScreenPtr pScreen, int mode) unblank = xf86IsUnblank(mode); if (unblank) SetTimeSinceLastInputEvent(); - if ((pScrn != NULL) && pScrn->vtSema) { + if (pScrn && pScrn->vtSema) { if (unblank) RADEONUnblank(pScrn); else @@ -2127,6 +2234,15 @@ static Bool RADEONCloseScreen_KMS(ScreenPtr pScreen) pScrn->vtSema = FALSE; xf86ClearPrimInitDone(info->pEnt->index); + + if (info->allowPageFlip) { + miPointerScreenPtr PointPriv = + dixLookupPrivate(&pScreen->devPrivates, miPointerScreenKey); + + if (PointPriv->spriteFuncs == &drmmode_sprite_funcs) + PointPriv->spriteFuncs = info->SpriteFuncs; + } + pScreen->BlockHandler = info->BlockHandler; pScreen->CloseScreen = info->CloseScreen; return pScreen->CloseScreen(pScreen); @@ -2135,14 +2251,9 @@ static Bool RADEONCloseScreen_KMS(ScreenPtr pScreen) void RADEONFreeScreen_KMS(ScrnInfoPtr pScrn) { - RADEONInfoPtr info = RADEONPTR(pScrn); - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, "RADEONFreeScreen\n"); - /* when server quits at PreInit, we don't need do this anymore*/ - if (!info) return; - RADEONFreeRec(pScrn); } @@ -2174,7 +2285,16 @@ Bool RADEONScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv) if (info->r600_shadow_fb == FALSE) info->directRenderingEnabled = radeon_dri2_screen_init(pScreen); - info->surf_man = radeon_surface_manager_new(pRADEONEnt->fd); + if (info->ChipFamily >= CHIP_FAMILY_R600) { + info->surf_man = radeon_surface_manager_new(pRADEONEnt->fd); + + if (!info->surf_man) { + xf86DrvMsg(pScreen->myNum, X_ERROR, + "Failed to initialize surface manager\n"); + return FALSE; + } + } + if (!info->bufmgr) info->bufmgr = radeon_bo_manager_gem_ctor(pRADEONEnt->fd); if (!info->bufmgr) { @@ -2207,13 +2327,17 @@ 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_bo->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, pScrn->displayWidth * pScrn->virtualY * ((pScrn->bitsPerPixel + 7) >> 3)); - if (info->fb_shadow == NULL) { + if (!info->fb_shadow) { xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Failed to allocate shadow framebuffer\n"); return FALSE; @@ -2327,19 +2451,8 @@ Bool RADEONScreenInit_KMS(ScreenPtr pScreen, int argc, char **argv) "Initializing DPMS\n"); xf86DPMSInit(pScreen, xf86DPMSSet, 0); - xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG, - "Initializing Cursor\n"); - - /* Set Silken Mouse */ - xf86SetSilkenMouse(pScreen); - - /* Cursor setup */ - miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); - - if (!xf86ReturnOptValBool(info->Options, OPTION_SW_CURSOR, FALSE)) { - if (RADEONCursorInit_KMS(pScreen)) { - } - } + if (!RADEONCursorInit_KMS(pScreen)) + return FALSE; /* DGA setup */ #ifdef XFreeXDGA @@ -2427,15 +2540,17 @@ Bool RADEONEnterVT_KMS(ScrnInfoPtr pScrn) if (info->r600_shadow_fb) { int base_align = drmmode_get_base_align(pScrn, info->pixel_bytes, 0); struct radeon_bo *front_bo = radeon_bo_open(info->bufmgr, 0, - info->front_bo->size, + pScrn->displayWidth * + info->pixel_bytes * + pScrn->virtualY, base_align, RADEON_GEM_DOMAIN_VRAM, 0); if (front_bo) { if (radeon_bo_map(front_bo, 1) == 0) { memset(front_bo->ptr, 0, front_bo->size); - radeon_bo_unref(info->front_bo); - info->front_bo = front_bo; + radeon_bo_unref(info->front_buffer->bo.radeon); + info->front_buffer->bo.radeon = front_bo; } else { radeon_bo_unref(front_bo); front_bo = NULL; @@ -2469,7 +2584,7 @@ CARD32 cleanup_black_fb(OsTimerPtr timer, CARD32 now, pointer data) xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn); int c; - if (xf86ScreenToScrn(radeon_master_screen(screen))->vtSema) + if (xf86ScreenToScrn(radeon_primary_screen(screen))->vtSema) return 0; /* Unreference the all-black FB created by RADEONLeaveVT_KMS. After @@ -2482,20 +2597,30 @@ CARD32 cleanup_black_fb(OsTimerPtr timer, CARD32 now, pointer data) drmmode_fb_reference(pRADEONEnt->fd, &drmmode_crtc->fb, NULL); } + TimerFree(timer); return 0; } static void -pixmap_unref_fb(void *value, XID id, void *cdata) +pixmap_unref_fb(PixmapPtr pixmap) { - PixmapPtr pixmap = value; - RADEONEntPtr pRADEONEnt = cdata; + ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen); struct drmmode_fb **fb_ptr = radeon_pixmap_get_fb_ptr(pixmap); + RADEONEntPtr pRADEONEnt = RADEONEntPriv(scrn); if (fb_ptr) drmmode_fb_reference(pRADEONEnt->fd, fb_ptr, NULL); } +static void +client_pixmap_unref_fb(void *value, XID id, void *pScreen) +{ + PixmapPtr pixmap = value; + + if (pixmap->drawable.pScreen == pScreen) + pixmap_unref_fb(pixmap); +} + void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); @@ -2513,6 +2638,12 @@ void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn) unsigned w = 0, h = 0; int i; + /* If we're called from CloseScreen, trying to clear the black + * scanout BO will likely crash and burn + */ + if (!pScreen->GCperDepth[0]) + goto hide_cursors; + /* Compute maximum scanout dimensions of active CRTCs */ for (i = 0; i < xf86_config->num_crtc; i++) { crtc = xf86_config->crtc[i]; @@ -2532,8 +2663,7 @@ void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn) radeon_pixmap_get_fb(black_scanout.pixmap); radeon_pixmap_clear(black_scanout.pixmap); - radeon_cs_flush_indirect(pScrn); - radeon_bo_wait(black_scanout.bo); + radeon_finish(pScrn, black_scanout.bo); for (i = 0; i < xf86_config->num_crtc; i++) { crtc = xf86_config->crtc[i]; @@ -2552,13 +2682,11 @@ void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn) if (pScrn->is_gpu) { if (drmmode_crtc->scanout[0].pixmap) - pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap, - None, pRADEONEnt); + pixmap_unref_fb(drmmode_crtc->scanout[0].pixmap); if (drmmode_crtc->scanout[1].pixmap) - pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap, - None, pRADEONEnt); + pixmap_unref_fb(drmmode_crtc->scanout[1].pixmap); } else { - drmmode_crtc_scanout_free(drmmode_crtc); + drmmode_crtc_scanout_free(crtc); } } } @@ -2576,17 +2704,20 @@ void RADEONLeaveVT_KMS(ScrnInfoPtr pScrn) (!clients[i] || clients[i]->clientState != ClientStateRunning)) continue; - FindClientResourcesByType(clients[i], RT_PIXMAP, pixmap_unref_fb, - pRADEONEnt); + FindClientResourcesByType(clients[i], RT_PIXMAP, + client_pixmap_unref_fb, pScreen); } - pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen), None, pRADEONEnt); + pixmap_unref_fb(pScreen->GetScreenPixmap(pScreen)); } else { - memset(info->front_bo->ptr, 0, info->front_bo->size); + memset(info->front_buffer->bo.radeon->ptr, 0, + pScrn->displayWidth * info->pixel_bytes * pScrn->virtualY); } - TimerSet(NULL, 0, 1000, cleanup_black_fb, pScreen); + if (pScreen->GCperDepth[0]) + TimerSet(NULL, 0, 1000, cleanup_black_fb, pScreen); + hide_cursors: xf86_hide_cursors (pScrn); radeon_drop_drm_master(pScrn); @@ -2620,159 +2751,98 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen) RADEONInfoPtr info = RADEONPTR(pScrn); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int cpp = info->pixel_bytes; - uint32_t screen_size; - int pitch, base_align; + int pitch; uint32_t tiling_flags = 0; - struct radeon_surface surface; - if (info->accel_state->exa != NULL) { + if (info->accel_state->exa) { xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n"); return FALSE; } if (!info->use_glamor && info->r600_shadow_fb == FALSE) { info->accel_state->exa = exaDriverAlloc(); - if (info->accel_state->exa == NULL) { + if (!info->accel_state->exa) { xf86DrvMsg(pScreen->myNum, X_ERROR, "exaDriverAlloc failed\n"); return FALSE; } } - if (info->allowColorTiling && !info->shadow_primary) { - if (info->ChipFamily >= CHIP_FAMILY_R600) { - if (info->allowColorTiling2D) { - tiling_flags |= RADEON_TILING_MACRO; - } else { - tiling_flags |= RADEON_TILING_MICRO; - } - } else - tiling_flags |= RADEON_TILING_MACRO; - } - pitch = RADEON_ALIGN(pScrn->virtualX, drmmode_get_pitch_align(pScrn, cpp, tiling_flags)) * cpp; - screen_size = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags)) * pitch; - base_align = drmmode_get_base_align(pScrn, cpp, tiling_flags); - if (info->ChipFamily >= CHIP_FAMILY_R600) { - if(!info->surf_man) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "failed to initialise surface manager\n"); - return FALSE; - } - memset(&surface, 0, sizeof(struct radeon_surface)); - surface.npix_x = pScrn->virtualX; - surface.npix_y = pScrn->virtualY; - surface.npix_z = 1; - surface.blk_w = 1; - surface.blk_h = 1; - surface.blk_d = 1; - surface.array_size = 1; - surface.last_level = 0; - surface.bpe = cpp; - surface.nsamples = 1; - surface.flags = RADEON_SURF_SCANOUT; - /* we are requiring a recent enough libdrm version */ - surface.flags |= RADEON_SURF_HAS_TILE_MODE_INDEX; - surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE); - surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED, MODE); - if (tiling_flags & RADEON_TILING_MICRO) { - surface.flags = RADEON_SURF_CLR(surface.flags, MODE); - surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE); - } - if (tiling_flags & RADEON_TILING_MACRO) { - surface.flags = RADEON_SURF_CLR(surface.flags, MODE); - surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE); - } - if (radeon_surface_best(info->surf_man, &surface)) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "radeon_surface_best failed\n"); - return FALSE; - } - if (radeon_surface_init(info->surf_man, &surface)) { - xf86DrvMsg(pScreen->myNum, X_ERROR, - "radeon_surface_init failed\n"); - return FALSE; - } - pitch = surface.level[0].pitch_bytes; - screen_size = surface.bo_size; - base_align = surface.bo_alignment; - tiling_flags = 0; - switch (surface.level[0].mode) { - case RADEON_SURF_MODE_2D: - tiling_flags |= RADEON_TILING_MACRO; - tiling_flags |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT; - tiling_flags |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT; - tiling_flags |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT; - if (surface.tile_split) - tiling_flags |= eg_tile_split(surface.tile_split) - << RADEON_TILING_EG_TILE_SPLIT_SHIFT; - break; - case RADEON_SURF_MODE_1D: - tiling_flags |= RADEON_TILING_MICRO; - break; - default: - break; - } - info->front_surface = surface; - } { int cursor_size; - int c; + int c, i; cursor_size = info->cursor_w * info->cursor_h * 4; cursor_size = RADEON_ALIGN(cursor_size, RADEON_GPU_PAGE_SIZE); for (c = 0; c < xf86_config->num_crtc; c++) { - /* cursor objects */ - if (info->cursor_bo[c] == NULL) { - info->cursor_bo[c] = radeon_bo_open(info->bufmgr, 0, - cursor_size, 0, - RADEON_GEM_DOMAIN_VRAM, 0); - if (!info->cursor_bo[c]) { - ErrorF("Failed to allocate cursor buffer memory\n"); - return FALSE; - } - - if (radeon_bo_map(info->cursor_bo[c], 1)) { - ErrorF("Failed to map cursor buffer memory\n"); - } - - drmmode_set_cursor(pScrn, &info->drmmode, c, info->cursor_bo[c]); - } - } + drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private; + + for (i = 0; i < 2; i++) { + if (!drmmode_crtc->cursor_bo[i]) { + drmmode_crtc->cursor_bo[i] = + radeon_bo_open(info->bufmgr, 0, cursor_size, 0, + RADEON_GEM_DOMAIN_VRAM, 0); + + if (!(drmmode_crtc->cursor_bo[i])) { + ErrorF("Failed to allocate cursor buffer memory\n"); + return FALSE; + } + + if (radeon_bo_map(drmmode_crtc->cursor_bo[i], 1)) + ErrorF("Failed to map cursor buffer memory\n"); + } + } + } } - screen_size = RADEON_ALIGN(screen_size, RADEON_GPU_PAGE_SIZE); + if (!info->front_buffer) { + int usage = CREATE_PIXMAP_USAGE_BACKING_PIXMAP; + + if (info->allowColorTiling && !info->shadow_primary) { + if (info->ChipFamily < CHIP_FAMILY_R600 || info->allowColorTiling2D) + usage |= RADEON_CREATE_PIXMAP_TILING_MACRO; + else + usage |= RADEON_CREATE_PIXMAP_TILING_MICRO; + } + + info->front_buffer = radeon_alloc_pixmap_bo(pScrn, pScrn->virtualX, + pScrn->virtualY, + pScrn->depth, + usage, + pScrn->bitsPerPixel, + &pitch, + &info->front_surface, + &tiling_flags); - if (info->front_bo == NULL) { - info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, - base_align, - info->shadow_primary ? - RADEON_GEM_DOMAIN_GTT : - RADEON_GEM_DOMAIN_VRAM, - tiling_flags ? RADEON_GEM_NO_CPU_ACCESS : 0); if (info->r600_shadow_fb == TRUE) { - if (radeon_bo_map(info->front_bo, 1)) { + if (radeon_bo_map(info->front_buffer->bo.radeon, 1)) { 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_bo, tiling_flags, pitch); - } + if (tiling_flags) + radeon_bo_set_tiling(info->front_buffer->bo.radeon, tiling_flags, pitch); + } - pScrn->displayWidth = pitch / cpp; + pScrn->displayWidth = pitch / cpp; + } - xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n", info->front_bo->size/1024); - radeon_kms_update_vram_limit(pScrn, screen_size); + pitch = pScrn->displayWidth * cpp; + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Front buffer size: %dK\n", + pitch * pScrn->virtualY / 1024); + radeon_kms_update_vram_limit(pScrn, pitch * pScrn->virtualY); return TRUE; } @@ -2784,9 +2854,10 @@ void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, uint32_t new_fb_size) int c; for (c = 0; c < xf86_config->num_crtc; c++) { - if (info->cursor_bo[c] != NULL) { + drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[c]->driver_private; + + if (drmmode_crtc->cursor_bo[0]) new_fb_size += (64 * 4 * 64); - } } remain_size_bytes = info->vram_size - new_fb_size; diff --git a/src/radeon_present.c b/src/radeon_present.c index 176853d9..d010aa19 100644 --- a/src/radeon_present.c +++ b/src/radeon_present.c @@ -52,7 +52,6 @@ static present_screen_info_rec radeon_present_screen_info; struct radeon_present_vblank_event { uint64_t event_id; - Bool vblank_for_flip; Bool unflip; }; @@ -110,7 +109,7 @@ radeon_present_flush_drm_events(ScreenPtr screen) if (r <= 0) return 0; - return drmHandleEvent(pRADEONEnt->fd, &drmmode->event_context) >= 0; + return radeon_drm_handle_event(pRADEONEnt->fd, &drmmode->event_context) >= 0; } /* @@ -120,26 +119,9 @@ static void radeon_present_vblank_handler(xf86CrtcPtr crtc, unsigned int msc, uint64_t usec, void *data) { - drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; struct radeon_present_vblank_event *event = data; - if (event->vblank_for_flip && - drmmode_crtc->tear_free && - drmmode_crtc->scanout_update_pending) { - if (drmmode_crtc->present_vblank_event_id != 0) { - xf86DrvMsg(crtc->scrn->scrnIndex, X_WARNING, - "Need to handle previously deferred vblank event\n"); - present_event_notify(drmmode_crtc->present_vblank_event_id, - drmmode_crtc->present_vblank_usec, - drmmode_crtc->present_vblank_msc); - } - - drmmode_crtc->present_vblank_event_id = event->event_id; - drmmode_crtc->present_vblank_msc = msc; - drmmode_crtc->present_vblank_usec = usec; - } else - present_event_notify(event->event_id, usec, msc); - + present_event_notify(event->event_id, usec, msc); free(event); } @@ -162,7 +144,6 @@ static int radeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) { xf86CrtcPtr xf86_crtc = crtc->devPrivate; - drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; ScreenPtr screen = crtc->pScreen; struct radeon_present_vblank_event *event; uintptr_t drm_queue_seq; @@ -171,14 +152,13 @@ radeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc) if (!event) return BadAlloc; event->event_id = event_id; - event->vblank_for_flip = drmmode_crtc->present_flip_expected; - drmmode_crtc->present_flip_expected = FALSE; drm_queue_seq = radeon_drm_queue_alloc(xf86_crtc, RADEON_DRM_QUEUE_CLIENT_DEFAULT, event_id, event, radeon_present_vblank_handler, - radeon_present_vblank_abort); + radeon_present_vblank_abort, + FALSE); if (drm_queue_seq == RADEON_DRM_QUEUE_ERROR) { free(event); return BadAlloc; @@ -272,33 +252,58 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, Bool sync_flip) { xf86CrtcPtr xf86_crtc = crtc->devPrivate; - drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; ScreenPtr screen = window->drawable.pScreen; ScrnInfoPtr scrn = xf86_crtc->scrn; +#ifdef USE_GLAMOR + struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap); +#endif xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); RADEONInfoPtr info = RADEONPTR(scrn); - PixmapPtr screen_pixmap; + PixmapPtr screen_pixmap = screen->GetScreenPixmap(screen); int num_crtcs_on; int i; - drmmode_crtc->present_flip_expected = FALSE; - if (!scrn->vtSema) return FALSE; if (!info->allowPageFlip) return FALSE; - if (info->hwcursor_disabled) + if (info->sprites_visible > 0) return FALSE; if (info->drmmode.dri2_flipping) return FALSE; +#if XORG_VERSION_CURRENT <= XORG_VERSION_NUMERIC(1, 20, 99, 1, 0) + if (pixmap->devKind != screen_pixmap->devKind) + return FALSE; +#endif + +#ifdef USE_GLAMOR + if (priv && priv->fb_failed) + return FALSE; +#endif + + if (!radeon_pixmap_get_fb(pixmap)) { +#ifdef USE_GLAMOR + if (!priv) + priv = radeon_get_pixmap_private(pixmap); + + if (priv && !priv->fb_failed) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "Cannot get FB for Present flip (may be " + "normal if using PRIME render offloading)\n"); + priv->fb_failed = TRUE; + } +#endif + + return FALSE; + } + /* The kernel driver doesn't handle flipping between BOs with different * tiling parameters correctly yet */ - screen_pixmap = screen->GetScreenPixmap(screen); if (radeon_present_get_pixmap_tiling_flags(info, pixmap) != radeon_present_get_pixmap_tiling_flags(info, screen_pixmap)) return FALSE; @@ -313,7 +318,6 @@ radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap, if (num_crtcs_on == 0) return FALSE; - drmmode_crtc->present_flip_expected = TRUE; return TRUE; } @@ -354,7 +358,6 @@ radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, PixmapPtr pixmap, Bool sync_flip) { xf86CrtcPtr xf86_crtc = crtc->devPrivate; - drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private; ScreenPtr screen = crtc->pScreen; ScrnInfoPtr scrn = xf86_crtc->scrn; RADEONInfoPtr info = RADEONPTR(scrn); @@ -362,11 +365,11 @@ radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, Bool ret = FALSE; if (!radeon_present_check_flip(crtc, screen->root, pixmap, sync_flip)) - goto out; + return ret; event = calloc(1, sizeof(struct radeon_present_vblank_event)); if (!event) - goto out; + return ret; event->event_id = event_id; @@ -383,8 +386,6 @@ radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc, else info->drmmode.present_flipping = TRUE; - out: - drmmode_crtc->present_flip_expected = FALSE; return ret; } @@ -404,8 +405,6 @@ radeon_present_unflip(ScreenPtr screen, uint64_t event_id) FLIP_ASYNC : FLIP_VSYNC; int i; - radeon_cs_flush_indirect(scrn); - if (!radeon_present_check_unflip(scrn)) goto modeset; @@ -424,7 +423,7 @@ radeon_present_unflip(ScreenPtr screen, uint64_t event_id) return; modeset: - radeon_bo_wait(info->front_bo); + radeon_finish(scrn, info->front_buffer); for (i = 0; i < config->num_crtc; i++) { xf86CrtcPtr crtc = config->crtc[i]; drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; diff --git a/src/radeon_probe.c b/src/radeon_probe.c index 19295f00..04f9e559 100644 --- a/src/radeon_probe.c +++ b/src/radeon_probe.c @@ -278,7 +278,7 @@ radeon_platform_probe(DriverPtr pDriver, } #endif -_X_EXPORT DriverRec RADEON = +DriverRec RADEON = { RADEON_VERSION_CURRENT, RADEON_DRIVER_NAME, diff --git a/src/radeon_probe.h b/src/radeon_probe.h index be82f9ae..7cb29b91 100644 --- a/src/radeon_probe.h +++ b/src/radeon_probe.h @@ -140,8 +140,8 @@ typedef struct unsigned long fd_wakeup_registered; /* server generation for which fd has been registered for wakeup handling */ int fd_wakeup_ref; unsigned int assigned_crtcs; - ScrnInfoPtr primary_scrn; - ScrnInfoPtr secondary_scrn; + unsigned int num_scrns; + ScrnInfoPtr scrn[6]; #ifdef XSERVER_PLATFORM_BUS struct xf86_platform_device *platform_dev; #endif diff --git a/src/radeon_textured_video.c b/src/radeon_textured_video.c index 63631c99..be71e408 100644 --- a/src/radeon_textured_video.c +++ b/src/radeon_textured_video.c @@ -153,7 +153,7 @@ radeon_allocate_video_bo(ScrnInfoPtr pScrn, static void RADEONFreeVideoMemory(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) { - if (pPriv->video_memory != NULL) { + if (pPriv->video_memory) { radeon_bo_unref(pPriv->video_memory); pPriv->video_memory = NULL; @@ -312,7 +312,7 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, RADEONFreeVideoMemory(pScrn, pPriv); } - if (pPriv->video_memory == NULL) { + if (!pPriv->video_memory) { Bool ret; ret = radeon_allocate_video_bo(pScrn, &pPriv->video_memory, @@ -329,7 +329,7 @@ RADEONPutImageTextured(ScrnInfoPtr pScrn, /* Bicubic filter loading */ if (pPriv->bicubic_enabled) { - if (info->bicubic_bo == NULL) + if (!info->bicubic_bo) pPriv->bicubic_enabled = FALSE; } @@ -499,11 +499,11 @@ static XF86VideoEncodingRec DummyEncodingEG[1] = } }; -#define NUM_FORMATS 3 +#define NUM_FORMATS 4 static XF86VideoFormatRec Formats[NUM_FORMATS] = { - {15, TrueColor}, {16, TrueColor}, {24, TrueColor} + {15, TrueColor}, {16, TrueColor}, {24, TrueColor}, {30, TrueColor} }; #define NUM_ATTRIBUTES 2 @@ -725,7 +725,7 @@ static void radeon_unload_bicubic_texture(ScrnInfoPtr pScrn) { RADEONInfoPtr info = RADEONPTR(pScrn); - if (info->bicubic_memory != NULL) { + if (info->bicubic_memory) { radeon_bo_unref(info->bicubic_memory); info->bicubic_memory = NULL; } @@ -827,7 +827,7 @@ RADEONSetupImageTexturedVideo(ScreenPtr pScreen) adapt = calloc(1, sizeof(XF86VideoAdaptorRec) + num_texture_ports * (sizeof(RADEONPortPrivRec) + sizeof(DevUnion))); - if (adapt == NULL) + if (!adapt) return NULL; xvBicubic = MAKE_ATOM("XV_BICUBIC"); diff --git a/src/radeon_textured_videofuncs.c b/src/radeon_textured_videofuncs.c index 653de44d..0959b119 100644 --- a/src/radeon_textured_videofuncs.c +++ b/src/radeon_textured_videofuncs.c @@ -63,10 +63,12 @@ RADEONPrepareTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) radeon_cs_space_add_persistent_bo(info->cs, src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); if (pPriv->bicubic_enabled) - radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); + radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, + RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); driver_priv = exaGetPixmapDriverPrivate(pPixmap); - radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); + radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 0, + RADEON_GEM_DOMAIN_VRAM); ret = radeon_cs_space_check(info->cs); if (ret) { @@ -433,10 +435,12 @@ R200PrepareTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) radeon_cs_space_add_persistent_bo(info->cs, src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); if (pPriv->bicubic_enabled) - radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); + radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, + RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); driver_priv = exaGetPixmapDriverPrivate(pPixmap); - radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); + radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 0, + RADEON_GEM_DOMAIN_VRAM); ret = radeon_cs_space_check(info->cs); if (ret) { @@ -958,10 +962,12 @@ R300PrepareTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) radeon_cs_space_add_persistent_bo(info->cs, src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); if (pPriv->bicubic_enabled) - radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); + radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, + RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); driver_priv = exaGetPixmapDriverPrivate(pPixmap); - radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); + radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 0, + RADEON_GEM_DOMAIN_VRAM); ret = radeon_cs_space_check(info->cs); if (ret) { @@ -2376,10 +2382,12 @@ R500PrepareTexturedVideo(ScrnInfoPtr pScrn, RADEONPortPrivPtr pPriv) radeon_cs_space_add_persistent_bo(info->cs, src_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); if (pPriv->bicubic_enabled) - radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); + radeon_cs_space_add_persistent_bo(info->cs, info->bicubic_bo, + RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); driver_priv = exaGetPixmapDriverPrivate(pPixmap); - radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo, 0, RADEON_GEM_DOMAIN_VRAM); + radeon_cs_space_add_persistent_bo(info->cs, driver_priv->bo->bo.radeon, 0, + RADEON_GEM_DOMAIN_VRAM); ret = radeon_cs_space_check(info->cs); if (ret) { diff --git a/src/radeon_video.c b/src/radeon_video.c index e08d8e00..fc321184 100644 --- a/src/radeon_video.c +++ b/src/radeon_video.c @@ -144,7 +144,7 @@ void RADEONInitVideo(ScreenPtr pScreen) num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors); newAdaptors = malloc((num_adaptors + 2) * sizeof(*newAdaptors)); - if (newAdaptors == NULL) + if (!newAdaptors) return; memcpy(newAdaptors, adaptors, num_adaptors * sizeof(XF86VideoAdaptorPtr)); @@ -152,7 +152,7 @@ void RADEONInitVideo(ScreenPtr pScreen) if (info->use_glamor) { texturedAdaptor = radeon_glamor_xv_init(pScreen, 16); - if (texturedAdaptor != NULL) { + if (texturedAdaptor) { adaptors[num_adaptors++] = texturedAdaptor; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video (glamor)\n"); } else @@ -161,7 +161,7 @@ void RADEONInitVideo(ScreenPtr pScreen) || (info->directRenderingEnabled) ) { texturedAdaptor = RADEONSetupImageTexturedVideo(pScreen); - if (texturedAdaptor != NULL) { + if (texturedAdaptor) { adaptors[num_adaptors++] = texturedAdaptor; xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Set up textured video\n"); } else |