summaryrefslogtreecommitdiff
path: root/driver/xf86-video-ati/src
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2016-04-02 07:37:35 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2016-04-02 07:37:35 +0000
commit8aa706cc566b1bdd1b34eda99aa39f03408ecc77 (patch)
tree64683856877270d249605ad5e6e726c07c887670 /driver/xf86-video-ati/src
parent4590cb8710f56e7c1b2c5b91a079d5765dda0ece (diff)
Update to xf86-video-ati 7.6.1. ok jsg@
Diffstat (limited to 'driver/xf86-video-ati/src')
-rw-r--r--driver/xf86-video-ati/src/Makefile.am10
-rw-r--r--driver/xf86-video-ati/src/Makefile.in33
-rw-r--r--driver/xf86-video-ati/src/ati_pciids_gen.h2
-rw-r--r--driver/xf86-video-ati/src/drmmode_display.c1023
-rw-r--r--driver/xf86-video-ati/src/drmmode_display.h46
-rw-r--r--driver/xf86-video-ati/src/evergreen_accel.c2
-rw-r--r--driver/xf86-video-ati/src/pcidb/ati_pciids.csv2
-rw-r--r--driver/xf86-video-ati/src/radeon.h107
-rw-r--r--driver/xf86-video-ati/src/radeon_accel.c1
-rw-r--r--driver/xf86-video-ati/src/radeon_bo_helper.c135
-rw-r--r--driver/xf86-video-ati/src/radeon_bo_helper.h6
-rw-r--r--driver/xf86-video-ati/src/radeon_chipinfo_gen.h2
-rw-r--r--driver/xf86-video-ati/src/radeon_chipset_gen.h2
-rw-r--r--driver/xf86-video-ati/src/radeon_dri2.c709
-rw-r--r--driver/xf86-video-ati/src/radeon_dri2.h37
-rw-r--r--driver/xf86-video-ati/src/radeon_dri3.c215
-rw-r--r--driver/xf86-video-ati/src/radeon_drm_queue.c181
-rw-r--r--driver/xf86-video-ati/src/radeon_drm_queue.h56
-rw-r--r--driver/xf86-video-ati/src/radeon_exa.c1
-rw-r--r--driver/xf86-video-ati/src/radeon_glamor.c121
-rw-r--r--driver/xf86-video-ati/src/radeon_glamor.h71
-rw-r--r--driver/xf86-video-ati/src/radeon_glamor_wrappers.c994
-rw-r--r--driver/xf86-video-ati/src/radeon_kms.c396
-rw-r--r--driver/xf86-video-ati/src/radeon_list.h39
-rw-r--r--driver/xf86-video-ati/src/radeon_pci_chipset_gen.h2
-rw-r--r--driver/xf86-video-ati/src/radeon_pci_device_match_gen.h2
-rw-r--r--driver/xf86-video-ati/src/radeon_present.c465
-rw-r--r--driver/xf86-video-ati/src/radeon_probe.c11
-rw-r--r--driver/xf86-video-ati/src/radeon_probe.h5
-rw-r--r--driver/xf86-video-ati/src/radeon_sync.c145
-rw-r--r--driver/xf86-video-ati/src/radeon_video.c63
-rw-r--r--driver/xf86-video-ati/src/radeon_video.h1
32 files changed, 3991 insertions, 894 deletions
diff --git a/driver/xf86-video-ati/src/Makefile.am b/driver/xf86-video-ati/src/Makefile.am
index 9ff1ffba0..8f39e213e 100644
--- a/driver/xf86-video-ati/src/Makefile.am
+++ b/driver/xf86-video-ati/src/Makefile.am
@@ -27,10 +27,11 @@
# TODO: -nostdlib/-Bstatic/-lgcc platform magic, not installing the .a, etc.
ati_drv_la_LIBADD = $(PCIACCESS_LIBS)
-radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS) $(PCIACCESS_LIBS)
+radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS)
-RADEON_KMS_SRCS=radeon_dri2.c radeon_kms.c drmmode_display.c radeon_vbo.c \
- radeon_bo_helper.c
+RADEON_KMS_SRCS=radeon_dri2.c radeon_dri3.c radeon_drm_queue.c radeon_kms.c \
+ radeon_present.c radeon_sync.c radeon_vbo.c radeon_bo_helper.c \
+ drmmode_display.c
RADEON_EXA_SOURCES = radeon_exa.c r600_exa.c r6xx_accel.c r600_textured_videofuncs.c r600_shader.c radeon_exa_shared.c \
evergreen_exa.c evergreen_accel.c evergreen_shader.c evergreen_textured_videofuncs.c cayman_accel.c cayman_shader.c
@@ -64,6 +65,7 @@ if GLAMOR
AM_CFLAGS += @LIBGLAMOR_CFLAGS@
radeon_drv_la_LIBADD += @LIBGLAMOR_LIBS@
radeon_drv_la_SOURCES += \
+ radeon_glamor_wrappers.c \
radeon_glamor.c
endif
@@ -88,11 +90,13 @@ EXTRA_DIST = \
bicubic_table.h \
bicubic_table.py \
radeon_bo_helper.h \
+ radeon_drm_queue.h \
radeon_exa_render.c \
radeon_exa_funcs.c \
radeon_exa_shared.h \
radeon_glamor.h \
radeon.h \
+ radeon_list.h \
radeon_probe.h \
radeon_reg.h \
radeon_version.h \
diff --git a/driver/xf86-video-ati/src/Makefile.in b/driver/xf86-video-ati/src/Makefile.in
index a84f7d64b..fdb64e268 100644
--- a/driver/xf86-video-ati/src/Makefile.in
+++ b/driver/xf86-video-ati/src/Makefile.in
@@ -81,6 +81,7 @@ host_triplet = @host@
@GLAMOR_TRUE@am__append_2 = @LIBGLAMOR_CFLAGS@
@GLAMOR_TRUE@am__append_3 = @LIBGLAMOR_LIBS@
@GLAMOR_TRUE@am__append_4 = \
+@GLAMOR_TRUE@ radeon_glamor_wrappers.c \
@GLAMOR_TRUE@ radeon_glamor.c
subdir = src
@@ -137,24 +138,26 @@ ati_drv_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(ati_drv_la_LDFLAGS) $(LDFLAGS) -o $@
@LIBUDEV_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
radeon_drv_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
- $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2) \
- $(am__DEPENDENCIES_1)
+ $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1)
am__radeon_drv_la_SOURCES_DIST = radeon_accel.c radeon_video.c \
radeon_misc.c radeon_probe.c radeon_textured_video.c \
radeon_xvmc.c radeon_exa.c r600_exa.c r6xx_accel.c \
r600_textured_videofuncs.c r600_shader.c radeon_exa_shared.c \
evergreen_exa.c evergreen_accel.c evergreen_shader.c \
evergreen_textured_videofuncs.c cayman_accel.c cayman_shader.c \
- radeon_dri2.c radeon_kms.c drmmode_display.c radeon_vbo.c \
- radeon_bo_helper.c radeon_glamor.c
+ radeon_dri2.c radeon_dri3.c radeon_drm_queue.c radeon_kms.c \
+ radeon_present.c radeon_sync.c radeon_vbo.c radeon_bo_helper.c \
+ drmmode_display.c radeon_glamor_wrappers.c radeon_glamor.c
am__objects_1 = radeon_exa.lo r600_exa.lo r6xx_accel.lo \
r600_textured_videofuncs.lo r600_shader.lo \
radeon_exa_shared.lo evergreen_exa.lo evergreen_accel.lo \
evergreen_shader.lo evergreen_textured_videofuncs.lo \
cayman_accel.lo cayman_shader.lo
-am__objects_2 = radeon_dri2.lo radeon_kms.lo drmmode_display.lo \
- radeon_vbo.lo radeon_bo_helper.lo
-@GLAMOR_TRUE@am__objects_3 = radeon_glamor.lo
+am__objects_2 = radeon_dri2.lo radeon_dri3.lo radeon_drm_queue.lo \
+ radeon_kms.lo radeon_present.lo radeon_sync.lo radeon_vbo.lo \
+ radeon_bo_helper.lo drmmode_display.lo
+@GLAMOR_TRUE@am__objects_3 = radeon_glamor_wrappers.lo \
+@GLAMOR_TRUE@ radeon_glamor.lo
am_radeon_drv_la_OBJECTS = radeon_accel.lo radeon_video.lo \
radeon_misc.lo radeon_probe.lo radeon_textured_video.lo \
radeon_xvmc.lo $(am__objects_1) $(am__objects_2) \
@@ -363,10 +366,11 @@ top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
ati_drv_la_LIBADD = $(PCIACCESS_LIBS)
-radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS) $(PCIACCESS_LIBS) \
- $(am__append_1) $(am__append_3)
-RADEON_KMS_SRCS = radeon_dri2.c radeon_kms.c drmmode_display.c radeon_vbo.c \
- radeon_bo_helper.c
+radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS) $(am__append_1) \
+ $(am__append_3)
+RADEON_KMS_SRCS = radeon_dri2.c radeon_dri3.c radeon_drm_queue.c radeon_kms.c \
+ radeon_present.c radeon_sync.c radeon_vbo.c radeon_bo_helper.c \
+ drmmode_display.c
RADEON_EXA_SOURCES = radeon_exa.c r600_exa.c r6xx_accel.c r600_textured_videofuncs.c r600_shader.c radeon_exa_shared.c \
evergreen_exa.c evergreen_accel.c evergreen_shader.c evergreen_textured_videofuncs.c cayman_accel.c cayman_shader.c
@@ -406,11 +410,13 @@ EXTRA_DIST = \
bicubic_table.h \
bicubic_table.py \
radeon_bo_helper.h \
+ radeon_drm_queue.h \
radeon_exa_render.c \
radeon_exa_funcs.c \
radeon_exa_shared.h \
radeon_glamor.h \
radeon.h \
+ radeon_list.h \
radeon_probe.h \
radeon_reg.h \
radeon_version.h \
@@ -558,12 +564,17 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_accel.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_bo_helper.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_dri2.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_dri3.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_drm_queue.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_exa.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_exa_shared.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_glamor.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_glamor_wrappers.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_kms.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_misc.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_present.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_probe.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_sync.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_textured_video.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_vbo.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/radeon_video.Plo@am__quote@
diff --git a/driver/xf86-video-ati/src/ati_pciids_gen.h b/driver/xf86-video-ati/src/ati_pciids_gen.h
index d867fa71e..c6216a54c 100644
--- a/driver/xf86-video-ati/src/ati_pciids_gen.h
+++ b/driver/xf86-video-ati/src/ati_pciids_gen.h
@@ -692,6 +692,7 @@
#define PCI_CHIP_OLAND_6610 0x6610
#define PCI_CHIP_OLAND_6611 0x6611
#define PCI_CHIP_OLAND_6613 0x6613
+#define PCI_CHIP_OLAND_6617 0x6617
#define PCI_CHIP_OLAND_6620 0x6620
#define PCI_CHIP_OLAND_6621 0x6621
#define PCI_CHIP_OLAND_6623 0x6623
@@ -712,6 +713,7 @@
#define PCI_CHIP_BONAIRE_6658 0x6658
#define PCI_CHIP_BONAIRE_665C 0x665C
#define PCI_CHIP_BONAIRE_665D 0x665D
+#define PCI_CHIP_BONAIRE_665F 0x665F
#define PCI_CHIP_KABINI_9830 0x9830
#define PCI_CHIP_KABINI_9831 0x9831
#define PCI_CHIP_KABINI_9832 0x9832
diff --git a/driver/xf86-video-ati/src/drmmode_display.c b/driver/xf86-video-ati/src/drmmode_display.c
index c8f060a76..4c8931eea 100644
--- a/driver/xf86-video-ati/src/drmmode_display.c
+++ b/driver/xf86-video-ati/src/drmmode_display.c
@@ -32,11 +32,13 @@
#include <errno.h>
#include <sys/ioctl.h>
#include <time.h>
+#include "cursorstr.h"
+#include "damagestr.h"
#include "micmap.h"
#include "xf86cmap.h"
#include "radeon.h"
+#include "radeon_glamor.h"
#include "radeon_reg.h"
-#include "sarea.h"
#include "drmmode_display.h"
@@ -97,7 +99,8 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
PixmapPtr pixmap;
struct radeon_surface *surface;
- pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth, 0);
+ pixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, depth,
+ RADEON_CREATE_PIXMAP_SCANOUT);
if (!pixmap)
return NULL;
@@ -147,7 +150,9 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
}
}
- if (!radeon_glamor_create_textured_pixmap(pixmap)) {
+ if (info->use_glamor &&
+ !radeon_glamor_create_textured_pixmap(pixmap,
+ radeon_get_pixmap_private(pixmap))) {
pScreen->DestroyPixmap(pixmap);
return NULL;
}
@@ -245,6 +250,33 @@ int drmmode_get_current_ust(int drm_fd, CARD64 *ust)
return 0;
}
+/*
+ * Get current frame count and frame count timestamp of the crtc.
+ */
+int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
+{
+ ScrnInfoPtr scrn = crtc->scrn;
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ drmVBlank vbl;
+ int ret;
+
+ vbl.request.type = DRM_VBLANK_RELATIVE;
+ vbl.request.type |= radeon_populate_vbl_request_type(crtc);
+ vbl.request.sequence = 0;
+
+ ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "get vblank counter failed: %s\n", strerror(errno));
+ return ret;
+ }
+
+ *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
+ *msc = vbl.reply.sequence;
+
+ return Success;
+}
+
static void
drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
{
@@ -310,18 +342,31 @@ drmmode_do_crtc_dpms(xf86CrtcPtr crtc, int mode)
static void
drmmode_crtc_dpms(xf86CrtcPtr crtc, int mode)
{
- /* Nothing to do. drmmode_do_crtc_dpms() is called as appropriate */
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+
+ /* Disable unused CRTCs */
+ if (!crtc->enabled || mode != DPMSModeOn)
+ drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ 0, 0, 0, NULL, 0, NULL);
+ else if (drmmode_crtc->dpms_mode != DPMSModeOn)
+ crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
+ crtc->x, crtc->y);
}
static PixmapPtr
create_pixmap_for_fbcon(drmmode_ptr drmmode,
ScrnInfoPtr pScrn, int fbcon_id)
{
- PixmapPtr pixmap = NULL;
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ PixmapPtr pixmap = info->fbcon_pixmap;
struct radeon_bo *bo;
drmModeFBPtr fbcon;
struct drm_gem_flink flink;
+ if (pixmap)
+ return pixmap;
+
fbcon = drmModeGetFB(drmmode->fd, fbcon_id);
if (fbcon == NULL)
return NULL;
@@ -348,12 +393,32 @@ create_pixmap_for_fbcon(drmmode_ptr drmmode,
pixmap = drmmode_create_bo_pixmap(pScrn, fbcon->width, fbcon->height,
fbcon->depth, fbcon->bpp,
fbcon->pitch, 0, bo, NULL);
+ info->fbcon_pixmap = pixmap;
radeon_bo_unref(bo);
out_free_fb:
drmModeFreeFB(fbcon);
return pixmap;
}
+static void
+destroy_pixmap_for_fbcon(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(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
+ */
+ if (info->use_glamor && info->ChipFamily >= CHIP_FAMILY_CAYMAN)
+ return;
+
+ if (info->fbcon_pixmap)
+ pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
+ info->fbcon_pixmap = NULL;
+}
+
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
+
void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
@@ -361,13 +426,9 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
PixmapPtr src, dst;
ScreenPtr pScreen = pScrn->pScreen;
int fbcon_id = 0;
+ Bool force;
+ GCPtr gc;
int i;
- int pitch;
- uint32_t tiling_flags = 0;
- Bool ret;
-
- if (info->accelOn == FALSE || info->use_glamor)
- goto fallback;
for (i = 0; i < xf86_config->num_crtc; i++) {
drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[i]->driver_private;
@@ -377,7 +438,7 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
}
if (!fbcon_id)
- goto fallback;
+ return;
if (fbcon_id == drmmode->fb_id) {
/* in some rare case there might be no fbcon and we might already
@@ -390,54 +451,165 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
src = create_pixmap_for_fbcon(drmmode, pScrn, fbcon_id);
if (!src)
- goto fallback;
+ return;
- if (info->allowColorTiling) {
- 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;
- }
+ dst = pScreen->GetScreenPixmap(pScreen);
- pitch = RADEON_ALIGN(pScrn->displayWidth,
- drmmode_get_pitch_align(pScrn, info->pixel_bytes, tiling_flags)) *
- info->pixel_bytes;
+ gc = GetScratchGC(pScrn->depth, pScreen);
+ ValidateGC(&dst->drawable, gc);
+
+ force = info->accel_state->force;
+ info->accel_state->force = TRUE;
+ (*gc->ops->CopyArea)(&src->drawable, &dst->drawable, gc, 0, 0,
+ pScrn->virtualX, pScrn->virtualY, 0, 0);
+ info->accel_state->force = force;
+
+ FreeScratchGC(gc);
- dst = drmmode_create_bo_pixmap(pScrn, pScrn->virtualX,
- pScrn->virtualY, pScrn->depth,
- pScrn->bitsPerPixel, pitch,
- tiling_flags, info->front_bo, &info->front_surface);
- if (!dst)
- goto out_free_src;
-
- ret = info->accel_state->exa->PrepareCopy (src, dst,
- -1, -1, GXcopy, FB_ALLONES);
- if (!ret)
- goto out_free_src;
- info->accel_state->exa->Copy (dst, 0, 0, 0, 0,
- pScrn->virtualX, pScrn->virtualY);
- info->accel_state->exa->DoneCopy (dst);
radeon_cs_flush_indirect(pScrn);
+ radeon_bo_wait(info->front_bo);
-#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
pScreen->canDoBGNoneRoot = TRUE;
-#endif
- drmmode_destroy_bo_pixmap(dst);
- out_free_src:
- drmmode_destroy_bo_pixmap(src);
+ destroy_pixmap_for_fbcon(pScrn);
return;
+}
-fallback:
- /* map and memset the bo */
- if (radeon_bo_map(info->front_bo, 1))
- return;
+#endif /* GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10 */
+
+static void
+drmmode_crtc_scanout_destroy(drmmode_ptr drmmode,
+ struct drmmode_scanout *scanout)
+{
+ if (scanout->pixmap) {
+ drmmode_destroy_bo_pixmap(scanout->pixmap);
+ scanout->pixmap = NULL;
+ }
+
+ if (scanout->bo) {
+ drmModeRmFB(drmmode->fd, scanout->fb_id);
+ scanout->fb_id = 0;
+ radeon_bo_unmap(scanout->bo);
+ radeon_bo_unref(scanout->bo);
+ scanout->bo = NULL;
+ }
+
+ if (scanout->damage) {
+ DamageDestroy(scanout->damage);
+ scanout->damage = NULL;
+ }
+}
+
+void
+drmmode_scanout_free(ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ drmmode_crtc_private_ptr drmmode_crtc =
+ xf86_config->crtc[c]->driver_private;
+
+ drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+ &drmmode_crtc->scanout[0]);
+ drmmode_crtc_scanout_destroy(drmmode_crtc->drmmode,
+ &drmmode_crtc->scanout[1]);
+ }
+}
+
+static void *
+drmmode_crtc_scanout_allocate(xf86CrtcPtr crtc,
+ struct drmmode_scanout *scanout,
+ int width, int height)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ int aligned_height;
+ int size;
+ int ret;
+ unsigned long rotate_pitch;
+ int base_align;
+
+ if (scanout->bo) {
+ if (scanout->width == width && scanout->height == height)
+ return scanout->bo->ptr;
+
+ drmmode_crtc_scanout_destroy(drmmode, scanout);
+ }
+
+ rotate_pitch =
+ RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0))
+ * drmmode->cpp;
+ aligned_height = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, 0));
+ base_align = drmmode_get_base_align(pScrn, drmmode->cpp, 0);
+ size = RADEON_ALIGN(rotate_pitch * aligned_height, RADEON_GPU_PAGE_SIZE);
+
+ scanout->bo = radeon_bo_open(drmmode->bufmgr, 0, size, base_align,
+ RADEON_GEM_DOMAIN_VRAM, 0);
+ if (scanout->bo == NULL)
+ return NULL;
+
+ radeon_bo_map(scanout->bo, 1);
+
+ ret = drmModeAddFB(drmmode->fd, width, height, pScrn->depth,
+ pScrn->bitsPerPixel, rotate_pitch,
+ scanout->bo->handle,
+ &scanout->fb_id);
+ if (ret) {
+ ErrorF("failed to add scanout fb\n");
+ radeon_bo_unref(scanout->bo);
+ scanout->bo = NULL;
+ return NULL;
+ }
+
+ scanout->width = width;
+ scanout->height = height;
+ return scanout->bo->ptr;
+}
+
+static PixmapPtr
+drmmode_crtc_scanout_create(xf86CrtcPtr crtc, struct drmmode_scanout *scanout,
+ int width, int height)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ unsigned long rotate_pitch;
+
+ if (scanout->pixmap) {
+ if (scanout->width == width && scanout->height == height)
+ return scanout->pixmap;
+
+ drmmode_crtc_scanout_destroy(drmmode, scanout);
+ }
+
+ if (!scanout->bo) {
+ if (!drmmode_crtc_scanout_allocate(crtc, scanout, width, height))
+ return NULL;
+ }
+
+ rotate_pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0))
+ * drmmode->cpp;
+
+ scanout->pixmap = drmmode_create_bo_pixmap(pScrn,
+ width, height,
+ pScrn->depth,
+ pScrn->bitsPerPixel,
+ rotate_pitch,
+ 0, scanout->bo, NULL);
+ if (scanout->pixmap == NULL)
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Couldn't allocate scanout pixmap for CRTC\n");
+
+ return scanout->pixmap;
+}
- memset(info->front_bo->ptr, 0x00, info->front_bo->size);
- radeon_bo_unmap(info->front_bo);
+static void
+radeon_screen_damage_report(DamagePtr damage, RegionPtr region, void *closure)
+{
+ /* Only keep track of the extents */
+ RegionUninit(&damage->damage);
+ damage->damage.data = NULL;
}
static Bool
@@ -452,7 +624,7 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
int saved_x, saved_y;
Rotation saved_rotation;
DisplayModeRec saved_mode;
- uint32_t *output_ids;
+ uint32_t *output_ids = NULL;
int output_count = 0;
Bool ret = TRUE;
int i;
@@ -460,7 +632,6 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
drmModeModeInfo kmode;
int pitch;
uint32_t tiling_flags = 0;
- int height;
if (info->allowColorTiling) {
if (info->ChipFamily >= CHIP_FAMILY_R600)
@@ -471,14 +642,13 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
pitch = RADEON_ALIGN(pScrn->displayWidth, drmmode_get_pitch_align(pScrn, info->pixel_bytes, tiling_flags)) *
info->pixel_bytes;
- height = RADEON_ALIGN(pScrn->virtualY, drmmode_get_height_align(pScrn, tiling_flags));
if (info->ChipFamily >= CHIP_FAMILY_R600) {
pitch = info->front_surface.level[0].pitch_bytes;
}
if (drmmode->fb_id == 0) {
ret = drmModeAddFB(drmmode->fd,
- pScrn->virtualX, height,
+ pScrn->virtualX, pScrn->virtualY,
pScrn->depth, pScrn->bitsPerPixel,
pitch,
info->front_bo->handle,
@@ -500,15 +670,15 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
crtc->y = y;
crtc->rotation = rotation;
crtc->transformPresent = FALSE;
- }
- output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
- if (!output_ids) {
- ret = FALSE;
- goto done;
- }
+ output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
+ if (!output_ids) {
+ ret = FALSE;
+ goto done;
+ }
+
+ ScreenPtr pScreen = pScrn->pScreen;
- if (mode) {
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
drmmode_output_private_ptr drmmode_output;
@@ -532,24 +702,76 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
fb_id = drmmode->fb_id;
#ifdef RADEON_PIXMAP_SHARING
if (crtc->randr_crtc && crtc->randr_crtc->scanout_pixmap) {
- x = drmmode_crtc->scanout_pixmap_x;
+ x = drmmode_crtc->prime_pixmap_x;
y = 0;
+
+ drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[0]);
+ drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]);
} else
#endif
- if (drmmode_crtc->rotate_fb_id) {
- fb_id = drmmode_crtc->rotate_fb_id;
+ if (drmmode_crtc->rotate.fb_id) {
+ fb_id = drmmode_crtc->rotate.fb_id;
x = y = 0;
+
+ drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[0]);
+ drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->scanout[1]);
+ } else if (info->tear_free || info->shadow_primary) {
+ for (i = 0; i < (info->tear_free ? 2 : 1); i++) {
+ drmmode_crtc_scanout_create(crtc,
+ &drmmode_crtc->scanout[i],
+ mode->HDisplay,
+ mode->VDisplay);
+
+ if (drmmode_crtc->scanout[i].pixmap) {
+ RegionPtr pRegion;
+ BoxPtr pBox;
+
+ if (!drmmode_crtc->scanout[i].damage) {
+ drmmode_crtc->scanout[i].damage =
+ DamageCreate(radeon_screen_damage_report,
+ NULL, DamageReportRawRegion,
+ TRUE, pScreen, NULL);
+ DamageRegister(&pScreen->GetScreenPixmap(pScreen)->drawable,
+ drmmode_crtc->scanout[i].damage);
+ }
+
+ pRegion = DamageRegion(drmmode_crtc->scanout[i].damage);
+ RegionUninit(pRegion);
+ pRegion->data = NULL;
+ pBox = RegionExtents(pRegion);
+ pBox->x1 = min(pBox->x1, x);
+ pBox->y1 = min(pBox->y1, y);
+ pBox->x2 = max(pBox->x2, x + mode->HDisplay);
+ pBox->y2 = max(pBox->y2, y + mode->VDisplay);
+ }
+ }
+
+ if (drmmode_crtc->scanout[0].pixmap &&
+ (!info->tear_free || drmmode_crtc->scanout[1].pixmap)) {
+ drmmode_crtc->scanout_id = 0;
+ fb_id = drmmode_crtc->scanout[0].fb_id;
+ x = y = 0;
+
+ radeon_scanout_update_handler(pScrn, 0, 0, crtc);
+ radeon_bo_wait(drmmode_crtc->scanout[0].bo);
+ }
}
- ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
- fb_id, x, y, output_ids, output_count, &kmode);
- if (ret)
+ if (drmModeSetCrtc(drmmode->fd,
+ drmmode_crtc->mode_crtc->crtc_id,
+ fb_id, x, y, output_ids,
+ output_count, &kmode) != 0) {
xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
- "failed to set mode: %s", strerror(-ret));
- else
+ "failed to set mode: %s", strerror(errno));
+ ret = FALSE;
+ goto done;
+ } else
ret = TRUE;
if (crtc->scrn->pScreen)
xf86CrtcSetScreenSubpixelOrder(crtc->scrn->pScreen);
+
+ drmmode_crtc->need_modeset = FALSE;
+
/* go through all the outputs and force DPMS them back on? */
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
@@ -576,6 +798,7 @@ done:
else
crtc->active = TRUE;
#endif
+ free(output_ids);
return ret;
}
@@ -634,6 +857,22 @@ drmmode_show_cursor (xf86CrtcPtr crtc)
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
uint32_t handle = drmmode_crtc->cursor_bo->handle;
+ static Bool use_set_cursor2 = TRUE;
+
+ if (use_set_cursor2) {
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
+ CursorPtr cursor = xf86_config->cursor;
+ int ret;
+
+ ret =
+ drmModeSetCursor2(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ handle, info->cursor_w, info->cursor_h,
+ cursor->bits->xhot, cursor->bits->yhot);
+ if (ret == -EINVAL)
+ use_set_cursor2 = FALSE;
+ else
+ return;
+ }
drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle,
info->cursor_w, info->cursor_h);
@@ -642,73 +881,22 @@ drmmode_show_cursor (xf86CrtcPtr crtc)
static void *
drmmode_crtc_shadow_allocate(xf86CrtcPtr crtc, int width, int height)
{
- ScrnInfoPtr pScrn = crtc->scrn;
- RADEONInfoPtr info = RADEONPTR(pScrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- drmmode_ptr drmmode = drmmode_crtc->drmmode;
- int size;
- struct radeon_bo *rotate_bo;
- int ret;
- unsigned long rotate_pitch;
- int base_align;
-
- /* rotation requires acceleration */
- if (info->r600_shadow_fb) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Rotation requires acceleration!\n");
- return NULL;
- }
-
- rotate_pitch =
- RADEON_ALIGN(width, drmmode_get_pitch_align(crtc->scrn, drmmode->cpp, 0)) * drmmode->cpp;
- height = RADEON_ALIGN(height, drmmode_get_height_align(crtc->scrn, 0));
- base_align = drmmode_get_base_align(crtc->scrn, drmmode->cpp, 0);
- size = RADEON_ALIGN(rotate_pitch * height, RADEON_GPU_PAGE_SIZE);
-
- rotate_bo = radeon_bo_open(drmmode->bufmgr, 0, size, base_align, RADEON_GEM_DOMAIN_VRAM, 0);
- if (rotate_bo == NULL)
- return NULL;
- radeon_bo_map(rotate_bo, 1);
-
- ret = drmModeAddFB(drmmode->fd, width, height, crtc->scrn->depth,
- crtc->scrn->bitsPerPixel, rotate_pitch,
- rotate_bo->handle,
- &drmmode_crtc->rotate_fb_id);
- if (ret) {
- ErrorF("failed to add rotate fb\n");
- }
-
- drmmode_crtc->rotate_bo = rotate_bo;
- return drmmode_crtc->rotate_bo->ptr;
+ return drmmode_crtc_scanout_allocate(crtc, &drmmode_crtc->rotate,
+ width, height);
}
static PixmapPtr
drmmode_crtc_shadow_create(xf86CrtcPtr crtc, void *data, int width, int height)
{
- ScrnInfoPtr pScrn = crtc->scrn;
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- drmmode_ptr drmmode = drmmode_crtc->drmmode;
- unsigned long rotate_pitch;
- PixmapPtr rotate_pixmap;
-
- if (!data)
- data = drmmode_crtc_shadow_allocate (crtc, width, height);
-
- rotate_pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, drmmode->cpp, 0)) * drmmode->cpp;
-
- rotate_pixmap = drmmode_create_bo_pixmap(pScrn,
- width, height,
- pScrn->depth,
- pScrn->bitsPerPixel,
- rotate_pitch,
- 0, drmmode_crtc->rotate_bo, NULL);
- if (rotate_pixmap == NULL) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Couldn't allocate shadow pixmap for rotated CRTC\n");
- }
- return rotate_pixmap;
+ /* Xorg passes in the return value of drmmode_crtc_shadow_allocate
+ * for data, but that's redundant for drmmode_crtc_scanout_create.
+ */
+ return drmmode_crtc_scanout_create(crtc, &drmmode_crtc->rotate, width,
+ height);
}
static void
@@ -717,17 +905,7 @@ drmmode_crtc_shadow_destroy(xf86CrtcPtr crtc, PixmapPtr rotate_pixmap, void *dat
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
- if (rotate_pixmap)
- drmmode_destroy_bo_pixmap(rotate_pixmap);
-
- if (data) {
- drmModeRmFB(drmmode->fd, drmmode_crtc->rotate_fb_id);
- drmmode_crtc->rotate_fb_id = 0;
- radeon_bo_unmap(drmmode_crtc->rotate_bo);
- radeon_bo_unref(drmmode_crtc->rotate_bo);
- drmmode_crtc->rotate_bo = NULL;
- }
-
+ drmmode_crtc_scanout_destroy(drmmode, &drmmode_crtc->rotate);
}
static void
@@ -754,7 +932,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
if (!ppix) {
if (crtc->randr_crtc->scanout_pixmap)
PixmapStopDirtyTracking(crtc->randr_crtc->scanout_pixmap, screenpix);
- drmmode_crtc->scanout_pixmap_x = 0;
+ drmmode_crtc->prime_pixmap_x = 0;
return TRUE;
}
@@ -793,8 +971,10 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
screen->width = screenpix->drawable.width = total_width;
screen->height = screenpix->drawable.height = max_height;
}
- drmmode_crtc->scanout_pixmap_x = this_x;
-#ifdef HAS_DIRTYTRACKING2
+ drmmode_crtc->prime_pixmap_x = this_x;
+#ifdef HAS_DIRTYTRACKING_ROTATION
+ PixmapStartDirtyTracking(ppix, screenpix, 0, 0, this_x, 0, RR_Rotate_0);
+#elif defined(HAS_DIRTYTRACKING2)
PixmapStartDirtyTracking2(ppix, screenpix, 0, 0, this_x, 0);
#else
PixmapStartDirtyTracking(ppix, screenpix, 0, 0);
@@ -803,7 +983,7 @@ drmmode_set_scanout_pixmap(xf86CrtcPtr crtc, PixmapPtr ppix)
}
#endif
-static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
+static xf86CrtcFuncsRec drmmode_crtc_funcs = {
.dpms = drmmode_crtc_dpms,
.set_mode_major = drmmode_set_mode_major,
.set_cursor_colors = drmmode_set_cursor_colors,
@@ -849,23 +1029,29 @@ void drmmode_crtc_hw_id(xf86CrtcPtr crtc)
drmmode_crtc->hw_id = tmp;
}
-static void
-drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
+static unsigned int
+drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num)
{
xf86CrtcPtr crtc;
drmmode_crtc_private_ptr drmmode_crtc;
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
crtc = xf86CrtcCreate(pScrn, &drmmode_crtc_funcs);
if (crtc == NULL)
- return;
+ return 0;
drmmode_crtc = xnfcalloc(sizeof(drmmode_crtc_private_rec), 1);
- drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, drmmode->mode_res->crtcs[num]);
+ drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd, mode_res->crtcs[num]);
drmmode_crtc->drmmode = drmmode;
crtc->driver_private = drmmode_crtc;
drmmode_crtc_hw_id(crtc);
- return;
+ /* Mark num'th crtc as in use on this device. */
+ pRADEONEnt->assigned_crtcs |= (1 << num);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Allocated crtc nr. %d to this screen.\n", num);
+
+ return 1;
}
static xf86OutputStatus
@@ -975,17 +1161,28 @@ static void
drmmode_output_dpms(xf86OutputPtr output, int mode)
{
drmmode_output_private_ptr drmmode_output = output->driver_private;
+ xf86CrtcPtr crtc = output->crtc;
drmModeConnectorPtr koutput = drmmode_output->mode_output;
drmmode_ptr drmmode = drmmode_output->drmmode;
- if (mode != DPMSModeOn && output->crtc)
- drmmode_do_crtc_dpms(output->crtc, mode);
+ if (!koutput)
+ return;
+
+ if (mode != DPMSModeOn && crtc)
+ drmmode_do_crtc_dpms(crtc, mode);
drmModeConnectorSetProperty(drmmode->fd, koutput->connector_id,
drmmode_output->dpms_enum_id, mode);
- if (mode == DPMSModeOn && output->crtc)
- drmmode_do_crtc_dpms(output->crtc, mode);
+ if (mode == DPMSModeOn && crtc) {
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ if (drmmode_crtc->need_modeset)
+ drmmode_set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x,
+ crtc->y);
+ else
+ drmmode_do_crtc_dpms(crtc, mode);
+ }
}
@@ -1194,22 +1391,137 @@ const char *output_names[] = { "None",
#define NUM_OUTPUT_NAMES (sizeof(output_names) / sizeof(output_names[0]))
+static xf86OutputPtr find_output(ScrnInfoPtr pScrn, int id)
+{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int i;
+ for (i = 0; i < xf86_config->num_output; i++) {
+ xf86OutputPtr output = xf86_config->output[i];
+ drmmode_output_private_ptr drmmode_output;
+
+ drmmode_output = output->driver_private;
+ if (drmmode_output->output_id == id)
+ return output;
+ }
+ return NULL;
+}
+
+static int parse_path_blob(drmModePropertyBlobPtr path_blob, int *conn_base_id, char **path)
+{
+ char *conn;
+ char conn_id[5];
+ int id, len;
+ char *blob_data;
+
+ if (!path_blob)
+ return -1;
+
+ blob_data = path_blob->data;
+ /* we only handle MST paths for now */
+ if (strncmp(blob_data, "mst:", 4))
+ return -1;
+
+ conn = strchr(blob_data + 4, '-');
+ if (!conn)
+ return -1;
+ len = conn - (blob_data + 4);
+ if (len + 1 > 5)
+ return -1;
+ memcpy(conn_id, blob_data + 4, len);
+ conn_id[len] = '\0';
+ id = strtoul(conn_id, NULL, 10);
+
+ *conn_base_id = id;
+
+ *path = conn + 1;
+ return 0;
+}
+
static void
-drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dvi, int *num_hdmi)
+drmmode_create_name(ScrnInfoPtr pScrn, drmModeConnectorPtr koutput, char *name,
+ drmModePropertyBlobPtr path_blob, int *num_dvi, int *num_hdmi)
+{
+ xf86OutputPtr output;
+ int conn_id;
+ char *extra_path;
+
+ output = NULL;
+ if (parse_path_blob(path_blob, &conn_id, &extra_path) == 0)
+ output = find_output(pScrn, conn_id);
+ if (output) {
+ snprintf(name, 32, "%s-%s", output->name, extra_path);
+ } else {
+ if (koutput->connector_type >= NUM_OUTPUT_NAMES)
+ snprintf(name, 32, "Unknown%d-%d", koutput->connector_type,
+ koutput->connector_type_id - 1);
+#ifdef RADEON_PIXMAP_SHARING
+ else if (pScrn->is_gpu)
+ snprintf(name, 32, "%s-%d-%d",
+ output_names[koutput->connector_type], pScrn->scrnIndex - GPU_SCREEN_OFFSET + 1,
+ koutput->connector_type_id - 1);
+#endif
+ else {
+ /* need to do smart conversion here for compat with non-kms ATI driver */
+ if (koutput->connector_type_id == 1) {
+ switch(koutput->connector_type) {
+ case DRM_MODE_CONNECTOR_DVII:
+ case DRM_MODE_CONNECTOR_DVID:
+ case DRM_MODE_CONNECTOR_DVIA:
+ snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_dvi);
+ (*num_dvi)++;
+ break;
+ case DRM_MODE_CONNECTOR_HDMIA:
+ case DRM_MODE_CONNECTOR_HDMIB:
+ snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_hdmi);
+ (*num_hdmi)++;
+ break;
+ case DRM_MODE_CONNECTOR_VGA:
+ case DRM_MODE_CONNECTOR_DisplayPort:
+ snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
+ koutput->connector_type_id - 1);
+ break;
+ default:
+ snprintf(name, 32, "%s", output_names[koutput->connector_type]);
+ break;
+ }
+ } else {
+ snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
+ koutput->connector_type_id - 1);
+ }
+ }
+ }
+}
+
+static unsigned int
+drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, drmModeResPtr mode_res, int num, int *num_dvi, int *num_hdmi, int dynamic)
{
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
RADEONInfoPtr info = RADEONPTR(pScrn);
xf86OutputPtr output;
drmModeConnectorPtr koutput;
drmModeEncoderPtr *kencoders = NULL;
drmmode_output_private_ptr drmmode_output;
drmModePropertyPtr props;
+ drmModePropertyBlobPtr path_blob = NULL;
char name[32];
int i;
const char *s;
- koutput = drmModeGetConnector(drmmode->fd, drmmode->mode_res->connectors[num]);
+ koutput = drmModeGetConnector(drmmode->fd, mode_res->connectors[num]);
if (!koutput)
- return;
+ return 0;
+
+ for (i = 0; i < koutput->count_props; i++) {
+ props = drmModeGetProperty(drmmode->fd, koutput->props[i]);
+ if (props && (props->flags & DRM_MODE_PROP_BLOB)) {
+ if (!strcmp(props->name, "PATH")) {
+ path_blob = drmModeGetPropertyBlob(drmmode->fd, koutput->prop_values[i]);
+ drmModeFreeProperty(props);
+ break;
+ }
+ drmModeFreeProperty(props);
+ }
+ }
kencoders = calloc(sizeof(drmModeEncoderPtr), koutput->count_encoders);
if (!kencoders) {
@@ -1223,42 +1535,27 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dv
}
}
- if (koutput->connector_type >= NUM_OUTPUT_NAMES)
- snprintf(name, 32, "Unknown%d-%d", koutput->connector_type,
- koutput->connector_type_id - 1);
-#ifdef RADEON_PIXMAP_SHARING
- else if (pScrn->is_gpu)
- snprintf(name, 32, "%s-%d-%d",
- output_names[koutput->connector_type], pScrn->scrnIndex - GPU_SCREEN_OFFSET + 1,
- koutput->connector_type_id - 1);
-#endif
- else {
- /* need to do smart conversion here for compat with non-kms ATI driver */
- if (koutput->connector_type_id == 1) {
- switch(koutput->connector_type) {
- case DRM_MODE_CONNECTOR_DVII:
- case DRM_MODE_CONNECTOR_DVID:
- case DRM_MODE_CONNECTOR_DVIA:
- snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_dvi);
- (*num_dvi)++;
- break;
- case DRM_MODE_CONNECTOR_HDMIA:
- case DRM_MODE_CONNECTOR_HDMIB:
- snprintf(name, 32, "%s-%d", output_names[koutput->connector_type], *num_hdmi);
- (*num_hdmi)++;
- break;
- case DRM_MODE_CONNECTOR_VGA:
- case DRM_MODE_CONNECTOR_DisplayPort:
- snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
- koutput->connector_type_id - 1);
- break;
- default:
- snprintf(name, 32, "%s", output_names[koutput->connector_type]);
- break;
- }
- } else {
- snprintf(name, 32, "%s-%d", output_names[koutput->connector_type],
- koutput->connector_type_id - 1);
+ drmmode_create_name(pScrn, koutput, name, path_blob, num_dvi, num_hdmi);
+ if (path_blob)
+ drmModeFreePropertyBlob(path_blob);
+
+ if (path_blob && dynamic) {
+ /* See if we have an output with this name already
+ * and hook stuff up.
+ */
+ for (i = 0; i < xf86_config->num_output; i++) {
+ output = xf86_config->output[i];
+
+ if (strncmp(output->name, name, 32))
+ continue;
+
+ drmmode_output = output->driver_private;
+ drmmode_output->output_id = mode_res->connectors[num];
+ drmmode_output->mode_output = koutput;
+ for (i = 0; i < koutput->count_encoders; i++)
+ drmModeFreeEncoder(kencoders[i]);
+ free(kencoders);
+ return 0;
}
}
@@ -1267,7 +1564,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dv
if (!RADEONZaphodStringMatches(pScrn, s, name))
goto out_free_encoders;
} else {
- if (info->IsPrimary && (num != 0))
+ if (!info->IsSecondary && (num != 0))
goto out_free_encoders;
else if (info->IsSecondary && (num != 1))
goto out_free_encoders;
@@ -1285,7 +1582,7 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dv
goto out_free_encoders;
}
- drmmode_output->output_id = drmmode->mode_res->connectors[num];
+ drmmode_output->output_id = mode_res->connectors[num];
drmmode_output->mode_output = koutput;
drmmode_output->mode_encoders = kencoders;
drmmode_output->drmmode = drmmode;
@@ -1316,7 +1613,12 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num, int *num_dv
}
}
- return;
+ if (dynamic) {
+ output->randr_output = RROutputCreate(xf86ScrnToScreen(pScrn), output->name, strlen(output->name), output);
+ drmmode_output_create_resources(output);
+ }
+
+ return 1;
out_free_encoders:
if (kencoders){
for (i = 0; i < koutput->count_encoders; i++)
@@ -1324,7 +1626,7 @@ out_free_encoders:
free(kencoders);
}
drmModeFreeConnector(koutput);
-
+ return 0;
}
uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
@@ -1354,7 +1656,7 @@ uint32_t find_clones(ScrnInfoPtr scrn, xf86OutputPtr output)
static void
-drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
+drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode, drmModeResPtr mode_res)
{
int i, j;
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
@@ -1369,8 +1671,8 @@ drmmode_clones_init(ScrnInfoPtr scrn, drmmode_ptr drmmode)
for (j = 0; j < drmmode_output->mode_output->count_encoders; j++)
{
int k;
- for (k = 0; k < drmmode->mode_res->count_encoders; k++) {
- if (drmmode->mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id)
+ for (k = 0; k < mode_res->count_encoders; k++) {
+ if (mode_res->encoders[k] == drmmode_output->mode_encoders[j]->encoder_id)
drmmode_output->enc_mask |= (1 << k);
}
@@ -1488,6 +1790,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
ScreenPtr screen = xf86ScrnToScreen(scrn);
uint32_t old_fb_id;
int i, pitch, old_width, old_height, old_pitch;
+ int aligned_height;
uint32_t screen_size;
int cpp = info->pixel_bytes;
struct radeon_bo *front_bo;
@@ -1496,6 +1799,9 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
uint32_t tiling_flags = 0, base_align;
PixmapPtr ppix = screen->GetScreenPixmap(screen);
void *fb_shadow;
+ xRectangle rect;
+ Bool force;
+ GCPtr gc;
if (scrn->virtualX == width && scrn->virtualY == height)
return TRUE;
@@ -1506,7 +1812,7 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
if (front_bo)
radeon_bo_wait(front_bo);
- if (info->allowColorTiling) {
+ if (info->allowColorTiling && !info->shadow_primary) {
if (info->ChipFamily >= CHIP_FAMILY_R600) {
if (info->allowColorTiling2D) {
tiling_flags |= RADEON_TILING_MACRO;
@@ -1518,8 +1824,8 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
}
pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(scrn, cpp, tiling_flags)) * cpp;
- height = RADEON_ALIGN(height, drmmode_get_height_align(scrn, tiling_flags));
- screen_size = RADEON_ALIGN(pitch * height, RADEON_GPU_PAGE_SIZE);
+ 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));
@@ -1562,7 +1868,9 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
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;
- tiling_flags |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_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;
@@ -1587,7 +1895,10 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
scrn->virtualY = height;
scrn->displayWidth = pitch / cpp;
- info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align, RADEON_GEM_DOMAIN_VRAM, 0);
+ info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size, base_align,
+ info->shadow_primary ?
+ RADEON_GEM_DOMAIN_GTT :
+ RADEON_GEM_DOMAIN_VRAM, 0);
if (!info->front_bo)
goto fail;
@@ -1636,6 +1947,24 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
scrn->pixmapPrivate.ptr = ppix->devPrivate.ptr;
#endif
+ if (info->use_glamor)
+ radeon_glamor_create_screen_resources(scrn->pScreen);
+
+ /* Clear new buffer */
+ gc = GetScratchGC(ppix->drawable.depth, scrn->pScreen);
+ force = info->accel_state->force;
+ info->accel_state->force = TRUE;
+ ValidateGC(&ppix->drawable, gc);
+ rect.x = 0;
+ rect.y = 0;
+ rect.width = width;
+ rect.height = height;
+ (*gc->ops->PolyFillRect)(&ppix->drawable, gc, 1, &rect);
+ FreeScratchGC(gc);
+ info->accel_state->force = force;
+ radeon_cs_flush_indirect(scrn);
+ radeon_bo_wait(info->front_bo);
+
for (i = 0; i < xf86_config->num_crtc; i++) {
xf86CrtcPtr crtc = xf86_config->crtc[i];
@@ -1646,9 +1975,6 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
crtc->rotation, crtc->x, crtc->y);
}
- if (info->use_glamor)
- radeon_glamor_create_screen_resources(scrn->pScreen);
-
if (old_fb_id)
drmModeRmFB(drmmode->fd, old_fb_id);
if (old_front)
@@ -1674,45 +2000,55 @@ static const xf86CrtcConfigFuncsRec drmmode_xf86crtc_config_funcs = {
};
static void
-drmmode_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
+drmmode_flip_free(drmmode_flipevtcarrier_ptr flipcarrier)
+{
+ drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
+
+ free(flipcarrier);
+
+ if (--flipdata->flip_count > 0)
+ return;
+
+ free(flipdata);
+}
+
+static void
+drmmode_flip_abort(ScrnInfoPtr scrn, void *event_data)
{
- radeon_dri2_frame_event_handler(frame, tv_sec, tv_usec, event_data);
+ drmmode_flipevtcarrier_ptr flipcarrier = event_data;
+ drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
+
+ if (flipdata->flip_count == 1)
+ flipdata->abort(scrn, flipdata->event_data);
+
+ drmmode_flip_free(flipcarrier);
}
static void
-drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
+drmmode_flip_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, void *event_data)
{
drmmode_flipevtcarrier_ptr flipcarrier = event_data;
drmmode_flipdata_ptr flipdata = flipcarrier->flipdata;
- drmmode_ptr drmmode = flipdata->drmmode;
/* Is this the event whose info shall be delivered to higher level? */
if (flipcarrier->dispatch_me) {
/* Yes: Cache msc, ust for later delivery. */
flipdata->fe_frame = frame;
- flipdata->fe_tv_sec = tv_sec;
- flipdata->fe_tv_usec = tv_usec;
+ flipdata->fe_usec = usec;
}
- free(flipcarrier);
-
- /* Last crtc completed flip? */
- flipdata->flip_count--;
- if (flipdata->flip_count > 0)
- return;
- /* Release framebuffer */
- drmModeRmFB(drmmode->fd, flipdata->old_fb_id);
+ if (flipdata->flip_count == 1) {
+ /* Deliver cached msc, ust from reference crtc to flip event handler */
+ if (flipdata->event_data)
+ flipdata->handler(scrn, flipdata->fe_frame,
+ flipdata->fe_usec,
+ flipdata->event_data);
- if (flipdata->event_data == NULL)
- return;
-
- /* Deliver cached msc, ust from reference crtc to flip event handler */
- radeon_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec,
- flipdata->fe_tv_usec, flipdata->event_data);
+ /* Release framebuffer */
+ drmModeRmFB(flipdata->drmmode->fd, flipdata->old_fb_id);
+ }
- free(flipdata);
+ drmmode_flip_free(flipcarrier);
}
@@ -1729,26 +2065,51 @@ drm_wakeup_handler(pointer data, int err, pointer p)
Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
{
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
+ RADEONInfoPtr info = RADEONPTR(pScrn);
int i, num_dvi = 0, num_hdmi = 0;
+ drmModeResPtr mode_res;
+ unsigned int crtcs_needed = 0;
xf86CrtcConfigInit(pScrn, &drmmode_xf86crtc_config_funcs);
drmmode->scrn = pScrn;
drmmode->cpp = cpp;
- drmmode->mode_res = drmModeGetResources(drmmode->fd);
- if (!drmmode->mode_res)
+ mode_res = drmModeGetResources(drmmode->fd);
+ if (!mode_res)
return FALSE;
- xf86CrtcSetSizeRange(pScrn, 320, 200, drmmode->mode_res->max_width, drmmode->mode_res->max_height);
- for (i = 0; i < drmmode->mode_res->count_crtcs; i++)
- if (!xf86IsEntityShared(pScrn->entityList[0]) || pScrn->confScreen->device->screen == i)
- drmmode_crtc_init(pScrn, drmmode, i);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "Initializing outputs ...\n");
+ for (i = 0; i < mode_res->count_connectors; i++)
+ crtcs_needed += drmmode_output_init(pScrn, drmmode, mode_res,
+ i, &num_dvi, &num_hdmi, 0);
+ xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "%d crtcs needed for screen.\n", crtcs_needed);
+
+ 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;
+ }
- for (i = 0; i < drmmode->mode_res->count_connectors; i++)
- drmmode_output_init(pScrn, drmmode, i, &num_dvi, &num_hdmi);
+ 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++)
+ if (!xf86IsEntityShared(pScrn->entityList[0]) ||
+ (crtcs_needed && !(pRADEONEnt->assigned_crtcs & (1 << i))))
+ crtcs_needed -= drmmode_crtc_init(pScrn, drmmode, mode_res, i);
+
+ /* All ZaphodHeads outputs provided with matching crtcs? */
+ if (xf86IsEntityShared(pScrn->entityList[0]) && (crtcs_needed > 0))
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "%d ZaphodHeads crtcs unavailable. Some outputs will stay off.\n",
+ crtcs_needed);
/* workout clones */
- drmmode_clones_init(pScrn, drmmode);
+ drmmode_clones_init(pScrn, drmmode, mode_res);
#ifdef RADEON_PIXMAP_SHARING
xf86ProviderSetup(pScrn, NULL, "radeon");
@@ -1757,9 +2118,10 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
xf86InitialConfiguration(pScrn, TRUE);
drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
- drmmode->event_context.vblank_handler = drmmode_vblank_handler;
- drmmode->event_context.page_flip_handler = drmmode_flip_handler;
+ drmmode->event_context.vblank_handler = radeon_drm_queue_handler;
+ drmmode->event_context.page_flip_handler = radeon_drm_queue_handler;
+ drmModeFreeResources(mode_res);
return TRUE;
}
@@ -1828,13 +2190,12 @@ void drmmode_adjust_frame(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int x, int y)
}
}
-Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
+Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
+ Bool set_hw)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
int c;
- drmmode_copy_fb(pScrn, drmmode);
-
for (c = 0; c < config->num_crtc; c++) {
xf86CrtcPtr crtc = config->crtc[c];
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
@@ -1843,9 +2204,12 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
/* Skip disabled CRTCs */
if (!crtc->enabled) {
- drmmode_do_crtc_dpms(crtc, DPMSModeOff);
- drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
- 0, 0, 0, NULL, 0, NULL);
+ if (set_hw) {
+ drmmode_do_crtc_dpms(crtc, DPMSModeOff);
+ drmModeSetCrtc(drmmode->fd,
+ drmmode_crtc->mode_crtc->crtc_id,
+ 0, 0, 0, NULL, 0, NULL);
+ }
continue;
}
@@ -1878,9 +2242,18 @@ Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
crtc->desiredY = 0;
}
- if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
- crtc->desiredX, crtc->desiredY))
- return FALSE;
+ if (set_hw) {
+ if (!crtc->funcs->set_mode_major(crtc, &crtc->desiredMode, crtc->desiredRotation,
+ crtc->desiredX, crtc->desiredY))
+ return FALSE;
+ } else {
+ crtc->mode = crtc->desiredMode;
+ crtc->rotation = crtc->desiredRotation;
+ crtc->x = crtc->desiredX;
+ crtc->y = crtc->desiredY;
+ if (!xf86CrtcRotate(crtc))
+ return FALSE;
+ }
}
return TRUE;
}
@@ -1970,6 +2343,75 @@ Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn)
return TRUE;
}
+void
+radeon_mode_hotplug(ScrnInfoPtr scrn, drmmode_ptr drmmode)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ drmModeResPtr mode_res;
+ int i, j;
+ Bool found;
+ Bool changed = FALSE;
+
+ mode_res = drmModeGetResources(drmmode->fd);
+ if (!mode_res)
+ goto out;
+
+restart_destroy:
+ for (i = 0; i < config->num_output; i++) {
+ xf86OutputPtr output = config->output[i];
+ drmmode_output_private_ptr drmmode_output = output->driver_private;
+ found = FALSE;
+ for (j = 0; j < mode_res->count_connectors; j++) {
+ if (mode_res->connectors[j] == drmmode_output->output_id) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found)
+ continue;
+
+ drmModeFreeConnector(drmmode_output->mode_output);
+ drmmode_output->mode_output = NULL;
+ drmmode_output->output_id = -1;
+
+ changed = TRUE;
+ if (drmmode->delete_dp_12_displays) {
+ RROutputDestroy(output->randr_output);
+ xf86OutputDestroy(output);
+ goto restart_destroy;
+ }
+ }
+
+ /* find new output ids we don't have outputs for */
+ for (i = 0; i < mode_res->count_connectors; i++) {
+ found = FALSE;
+
+ for (j = 0; j < config->num_output; j++) {
+ xf86OutputPtr output = config->output[j];
+ drmmode_output_private_ptr drmmode_output;
+
+ drmmode_output = output->driver_private;
+ if (mode_res->connectors[i] == drmmode_output->output_id) {
+ found = TRUE;
+ break;
+ }
+ }
+ if (found)
+ continue;
+
+ changed = TRUE;
+ drmmode_output_init(scrn, drmmode, mode_res, i, NULL, NULL, 1);
+ }
+
+ if (changed) {
+ RRSetChanged(xf86ScrnToScreen(scrn));
+ RRTellChanged(xf86ScrnToScreen(scrn));
+ }
+
+ drmModeFreeResources(mode_res);
+out:
+ RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
+}
#ifdef HAVE_LIBUDEV
static void
drmmode_handle_uevents(int fd, void *closure)
@@ -1981,7 +2423,7 @@ drmmode_handle_uevents(int fd, void *closure)
if (!dev)
return;
- RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
+ radeon_mode_hotplug(scrn, drmmode);
udev_device_unref(dev);
}
#endif
@@ -2035,18 +2477,21 @@ void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
#endif
}
-Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id)
+Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
+ uint32_t new_front_handle, uint64_t id, void *data,
+ int ref_crtc_hw_id, radeon_drm_handler_proc handler,
+ radeon_drm_abort_proc abort)
{
RADEONInfoPtr info = RADEONPTR(scrn);
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
unsigned int pitch;
- int i, old_fb_id;
+ int i;
uint32_t tiling_flags = 0;
- int height, emitted = 0;
drmmode_flipdata_ptr flipdata;
- drmmode_flipevtcarrier_ptr flipcarrier;
+ drmmode_flipevtcarrier_ptr flipcarrier = NULL;
+ struct radeon_drm_queue_entry *drm_queue = NULL;
if (info->allowColorTiling) {
if (info->ChipFamily >= CHIP_FAMILY_R600)
@@ -2057,26 +2502,26 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
pitch = RADEON_ALIGN(scrn->displayWidth, drmmode_get_pitch_align(scrn, info->pixel_bytes, tiling_flags)) *
info->pixel_bytes;
- height = RADEON_ALIGN(scrn->virtualY, drmmode_get_height_align(scrn, tiling_flags));
if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
pitch = info->front_surface.level[0].pitch_bytes;
}
- /*
- * Create a new handle for the back buffer
- */
- old_fb_id = drmmode->fb_id;
- if (drmModeAddFB(drmmode->fd, scrn->virtualX, height,
- scrn->depth, scrn->bitsPerPixel, pitch,
- new_front->handle, &drmmode->fb_id))
- goto error_out;
-
flipdata = calloc(1, sizeof(drmmode_flipdata_rec));
if (!flipdata) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"flip queue: data alloc failed.\n");
- goto error_undo;
+ goto error;
}
+
+ /*
+ * Create a new handle for the back buffer
+ */
+ flipdata->old_fb_id = drmmode->fb_id;
+ if (drmModeAddFB(drmmode->fd, scrn->virtualX, scrn->virtualY,
+ scrn->depth, scrn->bitsPerPixel, pitch,
+ new_front_handle, &drmmode->fb_id))
+ goto error;
+
/*
* Queue flips on all enabled CRTCs
* Note that if/when we get per-CRTC buffers, we'll have to update this.
@@ -2089,6 +2534,8 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
flipdata->event_data = data;
flipdata->drmmode = drmmode;
+ flipdata->handler = handler;
+ flipdata->abort = abort;
for (i = 0; i < config->num_crtc; i++) {
if (!config->crtc[i]->enabled)
@@ -2101,9 +2548,7 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
if (!flipcarrier) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"flip queue: carrier alloc failed.\n");
- if (emitted == 0)
- free(flipdata);
- goto error_undo;
+ goto error;
}
/* Only the reference crtc will finally deliver its page flip
@@ -2112,28 +2557,44 @@ Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *dat
flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id);
flipcarrier->flipdata = flipdata;
+ drm_queue = radeon_drm_queue_alloc(scrn, client, id,
+ flipcarrier,
+ drmmode_flip_handler,
+ drmmode_flip_abort);
+ if (!drm_queue) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Allocating DRM queue event entry failed.\n");
+ goto error;
+ }
+
if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
- drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipcarrier)) {
+ drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT,
+ drm_queue)) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"flip queue failed: %s\n", strerror(errno));
- free(flipcarrier);
- if (emitted == 0)
- free(flipdata);
- goto error_undo;
+ goto error;
}
- emitted++;
+ flipcarrier = NULL;
+ drm_queue = NULL;
}
- flipdata->old_fb_id = old_fb_id;
- return TRUE;
+ if (flipdata->flip_count > 0)
+ return TRUE;
-error_undo:
- drmModeRmFB(drmmode->fd, drmmode->fb_id);
- drmmode->fb_id = old_fb_id;
+error:
+ if (flipdata && flipdata->flip_count <= 1) {
+ drmModeRmFB(drmmode->fd, drmmode->fb_id);
+ drmmode->fb_id = flipdata->old_fb_id;
+ }
+
+ if (drm_queue)
+ radeon_drm_abort_entry(drm_queue);
+ else if (flipcarrier)
+ drmmode_flip_abort(scrn, flipcarrier);
+ else if (flipdata && flipdata->flip_count <= 1)
+ free(flipdata);
-error_out:
xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
strerror(errno));
return FALSE;
}
-
diff --git a/driver/xf86-video-ati/src/drmmode_display.h b/driver/xf86-video-ati/src/drmmode_display.h
index 41e29f624..ab6c5908a 100644
--- a/driver/xf86-video-ati/src/drmmode_display.h
+++ b/driver/xf86-video-ati/src/drmmode_display.h
@@ -32,6 +32,7 @@
#include "libudev.h"
#endif
+#include "radeon_drm_queue.h"
#include "radeon_probe.h"
#ifndef DRM_CAP_TIMESTAMP_MONOTONIC
@@ -41,7 +42,6 @@
typedef struct {
int fd;
unsigned fb_id;
- drmModeResPtr mode_res;
drmModeFBPtr mode_fb;
int cpp;
struct radeon_bo_manager *bufmgr;
@@ -51,6 +51,12 @@ typedef struct {
InputHandlerProc uevent_handler;
#endif
drmEventContext event_context;
+ int count_crtcs;
+
+ Bool delete_dp_12_displays;
+
+ Bool dri2_flipping;
+ Bool present_flipping;
} drmmode_rec, *drmmode_ptr;
typedef struct {
@@ -59,8 +65,9 @@ typedef struct {
int flip_count;
void *event_data;
unsigned int fe_frame;
- unsigned int fe_tv_sec;
- unsigned int fe_tv_usec;
+ uint64_t fe_usec;
+ radeon_drm_handler_proc handler;
+ radeon_drm_abort_proc abort;
} drmmode_flipdata_rec, *drmmode_flipdata_ptr;
typedef struct {
@@ -68,20 +75,33 @@ typedef struct {
Bool dispatch_me;
} drmmode_flipevtcarrier_rec, *drmmode_flipevtcarrier_ptr;
+struct drmmode_scanout {
+ struct radeon_bo *bo;
+ PixmapPtr pixmap;
+ DamagePtr damage;
+ unsigned fb_id;
+ int width, height;
+};
+
typedef struct {
drmmode_ptr drmmode;
drmModeCrtcPtr mode_crtc;
int hw_id;
struct radeon_bo *cursor_bo;
- struct radeon_bo *rotate_bo;
- unsigned rotate_fb_id;
+ struct drmmode_scanout rotate;
+ struct drmmode_scanout scanout[2];
+ unsigned scanout_id;
+ Bool scanout_update_pending;
int dpms_mode;
CARD64 dpms_last_ust;
uint32_t dpms_last_seq;
int dpms_last_fps;
uint32_t interpolated_vblanks;
uint16_t lut_r[256], lut_g[256], lut_b[256];
- int scanout_pixmap_x;
+ int prime_pixmap_x;
+
+ /* Modeset needed for DPMS on */
+ Bool need_modeset;
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
typedef struct {
@@ -112,18 +132,28 @@ 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);
+extern Bool drmmode_set_desired_modes(ScrnInfoPtr pScrn, drmmode_ptr drmmode,
+ Bool set_hw);
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
extern void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode);
+#endif
extern Bool drmmode_setup_colormap(ScreenPtr pScreen, ScrnInfoPtr pScrn);
+extern void drmmode_scanout_free(ScrnInfoPtr scrn);
+
extern void drmmode_uevent_init(ScrnInfoPtr scrn, drmmode_ptr drmmode);
extern void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode);
+extern int drmmode_get_crtc_id(xf86CrtcPtr crtc);
extern int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling);
extern int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling);
extern int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling);
-Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id);
+Bool radeon_do_pageflip(ScrnInfoPtr scrn, ClientPtr client,
+ uint32_t new_front_handle, uint64_t id, void *data,
+ int ref_crtc_hw_id, radeon_drm_handler_proc handler,
+ radeon_drm_abort_proc abort);
+int drmmode_crtc_get_ust_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc);
int drmmode_get_current_ust(int drm_fd, CARD64 *ust);
#endif
diff --git a/driver/xf86-video-ati/src/evergreen_accel.c b/driver/xf86-video-ati/src/evergreen_accel.c
index 41ebc1a9f..43146bbfa 100644
--- a/driver/xf86-video-ati/src/evergreen_accel.c
+++ b/driver/xf86-video-ati/src/evergreen_accel.c
@@ -79,9 +79,9 @@ unsigned eg_tile_split(unsigned tile_split)
case 128: tile_split = 1; break;
case 256: tile_split = 2; break;
case 512: tile_split = 3; break;
+ default:
case 1024: tile_split = 4; break;
case 2048: tile_split = 5; break;
- default:
case 4096: tile_split = 6; break;
}
return tile_split;
diff --git a/driver/xf86-video-ati/src/pcidb/ati_pciids.csv b/driver/xf86-video-ati/src/pcidb/ati_pciids.csv
index 1c92f5b52..55d7b1dfd 100644
--- a/driver/xf86-video-ati/src/pcidb/ati_pciids.csv
+++ b/driver/xf86-video-ati/src/pcidb/ati_pciids.csv
@@ -693,6 +693,7 @@
"0x6610","OLAND_6610","OLAND",,,,,,"OLAND"
"0x6611","OLAND_6611","OLAND",,,,,,"OLAND"
"0x6613","OLAND_6613","OLAND",,,,,,"OLAND"
+"0x6617","OLAND_6617","OLAND",1,,,,,"OLAND"
"0x6620","OLAND_6620","OLAND",1,,,,,"OLAND"
"0x6621","OLAND_6621","OLAND",1,,,,,"OLAND"
"0x6623","OLAND_6623","OLAND",1,,,,,"OLAND"
@@ -713,6 +714,7 @@
"0x6658","BONAIRE_6658","BONAIRE",,,,,,"BONAIRE"
"0x665C","BONAIRE_665C","BONAIRE",,,,,,"BONAIRE"
"0x665D","BONAIRE_665D","BONAIRE",,,,,,"BONAIRE"
+"0x665F","BONAIRE_665F","BONAIRE",,,,,,"BONAIRE"
"0x9830","KABINI_9830","KABINI",1,1,,,1,"KABINI"
"0x9831","KABINI_9831","KABINI",,1,,,1,"KABINI"
"0x9832","KABINI_9832","KABINI",1,1,,,1,"KABINI"
diff --git a/driver/xf86-video-ati/src/radeon.h b/driver/xf86-video-ati/src/radeon.h
index 6123cc26a..e2fd41cfd 100644
--- a/driver/xf86-video-ati/src/radeon.h
+++ b/driver/xf86-video-ati/src/radeon.h
@@ -51,8 +51,6 @@
#include "exa.h"
-#include "radeon_glamor.h"
-
/* Exa and Cursor Support */
#include "xf86Cursor.h"
@@ -92,6 +90,8 @@
#include "simple_list.h"
#include "atipcirename.h"
+struct _SyncFence;
+
#ifndef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif
@@ -148,7 +148,12 @@ typedef enum {
OPTION_ACCELMETHOD,
OPTION_EXA_VSYNC,
OPTION_ZAPHOD_HEADS,
- OPTION_SWAPBUFFERS_WAIT
+ OPTION_SWAPBUFFERS_WAIT,
+ OPTION_DELETE_DP12,
+ OPTION_DRI3,
+ OPTION_DRI,
+ OPTION_SHADOW_PRIMARY,
+ OPTION_TEAR_FREE,
} RADEONOpts;
@@ -241,6 +246,47 @@ typedef enum {
#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;
+
+ uint32_t tiling_flags;
+
+ /* GEM handle for glamor-only pixmaps shared via DRI3 */
+ Bool handle_valid;
+ uint32_t handle;
+};
+
+#if HAS_DEVPRIVATEKEYREC
+extern DevPrivateKeyRec glamor_pixmap_index;
+#else
+extern int glamor_pixmap_index;
+#endif
+
+static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap)
+{
+#if HAS_DEVPRIVATEKEYREC
+ return dixGetPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
+#else
+ return dixLookupPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
+#endif
+}
+
+static inline void radeon_set_pixmap_private(PixmapPtr pixmap, struct radeon_pixmap *priv)
+{
+ dixSetPrivate(&pixmap->devPrivates, &glamor_pixmap_index, priv);
+}
+
+#endif /* USE_GLAMOR */
+
+
struct radeon_exa_pixmap_priv {
struct radeon_bo *bo;
uint32_t tiling_flags;
@@ -412,6 +458,9 @@ typedef struct {
void (*BlockHandler)(BLOCKHANDLER_ARGS_DECL);
+ void (*CreateFence) (ScreenPtr pScreen, struct _SyncFence *pFence,
+ Bool initially_triggered);
+
int pix24bpp; /* Depth of pixmap for 24bpp fb */
Bool dac6bits; /* Use 6 bit DAC? */
@@ -419,15 +468,19 @@ typedef struct {
Bool directRenderingEnabled;
struct radeon_dri2 dri2;
- Bool accelDFS;
/* accel */
Bool RenderAccel; /* Render */
Bool allowColorTiling;
Bool allowColorTiling2D;
+ uint_fast32_t gpu_flushed;
+ uint_fast32_t gpu_synced;
struct radeon_accel_state *accel_state;
+ PixmapPtr fbcon_pixmap;
Bool accelOn;
Bool use_glamor;
+ Bool shadow_primary;
+ Bool tear_free;
Bool exa_pixmaps;
Bool exa_force_create;
XF86ModReqInfo exaReq;
@@ -442,9 +495,11 @@ typedef struct {
DisplayModePtr currentMode;
CreateScreenResourcesProcPtr CreateScreenResources;
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
+ CreateWindowProcPtr CreateWindow;
+#endif
Bool IsSecondary;
- Bool IsPrimary;
Bool r600_shadow_fb;
void *fb_shadow;
@@ -483,6 +538,31 @@ typedef struct {
/* cursor size */
int cursor_w;
int cursor_h;
+
+#ifdef USE_GLAMOR
+ struct {
+ CreateGCProcPtr SavedCreateGC;
+ RegionPtr (*SavedCopyArea)(DrawablePtr, DrawablePtr, GCPtr, int, int,
+ int, int, int, int);
+ void (*SavedPolyFillRect)(DrawablePtr, GCPtr, int, xRectangle*);
+ CloseScreenProcPtr SavedCloseScreen;
+ GetImageProcPtr SavedGetImage;
+ GetSpansProcPtr SavedGetSpans;
+ CreatePixmapProcPtr SavedCreatePixmap;
+ DestroyPixmapProcPtr SavedDestroyPixmap;
+ CopyWindowProcPtr SavedCopyWindow;
+ ChangeWindowAttributesProcPtr SavedChangeWindowAttributes;
+ BitmapToRegionProcPtr SavedBitmapToRegion;
+#ifdef RENDER
+ CompositeProcPtr SavedComposite;
+ TrianglesProcPtr SavedTriangles;
+ GlyphsProcPtr SavedGlyphs;
+ TrapezoidsProcPtr SavedTrapezoids;
+ AddTrapsProcPtr SavedAddTraps;
+ UnrealizeGlyphProcPtr SavedUnrealizeGlyph;
+#endif
+ } glamor;
+#endif /* USE_GLAMOR */
} RADEONInfoRec, *RADEONInfoPtr;
/* radeon_accel.c */
@@ -512,6 +592,20 @@ extern Bool RADEONGetDatatypeBpp(int bpp, uint32_t *type);
extern Bool RADEONGetPixmapOffsetPitch(PixmapPtr pPix,
uint32_t *pitch_offset);
+/* radeon_dri3.c */
+Bool radeon_dri3_screen_init(ScreenPtr screen);
+
+/* radeon_kms.c */
+void radeon_scanout_update_handler(ScrnInfoPtr scrn, uint32_t frame,
+ uint64_t usec, void *event_data);
+
+/* radeon_present.c */
+Bool radeon_present_screen_init(ScreenPtr screen);
+
+/* radeon_sync.c */
+extern Bool radeon_sync_init(ScreenPtr screen);
+extern void radeon_sync_close(ScreenPtr screen);
+
/* radeon_video.c */
extern void RADEONInitVideo(ScreenPtr pScreen);
extern void RADEONResetVideo(ScrnInfoPtr pScrn);
@@ -630,7 +724,7 @@ static inline struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
{
struct radeon_exa_pixmap_priv *driver_priv;
driver_priv = exaGetPixmapDriverPrivate(pPix);
- return driver_priv->bo;
+ return driver_priv ? driver_priv->bo : NULL;
}
return NULL;
@@ -786,6 +880,7 @@ static __inline__ void RADEON_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn)
}
enum {
+ RADEON_CREATE_PIXMAP_SCANOUT = 0x02000000,
RADEON_CREATE_PIXMAP_DRI2 = 0x04000000,
RADEON_CREATE_PIXMAP_TILING_MICRO_SQUARE = 0x08000000,
RADEON_CREATE_PIXMAP_TILING_MACRO = 0x10000000,
diff --git a/driver/xf86-video-ati/src/radeon_accel.c b/driver/xf86-video-ati/src/radeon_accel.c
index 8eff5c52a..1def2a3fb 100644
--- a/driver/xf86-video-ati/src/radeon_accel.c
+++ b/driver/xf86-video-ati/src/radeon_accel.c
@@ -78,6 +78,7 @@
#include <assert.h>
/* Driver data structures */
#include "radeon.h"
+#include "radeon_glamor.h"
#include "radeon_reg.h"
#include "r600_reg.h"
#include "radeon_probe.h"
diff --git a/driver/xf86-video-ati/src/radeon_bo_helper.c b/driver/xf86-video-ati/src/radeon_bo_helper.c
index ed964d7b0..ce964e0ea 100644
--- a/driver/xf86-video-ati/src/radeon_bo_helper.c
+++ b/driver/xf86-video-ati/src/radeon_bo_helper.c
@@ -25,6 +25,7 @@
#endif
#include "radeon.h"
+#include "radeon_glamor.h"
#ifdef RADEON_PIXMAP_SHARING
#include "radeon_bo_gem.h"
@@ -87,12 +88,15 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH)
tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO;
+ if ((usage_hint == CREATE_PIXMAP_USAGE_BACKING_PIXMAP &&
+ info->shadow_primary)
#ifdef CREATE_PIXMAP_USAGE_SHARED
- if ((usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED) {
+ || (usage_hint & 0xffff) == CREATE_PIXMAP_USAGE_SHARED
+#endif
+ ) {
tiling = 0;
domain = RADEON_GEM_DOMAIN_GTT;
}
-#endif
}
/* Small pixmaps must not be macrotiled on R300, hw cannot sample them
@@ -164,7 +168,8 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
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;
- tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_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:
@@ -187,6 +192,87 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
return bo;
}
+/* 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);
+#ifdef USE_GLAMOR
+ ScreenPtr screen = pixmap->drawable.pScreen;
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(screen));
+#endif
+
+ if (bo) {
+ *handle = bo->handle;
+ return TRUE;
+ }
+
+#ifdef USE_GLAMOR
+ if (info->use_glamor) {
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+ CARD16 stride;
+ CARD32 size;
+ int fd, r;
+
+ if (!priv) {
+ priv = calloc(1, sizeof(*priv));
+ radeon_set_pixmap_private(pixmap, priv);
+ }
+
+ if (priv->handle_valid) {
+ *handle = priv->handle;
+ return TRUE;
+ }
+
+ fd = glamor_fd_from_pixmap(screen, pixmap, &stride, &size);
+ if (fd < 0)
+ return FALSE;
+
+ r = drmPrimeFDToHandle(info->dri2.drm_fd, fd, &priv->handle);
+ close(fd);
+ if (r == 0) {
+ struct drm_radeon_gem_set_tiling args = { .handle = priv->handle };
+
+ priv->handle_valid = TRUE;
+ *handle = priv->handle;
+
+ if (drmCommandWriteRead(info->dri2.drm_fd,
+ DRM_RADEON_GEM_GET_TILING, &args,
+ sizeof(args)) == 0)
+ priv->tiling_flags = args.tiling_flags;
+
+ return TRUE;
+ }
+ }
+#endif
+
+ return FALSE;
+}
+
+uint32_t radeon_get_pixmap_tiling_flags(PixmapPtr pPix)
+{
+#ifdef USE_GLAMOR
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen));
+
+ if (info->use_glamor) {
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pPix);
+
+ if (!priv || (!priv->bo && !priv->handle_valid)) {
+ uint32_t handle;
+
+ radeon_get_pixmap_handle(pPix, &handle);
+ priv = radeon_get_pixmap_private(pPix);
+ }
+
+ return priv ? priv->tiling_flags : 0;
+ } else
+#endif
+ {
+ struct radeon_exa_pixmap_priv *driver_priv;
+ driver_priv = exaGetPixmapDriverPrivate(pPix);
+ return driver_priv ? driver_priv->tiling_flags : 0;
+ }
+}
+
#ifdef RADEON_PIXMAP_SHARING
Bool radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p)
@@ -200,6 +286,21 @@ 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)
{
@@ -215,7 +316,22 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
memset(surface, 0, sizeof(struct radeon_surface));
+ radeon_set_pixmap_bo(ppix, bo);
+
if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
+ 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;
+ }
surface->npix_x = ppix->drawable.width;
surface->npix_y = ppix->drawable.height;
@@ -229,7 +345,17 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
/* 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_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)) {
return FALSE;
}
@@ -241,7 +367,6 @@ Bool radeon_set_shared_pixmap_backing(PixmapPtr ppix, void *fd_handle,
surface->level[0].pitch_bytes = ppix->devKind;
surface->level[0].nblk_x = ppix->devKind / surface->bpe;
}
- radeon_set_pixmap_bo(ppix, bo);
close(ihandle);
/* we have a reference from the alloc and one from set pixmap bo,
diff --git a/driver/xf86-video-ati/src/radeon_bo_helper.h b/driver/xf86-video-ati/src/radeon_bo_helper.h
index 9c3d73f97..d4a4ee018 100644
--- a/driver/xf86-video-ati/src/radeon_bo_helper.h
+++ b/driver/xf86-video-ati/src/radeon_bo_helper.h
@@ -29,6 +29,12 @@ radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
struct radeon_surface *new_surface, uint32_t *new_tiling);
extern Bool
+radeon_get_pixmap_handle(PixmapPtr pixmap, uint32_t *handle);
+
+extern uint32_t
+radeon_get_pixmap_tiling_flags(PixmapPtr pPix);
+
+extern Bool
radeon_share_pixmap_backing(struct radeon_bo *bo, void **handle_p);
extern Bool
diff --git a/driver/xf86-video-ati/src/radeon_chipinfo_gen.h b/driver/xf86-video-ati/src/radeon_chipinfo_gen.h
index 40577c9eb..91ef8df8a 100644
--- a/driver/xf86-video-ati/src/radeon_chipinfo_gen.h
+++ b/driver/xf86-video-ati/src/radeon_chipinfo_gen.h
@@ -612,6 +612,7 @@ static RADEONCardInfo RADEONCards[] = {
{ 0x6610, CHIP_FAMILY_OLAND, 0, 0, 0, 0, 0 },
{ 0x6611, CHIP_FAMILY_OLAND, 0, 0, 0, 0, 0 },
{ 0x6613, CHIP_FAMILY_OLAND, 0, 0, 0, 0, 0 },
+ { 0x6617, CHIP_FAMILY_OLAND, 1, 0, 0, 0, 0 },
{ 0x6620, CHIP_FAMILY_OLAND, 1, 0, 0, 0, 0 },
{ 0x6621, CHIP_FAMILY_OLAND, 1, 0, 0, 0, 0 },
{ 0x6623, CHIP_FAMILY_OLAND, 1, 0, 0, 0, 0 },
@@ -632,6 +633,7 @@ static RADEONCardInfo RADEONCards[] = {
{ 0x6658, CHIP_FAMILY_BONAIRE, 0, 0, 0, 0, 0 },
{ 0x665C, CHIP_FAMILY_BONAIRE, 0, 0, 0, 0, 0 },
{ 0x665D, CHIP_FAMILY_BONAIRE, 0, 0, 0, 0, 0 },
+ { 0x665F, CHIP_FAMILY_BONAIRE, 0, 0, 0, 0, 0 },
{ 0x9830, CHIP_FAMILY_KABINI, 1, 1, 0, 0, 1 },
{ 0x9831, CHIP_FAMILY_KABINI, 0, 1, 0, 0, 1 },
{ 0x9832, CHIP_FAMILY_KABINI, 1, 1, 0, 0, 1 },
diff --git a/driver/xf86-video-ati/src/radeon_chipset_gen.h b/driver/xf86-video-ati/src/radeon_chipset_gen.h
index e3f23b6c9..5d6d2334e 100644
--- a/driver/xf86-video-ati/src/radeon_chipset_gen.h
+++ b/driver/xf86-video-ati/src/radeon_chipset_gen.h
@@ -612,6 +612,7 @@ SymTabRec RADEONChipsets[] = {
{ PCI_CHIP_OLAND_6610, "OLAND" },
{ PCI_CHIP_OLAND_6611, "OLAND" },
{ PCI_CHIP_OLAND_6613, "OLAND" },
+ { PCI_CHIP_OLAND_6617, "OLAND" },
{ PCI_CHIP_OLAND_6620, "OLAND" },
{ PCI_CHIP_OLAND_6621, "OLAND" },
{ PCI_CHIP_OLAND_6623, "OLAND" },
@@ -632,6 +633,7 @@ SymTabRec RADEONChipsets[] = {
{ PCI_CHIP_BONAIRE_6658, "BONAIRE" },
{ PCI_CHIP_BONAIRE_665C, "BONAIRE" },
{ PCI_CHIP_BONAIRE_665D, "BONAIRE" },
+ { PCI_CHIP_BONAIRE_665F, "BONAIRE" },
{ PCI_CHIP_KABINI_9830, "KABINI" },
{ PCI_CHIP_KABINI_9831, "KABINI" },
{ PCI_CHIP_KABINI_9832, "KABINI" },
diff --git a/driver/xf86-video-ati/src/radeon_dri2.c b/driver/xf86-video-ati/src/radeon_dri2.c
index 9a9918b0f..d30bbd0bd 100644
--- a/driver/xf86-video-ati/src/radeon_dri2.c
+++ b/driver/xf86-video-ati/src/radeon_dri2.c
@@ -40,25 +40,13 @@
#include <fcntl.h>
#include <errno.h>
+#include "radeon_bo_helper.h"
#include "radeon_version.h"
-
-#if HAVE_LIST_H
-#include "list.h"
-#if !HAVE_XORG_LIST
-#define xorg_list list
-#define xorg_list_init list_init
-#define xorg_list_add list_add
-#define xorg_list_del list_del
-#define xorg_list_for_each_entry list_for_each_entry
-#endif
-#endif
-
+#include "radeon_list.h"
#include "radeon_bo_gem.h"
-#if DRI2INFOREC_VERSION >= 4 && HAVE_LIST_H
-#define USE_DRI2_SCHEDULING
-#endif
+#include <xf86Priv.h>
#if DRI2INFOREC_VERSION >= 9
#define USE_DRI2_PRIME
@@ -66,9 +54,7 @@
#define FALLBACK_SWAP_DELAY 16
-#ifdef USE_GLAMOR
-#include <glamor.h>
-#endif
+#include "radeon_glamor.h"
typedef DRI2BufferPtr BufferPtr;
@@ -79,6 +65,28 @@ struct dri2_buffer_priv {
};
+struct dri2_window_priv {
+ xf86CrtcPtr crtc;
+ int vblank_delta;
+};
+
+#if HAS_DEVPRIVATEKEYREC
+
+static DevPrivateKeyRec dri2_window_private_key_rec;
+#define dri2_window_private_key (&dri2_window_private_key_rec)
+
+#else
+
+static int dri2_window_private_key_index;
+DevPrivateKey dri2_window_private_key = &dri2_window_private_key_index;
+
+#endif /* HAS_DEVPRIVATEKEYREC */
+
+#define get_dri2_window_priv(window) \
+ ((struct dri2_window_priv*) \
+ dixLookupPrivate(&(window)->devPrivates, dri2_window_private_key))
+
+
static PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
{
if (drawable->type == DRAWABLE_PIXMAP)
@@ -125,21 +133,43 @@ static PixmapPtr fixup_glamor(DrawablePtr drawable, PixmapPtr pixmap)
/* And redirect the pixmap to the new bo (for 3D). */
glamor_egl_exchange_buffers(old, pixmap);
radeon_set_pixmap_private(old, priv);
- screen->DestroyPixmap(pixmap);
old->refcnt++;
screen->ModifyPixmapHeader(old,
old->drawable.width,
old->drawable.height,
0, 0,
- priv->stride,
+ pixmap->devKind,
NULL);
+ old->devPrivate.ptr = NULL;
+
+ screen->DestroyPixmap(pixmap);
#endif /* USE_GLAMOR*/
return old;
}
+/* Get GEM flink name for a pixmap */
+static Bool
+radeon_get_flink_name(RADEONInfoPtr info, PixmapPtr pixmap, uint32_t *name)
+{
+ struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap);
+ struct drm_gem_flink flink;
+
+ if (bo)
+ return radeon_gem_get_kernel_name(bo, name) == 0;
+
+ if (radeon_get_pixmap_handle(pixmap, &flink.handle)) {
+ if (drmIoctl(info->dri2.drm_fd, DRM_IOCTL_GEM_FLINK, &flink) != 0)
+ return FALSE;
+
+ *name = flink.name;
+ return TRUE;
+ }
+
+ return FALSE;
+}
static BufferPtr
radeon_dri2_create_buffer2(ScreenPtr pScreen,
@@ -151,8 +181,7 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen,
RADEONInfoPtr info = RADEONPTR(pScrn);
BufferPtr buffers;
struct dri2_buffer_priv *privates;
- PixmapPtr pixmap, depth_pixmap;
- struct radeon_bo *bo;
+ PixmapPtr pixmap;
int flags;
unsigned front_width;
uint32_t tiling = 0;
@@ -180,25 +209,23 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen,
cpp = drawable->bitsPerPixel / 8;
}
- pixmap = pScreen->GetScreenPixmap(pScreen);
- front_width = pixmap->drawable.width;
+ front_width = pScreen->GetScreenPixmap(pScreen)->drawable.width;
- pixmap = depth_pixmap = NULL;
+ pixmap = NULL;
if (attachment == DRI2BufferFrontLeft) {
+ uint32_t handle;
+
pixmap = get_drawable_pixmap(drawable);
if (pScreen != pixmap->drawable.pScreen)
pixmap = NULL;
- else if (info->use_glamor && !radeon_get_pixmap_bo(pixmap)) {
+ else if (info->use_glamor && !radeon_get_pixmap_handle(pixmap, &handle)) {
is_glamor_pixmap = TRUE;
aligned_width = pixmap->drawable.width;
height = pixmap->drawable.height;
pixmap = NULL;
} else
pixmap->refcnt++;
- } else if (attachment == DRI2BufferStencil && depth_pixmap) {
- pixmap = depth_pixmap;
- pixmap->refcnt++;
}
if (!pixmap && (is_glamor_pixmap || attachment != DRI2BufferFrontLeft)) {
@@ -283,10 +310,6 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen,
if (buffers == NULL)
goto error;
- if (attachment == DRI2BufferDepth) {
- depth_pixmap = pixmap;
- }
-
if (pixmap) {
if (!info->use_glamor) {
info->exa_force_create = TRUE;
@@ -300,8 +323,7 @@ radeon_dri2_create_buffer2(ScreenPtr pScreen,
if (is_glamor_pixmap)
pixmap = fixup_glamor(drawable, pixmap);
- bo = radeon_get_pixmap_bo(pixmap);
- if (!bo || radeon_gem_get_kernel_name(bo, &buffers->name) != 0)
+ if (!radeon_get_flink_name(info, pixmap, &buffers->name))
goto error;
}
@@ -490,8 +512,6 @@ radeon_dri2_copy_region(DrawablePtr pDraw, RegionPtr pRegion,
pDstBuffer, pSrcBuffer);
}
-#ifdef USE_DRI2_SCHEDULING
-
enum DRI2FrameEventType {
DRI2_SWAP,
DRI2_FLIP,
@@ -502,67 +522,20 @@ typedef struct _DRI2FrameEvent {
XID drawable_id;
ClientPtr client;
enum DRI2FrameEventType type;
- int frame;
+ unsigned frame;
xf86CrtcPtr crtc;
+ OsTimerPtr timer;
+ struct radeon_drm_queue_entry *drm_queue;
/* for swaps & flips only */
DRI2SwapEventPtr event_complete;
void *event_data;
DRI2BufferPtr front;
DRI2BufferPtr back;
-
- Bool valid;
-
- struct xorg_list link;
} DRI2FrameEventRec, *DRI2FrameEventPtr;
-typedef struct _DRI2ClientEvents {
- struct xorg_list reference_list;
-} DRI2ClientEventsRec, *DRI2ClientEventsPtr;
-
-#if HAS_DEVPRIVATEKEYREC
-
static int DRI2InfoCnt;
-static DevPrivateKeyRec DRI2ClientEventsPrivateKeyRec;
-#define DRI2ClientEventsPrivateKey (&DRI2ClientEventsPrivateKeyRec)
-
-#else
-
-static int DRI2ClientEventsPrivateKeyIndex;
-DevPrivateKey DRI2ClientEventsPrivateKey = &DRI2ClientEventsPrivateKeyIndex;
-
-#endif /* HAS_DEVPRIVATEKEYREC */
-
-#define GetDRI2ClientEvents(pClient) ((DRI2ClientEventsPtr) \
- dixLookupPrivate(&(pClient)->devPrivates, DRI2ClientEventsPrivateKey))
-
-static int
-ListAddDRI2ClientEvents(ClientPtr client, struct xorg_list *entry)
-{
- DRI2ClientEventsPtr pClientPriv;
- pClientPriv = GetDRI2ClientEvents(client);
-
- if (!pClientPriv) {
- return BadAlloc;
- }
-
- xorg_list_add(entry, &pClientPriv->reference_list);
- return 0;
-}
-
-static void
-ListDelDRI2ClientEvents(ClientPtr client, struct xorg_list *entry)
-{
- DRI2ClientEventsPtr pClientPriv;
- pClientPriv = GetDRI2ClientEvents(client);
-
- if (!pClientPriv) {
- return;
- }
- xorg_list_del(entry);
-}
-
static void
radeon_dri2_ref_buffer(BufferPtr buffer)
{
@@ -582,52 +555,159 @@ radeon_dri2_unref_buffer(BufferPtr buffer)
static void
radeon_dri2_client_state_changed(CallbackListPtr *ClientStateCallback, pointer data, pointer calldata)
{
- DRI2ClientEventsPtr pClientEventsPriv;
- DRI2FrameEventPtr ref;
NewClientInfoRec *clientinfo = calldata;
ClientPtr pClient = clientinfo->client;
- pClientEventsPriv = GetDRI2ClientEvents(pClient);
switch (pClient->clientState) {
- case ClientStateInitial:
- xorg_list_init(&pClientEventsPriv->reference_list);
- break;
- case ClientStateRunning:
- break;
-
case ClientStateRetained:
case ClientStateGone:
- if (pClientEventsPriv) {
- xorg_list_for_each_entry(ref, &pClientEventsPriv->reference_list, link) {
- ref->valid = FALSE;
- radeon_dri2_unref_buffer(ref->front);
- radeon_dri2_unref_buffer(ref->back);
- }
- }
+ radeon_drm_abort_client(pClient);
break;
default:
break;
}
}
+/*
+ * Get current frame count delta for the specified drawable and CRTC
+ */
+static uint32_t radeon_get_msc_delta(DrawablePtr pDraw, xf86CrtcPtr crtc)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ if (pDraw && pDraw->type == DRAWABLE_WINDOW)
+ return drmmode_crtc->interpolated_vblanks +
+ get_dri2_window_priv((WindowPtr)pDraw)->vblank_delta;
+
+ return drmmode_crtc->interpolated_vblanks;
+}
+
+/*
+ * Get current frame count and timestamp of the specified CRTC
+ */
+static Bool radeon_dri2_get_crtc_msc(xf86CrtcPtr crtc, CARD64 *ust, CARD64 *msc)
+{
+ if (!radeon_crtc_is_enabled(crtc) ||
+ drmmode_crtc_get_ust_msc(crtc, ust, msc) != Success) {
+ /* CRTC is not running, extrapolate MSC and timestamp */
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ ScrnInfoPtr scrn = crtc->scrn;
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ CARD64 now, delta_t, delta_seq;
+
+ if (!drmmode_crtc->dpms_last_ust)
+ return FALSE;
+
+ if (drmmode_get_current_ust(info->dri2.drm_fd, &now) != 0) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "%s cannot get current time\n", __func__);
+ return FALSE;
+ }
+
+ delta_t = now - drmmode_crtc->dpms_last_ust;
+ delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
+ delta_seq /= 1000000;
+ *ust = drmmode_crtc->dpms_last_ust;
+ delta_t = delta_seq * 1000000;
+ delta_t /= drmmode_crtc->dpms_last_fps;
+ *ust += delta_t;
+ *msc = drmmode_crtc->dpms_last_seq;
+ *msc += delta_seq;
+ }
+
+ return TRUE;
+}
+
static
xf86CrtcPtr radeon_dri2_drawable_crtc(DrawablePtr pDraw, Bool consider_disabled)
{
ScreenPtr pScreen = pDraw->pScreen;
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
- xf86CrtcPtr crtc;
+ xf86CrtcPtr crtc = radeon_pick_best_crtc(pScrn, consider_disabled,
+ pDraw->x, pDraw->x + pDraw->width,
+ pDraw->y, pDraw->y + pDraw->height);
- crtc = radeon_pick_best_crtc(pScrn, consider_disabled,
- pDraw->x,
- pDraw->x + pDraw->width,
- pDraw->y,
- pDraw->y + pDraw->height);
+ if (crtc && pDraw->type == DRAWABLE_WINDOW) {
+ struct dri2_window_priv *priv = get_dri2_window_priv((WindowPtr)pDraw);
- /* Make sure the CRTC is valid and this is the real front buffer */
- if (crtc != NULL && !crtc->rotatedData)
- return crtc;
- else
- return NULL;
+ if (priv->crtc && priv->crtc != crtc) {
+ CARD64 ust, mscold, mscnew;
+
+ if (radeon_dri2_get_crtc_msc(priv->crtc, &ust, &mscold) &&
+ radeon_dri2_get_crtc_msc(crtc, &ust, &mscnew))
+ priv->vblank_delta += mscold - mscnew;
+ }
+
+ priv->crtc = crtc;
+ }
+
+ return crtc;
+}
+
+static void
+radeon_dri2_flip_event_abort(ScrnInfoPtr scrn, void *event_data)
+{
+ free(event_data);
+}
+
+static void
+radeon_dri2_flip_event_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec,
+ void *event_data)
+{
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ DRI2FrameEventPtr flip = event_data;
+ unsigned tv_sec, tv_usec;
+ DrawablePtr drawable;
+ ScreenPtr screen;
+ int status;
+ PixmapPtr pixmap;
+
+ status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
+ M_ANY, DixWriteAccess);
+ if (status != Success)
+ goto abort;
+
+ if (!flip->crtc)
+ goto abort;
+ frame += radeon_get_msc_delta(drawable, flip->crtc);
+
+ screen = scrn->pScreen;
+ pixmap = screen->GetScreenPixmap(screen);
+ xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
+ "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n",
+ __func__, __LINE__, flip, pixmap->drawable.width, pixmap->devKind, pixmap->devKind/4);
+
+ tv_sec = usec / 1000000;
+ tv_usec = usec % 1000000;
+
+ /* We assume our flips arrive in order, so we don't check the frame */
+ switch (flip->type) {
+ case DRI2_SWAP:
+ /* Check for too small vblank count of pageflip completion, taking wraparound
+ * into account. This usually means some defective kms pageflip completion,
+ * causing wrong (msc, ust) return values and possible visual corruption.
+ */
+ if ((frame < flip->frame) && (flip->frame - frame < 5)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "%s: Pageflip completion event has impossible msc %u < target_msc %u\n",
+ __func__, frame, flip->frame);
+ /* All-Zero values signal failure of (msc, ust) timestamping to client. */
+ frame = tv_sec = tv_usec = 0;
+ }
+
+ DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
+ DRI2_FLIP_COMPLETE, flip->event_complete,
+ flip->event_data);
+ info->drmmode.dri2_flipping = FALSE;
+ break;
+ default:
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: unknown vblank event received\n", __func__);
+ /* Unknown type */
+ break;
+ }
+
+abort:
+ radeon_dri2_flip_event_abort(scrn, event_data);
}
static Bool
@@ -636,6 +716,7 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
DRI2BufferPtr back, DRI2SwapEventPtr func,
void *data, unsigned int target_msc)
{
+ RADEONInfoPtr info = RADEONPTR(scrn);
struct dri2_buffer_priv *back_priv;
struct radeon_bo *bo;
DRI2FrameEventPtr flip_info;
@@ -662,26 +743,31 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
back_priv = back->driverPrivate;
bo = radeon_get_pixmap_bo(back_priv->pixmap);
- return radeon_do_pageflip(scrn, bo, flip_info, ref_crtc_hw_id);
+ if (radeon_do_pageflip(scrn, client, bo->handle,
+ RADEON_DRM_QUEUE_ID_DEFAULT, flip_info,
+ ref_crtc_hw_id,
+ radeon_dri2_flip_event_handler,
+ radeon_dri2_flip_event_abort)) {
+ info->drmmode.dri2_flipping = TRUE;
+ return TRUE;
+ }
+
+ return FALSE;
}
static Bool
update_front(DrawablePtr draw, DRI2BufferPtr front)
{
- int r;
PixmapPtr pixmap;
RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(draw->pScreen));
struct dri2_buffer_priv *priv = front->driverPrivate;
- struct radeon_bo *bo;
pixmap = get_drawable_pixmap(draw);
pixmap->refcnt++;
if (!info->use_glamor)
exaMoveInPixmap(pixmap);
- bo = radeon_get_pixmap_bo(pixmap);
- r = radeon_gem_get_kernel_name(bo, &front->name);
- if (r) {
+ if (!radeon_get_flink_name(info, pixmap, &front->name)) {
(*draw->pScreen->DestroyPixmap)(pixmap);
return FALSE;
}
@@ -734,8 +820,11 @@ static Bool
can_flip(ScrnInfoPtr pScrn, DrawablePtr draw,
DRI2BufferPtr front, DRI2BufferPtr back)
{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
return draw->type == DRAWABLE_WINDOW &&
- RADEONPTR(pScrn)->allowPageFlip &&
+ info->allowPageFlip &&
+ !info->drmmode.present_flipping &&
pScrn->vtSema &&
DRI2CanFlip(draw) &&
can_exchange(pScrn, draw, front, back);
@@ -784,31 +873,36 @@ radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPt
DamageRegionProcessPending(&front_priv->pixmap->drawable);
}
-void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
+static void radeon_dri2_frame_event_abort(ScrnInfoPtr scrn, void *event_data)
+{
+ DRI2FrameEventPtr event = event_data;
+
+ TimerCancel(event->timer);
+ TimerFree(event->timer);
+ radeon_dri2_unref_buffer(event->front);
+ radeon_dri2_unref_buffer(event->back);
+ free(event);
+}
+
+static void radeon_dri2_frame_event_handler(ScrnInfoPtr scrn, uint32_t seq,
+ uint64_t usec, void *event_data)
{
DRI2FrameEventPtr event = event_data;
DrawablePtr drawable;
- ScreenPtr screen;
- ScrnInfoPtr scrn;
int status;
int swap_type;
BoxRec box;
RegionRec region;
- if (!event->valid)
+ if (!event->crtc)
goto cleanup;
status = dixLookupDrawable(&drawable, event->drawable_id, serverClient,
M_ANY, DixWriteAccess);
if (status != Success)
goto cleanup;
- if (!event->crtc)
- goto cleanup;
- frame += radeon_get_interpolated_vblanks(event->crtc);
- screen = drawable->pScreen;
- scrn = xf86ScreenToScrn(screen);
+ seq += radeon_get_msc_delta(drawable, event->crtc);
switch (event->type) {
case DRI2_FLIP:
@@ -840,12 +934,14 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
swap_type = DRI2_BLIT_COMPLETE;
}
- DRI2SwapComplete(event->client, drawable, frame, tv_sec, tv_usec,
- swap_type, event->event_complete, event->event_data);
+ DRI2SwapComplete(event->client, drawable, seq, usec / 1000000,
+ usec % 1000000, swap_type, event->event_complete,
+ event->event_data);
break;
case DRI2_WAITMSC:
- DRI2WaitMSCComplete(event->client, drawable, frame, tv_sec, tv_usec);
+ DRI2WaitMSCComplete(event->client, drawable, seq, usec / 1000000,
+ usec % 1000000);
break;
default:
/* Unknown type */
@@ -855,12 +951,7 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
}
cleanup:
- if (event->valid) {
- radeon_dri2_unref_buffer(event->front);
- radeon_dri2_unref_buffer(event->back);
- ListDelDRI2ClientEvents(event->client, &event->link);
- }
- free(event);
+ radeon_dri2_frame_event_abort(scrn, event_data);
}
drmVBlankSeqType radeon_populate_vbl_request_type(xf86CrtcPtr crtc)
@@ -898,8 +989,6 @@ CARD32 radeon_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 *target_msc,
int nominal_frame_rate = drmmode_crtc->dpms_last_fps;
CARD64 last_vblank_ust = drmmode_crtc->dpms_last_ust;
uint32_t last_vblank_seq = drmmode_crtc->dpms_last_seq;
- int interpolated_vblanks = drmmode_crtc->interpolated_vblanks;
- int target_seq;
CARD64 now, target_time, delta_t;
int64_t d, delta_seq;
int ret;
@@ -916,16 +1005,15 @@ CARD32 radeon_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 *target_msc,
*target_msc = 0;
return FALLBACK_SWAP_DELAY;
}
- target_seq = (int)*target_msc - interpolated_vblanks;
- delta_seq = (int64_t)target_seq - (int64_t)last_vblank_seq;
+ delta_seq = *target_msc - last_vblank_seq;
delta_seq *= 1000000;
target_time = last_vblank_ust;
target_time += delta_seq / nominal_frame_rate;
d = target_time - now;
if (d < 0) {
/* we missed the event, adjust target_msc, do the divisor magic */
- CARD64 current_msc;
- current_msc = last_vblank_seq + interpolated_vblanks;
+ CARD64 current_msc = last_vblank_seq;
+
delta_t = now - last_vblank_ust;
delta_seq = delta_t * nominal_frame_rate;
current_msc += delta_seq / 1000000;
@@ -938,8 +1026,7 @@ CARD32 radeon_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 *target_msc,
if ((current_msc % divisor) >= remainder)
*target_msc += divisor;
*target_msc &= 0xffffffff;
- target_seq = (int)*target_msc - interpolated_vblanks;
- delta_seq = (int64_t)target_seq - (int64_t)last_vblank_seq;
+ delta_seq = *target_msc - last_vblank_seq;
delta_seq *= 1000000;
target_time = last_vblank_ust;
target_time += delta_seq / nominal_frame_rate;
@@ -960,16 +1047,11 @@ CARD32 radeon_dri2_extrapolate_msc_delay(xf86CrtcPtr crtc, CARD64 *target_msc,
}
/*
- * Get current frame count and frame count timestamp, based on drawable's
- * crtc.
+ * Get current interpolated frame count and frame count timestamp, based on
+ * drawable's crtc.
*/
static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
{
- ScreenPtr screen = draw->pScreen;
- ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
- RADEONInfoPtr info = RADEONPTR(scrn);
- drmVBlank vbl;
- int ret;
xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE);
/* Drawable not displayed, make up a value */
@@ -978,47 +1060,12 @@ static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
*msc = 0;
return TRUE;
}
- if (radeon_crtc_is_enabled(crtc)) {
- /* CRTC is running, read vblank counter and timestamp */
- vbl.request.type = DRM_VBLANK_RELATIVE;
- vbl.request.type |= radeon_populate_vbl_request_type(crtc);
- vbl.request.sequence = 0;
-
- ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
- if (ret) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "get vblank counter failed: %s\n", strerror(errno));
- return FALSE;
- }
- *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
- *msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc);
- *msc &= 0xffffffff;
- } else {
- /* CRTC is not running, extrapolate MSC and timestamp */
- drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- CARD64 now, delta_t, delta_seq;
+ if (!radeon_dri2_get_crtc_msc(crtc, ust, msc))
+ return FALSE;
- if (!drmmode_crtc->dpms_last_ust)
- return FALSE;
- ret = drmmode_get_current_ust(info->dri2.drm_fd, &now);
- if (ret) {
- xf86DrvMsg(scrn->scrnIndex, X_ERROR,
- "%s cannot get current time\n", __func__);
- return FALSE;
- }
- delta_t = now - drmmode_crtc->dpms_last_ust;
- delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
- delta_seq /= 1000000;
- *ust = drmmode_crtc->dpms_last_ust;
- delta_t = delta_seq * 1000000;
- delta_t /= drmmode_crtc->dpms_last_fps;
- *ust += delta_t;
- *msc = drmmode_crtc->dpms_last_seq;
- *msc += drmmode_crtc->interpolated_vblanks;
- *msc += delta_seq;
- *msc &= 0xffffffff;
- }
+ *msc += radeon_get_msc_delta(draw, crtc);
+ *msc &= 0xffffffff;
return TRUE;
}
@@ -1026,17 +1073,13 @@ static
CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
{
DRI2FrameEventPtr event_info = (DRI2FrameEventPtr)data;
- DrawablePtr drawable;
- ScreenPtr screen;
+ xf86CrtcPtr crtc = event_info->crtc;
ScrnInfoPtr scrn;
RADEONInfoPtr info;
- int status;
CARD64 drm_now;
int ret;
- unsigned int tv_sec, tv_usec;
CARD64 delta_t, delta_seq, frame;
drmmode_crtc_private_ptr drmmode_crtc;
- TimerFree(timer);
/*
* This is emulated event, so its time is current time, which we
@@ -1047,28 +1090,26 @@ CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
*/
if (!event_info->crtc) {
ErrorF("%s no crtc\n", __func__);
- radeon_dri2_frame_event_handler(0, 0, 0, data);
+ if (event_info->drm_queue)
+ radeon_drm_abort_entry(event_info->drm_queue);
+ else
+ radeon_dri2_frame_event_abort(NULL, data);
return 0;
}
- status = dixLookupDrawable(&drawable, event_info->drawable_id, serverClient,
- M_ANY, DixWriteAccess);
- if (status != Success) {
- ErrorF("%s cannot lookup drawable\n", __func__);
- radeon_dri2_frame_event_handler(0, 0, 0, data);
- return 0;
- }
- screen = drawable->pScreen;
- scrn = xf86ScreenToScrn(screen);
+
+ scrn = crtc->scrn;
info = RADEONPTR(scrn);
ret = drmmode_get_current_ust(info->dri2.drm_fd, &drm_now);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"%s cannot get current time\n", __func__);
- radeon_dri2_frame_event_handler(0, 0, 0, data);
+ if (event_info->drm_queue)
+ radeon_drm_queue_handler(info->dri2.drm_fd, 0, 0, 0,
+ event_info->drm_queue);
+ else
+ radeon_dri2_frame_event_handler(scrn, 0, 0, data);
return 0;
}
- tv_sec = (unsigned int)(drm_now / 1000000);
- tv_usec = (unsigned int)(drm_now - (CARD64)tv_sec * 1000000);
/*
* calculate the frame number from current time
* that would come from CRTC if it were running
@@ -1078,20 +1119,22 @@ CARD32 radeon_dri2_deferred_event(OsTimerPtr timer, CARD32 now, pointer data)
delta_seq = delta_t * drmmode_crtc->dpms_last_fps;
delta_seq /= 1000000;
frame = (CARD64)drmmode_crtc->dpms_last_seq + delta_seq;
- frame &= 0xffffffff;
- radeon_dri2_frame_event_handler((unsigned int)frame, tv_sec, tv_usec, data);
+ if (event_info->drm_queue)
+ radeon_drm_queue_handler(info->dri2.drm_fd, frame, drm_now / 1000000,
+ drm_now % 1000000, event_info->drm_queue);
+ else
+ radeon_dri2_frame_event_handler(scrn, frame, drm_now, data);
return 0;
}
static
-void radeon_dri2_schedule_event(CARD32 delay, pointer arg)
+void radeon_dri2_schedule_event(CARD32 delay, DRI2FrameEventPtr event_info)
{
- OsTimerPtr timer;
-
- timer = TimerSet(NULL, 0, delay, radeon_dri2_deferred_event, arg);
+ event_info->timer = TimerSet(NULL, 0, delay, radeon_dri2_deferred_event,
+ event_info);
if (delay == 0) {
CARD32 now = GetTimeInMillis();
- radeon_dri2_deferred_event(timer, now, arg);
+ radeon_dri2_deferred_event(event_info->timer, now, event_info);
}
}
@@ -1109,7 +1152,9 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
RADEONInfoPtr info = RADEONPTR(scrn);
DRI2FrameEventPtr wait_info = NULL;
+ struct radeon_drm_queue_entry *wait = NULL;
xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE);
+ uint32_t msc_delta;
drmVBlank vbl;
int ret;
CARD64 current_msc;
@@ -1124,6 +1169,8 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
if (crtc == NULL)
goto out_complete;
+ msc_delta = radeon_get_msc_delta(draw, crtc);
+
wait_info = calloc(1, sizeof(DRI2FrameEventRec));
if (!wait_info)
goto out_complete;
@@ -1131,26 +1178,17 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
wait_info->drawable_id = draw->id;
wait_info->client = client;
wait_info->type = DRI2_WAITMSC;
- wait_info->valid = TRUE;
wait_info->crtc = crtc;
- if (ListAddDRI2ClientEvents(client, &wait_info->link)) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "add events to client private failed.\n");
- free(wait_info);
- wait_info = NULL;
- goto out_complete;
- }
-
/*
* CRTC is in DPMS off state, calculate wait time from current time,
* target_msc and last vblank time/sequence when CRTC was turned off
*/
if (!radeon_crtc_is_enabled(crtc)) {
CARD32 delay;
+ target_msc -= msc_delta;
delay = radeon_dri2_extrapolate_msc_delay(crtc, &target_msc,
divisor, remainder);
- wait_info->frame = target_msc;
radeon_dri2_schedule_event(delay, wait_info);
DRI2BlockClient(client, draw);
return TRUE;
@@ -1167,9 +1205,19 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
goto out_complete;
}
- current_msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc);
+ current_msc = vbl.reply.sequence + msc_delta;
current_msc &= 0xffffffff;
+ wait = radeon_drm_queue_alloc(scrn, client, RADEON_DRM_QUEUE_ID_DEFAULT,
+ wait_info, radeon_dri2_frame_event_handler,
+ radeon_dri2_frame_event_abort);
+ if (!wait) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Allocating DRM queue event entry failed.\n");
+ goto out_complete;
+ }
+ wait_info->drm_queue = wait;
+
/*
* If divisor is zero, or current_msc is smaller than target_msc,
* we just need to make sure target_msc passes before waking up the
@@ -1186,9 +1234,8 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
target_msc = current_msc;
vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
vbl.request.type |= radeon_populate_vbl_request_type(crtc);
- vbl.request.sequence = target_msc;
- vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc);
- vbl.request.signal = (unsigned long)wait_info;
+ vbl.request.sequence = target_msc - msc_delta;
+ vbl.request.signal = (unsigned long)wait;
ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1196,8 +1243,6 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
goto out_complete;
}
- wait_info->frame = vbl.reply.sequence;
- wait_info->frame += radeon_get_interpolated_vblanks(crtc);
DRI2BlockClient(client, draw);
return TRUE;
}
@@ -1210,7 +1255,7 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
vbl.request.type |= radeon_populate_vbl_request_type(crtc);
vbl.request.sequence = current_msc - (current_msc % divisor) +
- remainder;
+ remainder - msc_delta;
/*
* If calculated remainder is larger than requested remainder,
@@ -1220,9 +1265,8 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
*/
if ((current_msc % divisor) >= remainder)
vbl.request.sequence += divisor;
- vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc);
- vbl.request.signal = (unsigned long)wait_info;
+ vbl.request.signal = (unsigned long)wait;
ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
@@ -1230,79 +1274,16 @@ static int radeon_dri2_schedule_wait_msc(ClientPtr client, DrawablePtr draw,
goto out_complete;
}
- wait_info->frame = vbl.reply.sequence;
- wait_info->frame += radeon_get_interpolated_vblanks(crtc);
DRI2BlockClient(client, draw);
return TRUE;
out_complete:
- if (wait_info) {
- ListDelDRI2ClientEvents(wait_info->client, &wait_info->link);
- free(wait_info);
- }
- DRI2WaitMSCComplete(client, draw, target_msc, 0, 0);
+ if (wait_info)
+ radeon_dri2_deferred_event(NULL, 0, wait_info);
return TRUE;
}
-void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
-{
- DRI2FrameEventPtr flip = event_data;
- DrawablePtr drawable;
- ScreenPtr screen;
- ScrnInfoPtr scrn;
- int status;
- PixmapPtr pixmap;
-
- status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
- M_ANY, DixWriteAccess);
- if (status != Success) {
- free(flip);
- return;
- }
- if (!flip->crtc) {
- free(flip);
- return;
- }
- frame += radeon_get_interpolated_vblanks(flip->crtc);
-
- screen = drawable->pScreen;
- scrn = xf86ScreenToScrn(screen);
-
- pixmap = screen->GetScreenPixmap(screen);
- xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
- "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n",
- __func__, __LINE__, flip, pixmap->drawable.width, pixmap->devKind, pixmap->devKind/4);
-
- /* We assume our flips arrive in order, so we don't check the frame */
- switch (flip->type) {
- case DRI2_SWAP:
- /* Check for too small vblank count of pageflip completion, taking wraparound
- * into account. This usually means some defective kms pageflip completion,
- * causing wrong (msc, ust) return values and possible visual corruption.
- */
- if ((frame < flip->frame) && (flip->frame - frame < 5)) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "%s: Pageflip completion event has impossible msc %d < target_msc %d\n",
- __func__, frame, flip->frame);
- /* All-Zero values signal failure of (msc, ust) timestamping to client. */
- frame = tv_sec = tv_usec = 0;
- }
-
- DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
- DRI2_FLIP_COMPLETE, flip->event_complete,
- flip->event_data);
- break;
- default:
- xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: unknown vblank event received\n", __func__);
- /* Unknown type */
- break;
- }
-
- free(flip);
-}
-
/*
* ScheduleSwap is responsible for requesting a DRM vblank event for the
* appropriate frame.
@@ -1333,10 +1314,11 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
RADEONInfoPtr info = RADEONPTR(scrn);
xf86CrtcPtr crtc = radeon_dri2_drawable_crtc(draw, TRUE);
+ uint32_t msc_delta;
drmVBlank vbl;
int ret, flip = 0;
DRI2FrameEventPtr swap_info = NULL;
- enum DRI2FrameEventType swap_type = DRI2_SWAP;
+ struct radeon_drm_queue_entry *swap;
CARD64 current_msc;
BoxRec box;
RegionRec region;
@@ -1358,25 +1340,30 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
if (crtc == NULL)
goto blit_fallback;
+ msc_delta = radeon_get_msc_delta(draw, crtc);
+
swap_info = calloc(1, sizeof(DRI2FrameEventRec));
if (!swap_info)
goto blit_fallback;
+ swap_info->type = DRI2_SWAP;
swap_info->drawable_id = draw->id;
swap_info->client = client;
swap_info->event_complete = func;
swap_info->event_data = data;
swap_info->front = front;
swap_info->back = back;
- swap_info->valid = TRUE;
swap_info->crtc = crtc;
- if (ListAddDRI2ClientEvents(client, &swap_info->link)) {
+
+ swap = radeon_drm_queue_alloc(scrn, client, RADEON_DRM_QUEUE_ID_DEFAULT,
+ swap_info, radeon_dri2_frame_event_handler,
+ radeon_dri2_frame_event_abort);
+ if (!swap) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "add events to client private failed.\n");
- free(swap_info);
- swap_info = NULL;
+ "Allocating DRM queue entry failed.\n");
goto blit_fallback;
}
+ swap_info->drm_queue = swap;
/*
* CRTC is in DPMS off state, fallback to blit, but calculate
@@ -1385,9 +1372,11 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
*/
if (!radeon_crtc_is_enabled(crtc)) {
CARD32 delay;
+ *target_msc -= msc_delta;
delay = radeon_dri2_extrapolate_msc_delay(crtc, target_msc,
divisor, remainder);
- swap_info->frame = *target_msc;
+ *target_msc += msc_delta;
+ *target_msc &= 0xffffffff;
radeon_dri2_schedule_event(delay, swap_info);
return TRUE;
}
@@ -1401,23 +1390,19 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"first get vblank counter failed: %s\n",
strerror(errno));
- *target_msc = 0;
- radeon_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
- return TRUE;
+ goto blit_fallback;
}
- current_msc = vbl.reply.sequence + radeon_get_interpolated_vblanks(crtc);
+ current_msc = vbl.reply.sequence + msc_delta;
current_msc &= 0xffffffff;
/* Flips need to be submitted one frame before */
if (can_flip(scrn, draw, front, back)) {
- swap_type = DRI2_FLIP;
+ swap_info->type = DRI2_FLIP;
flip = 1;
}
- swap_info->type = swap_type;
-
- /* Correct target_msc by 'flip' if swap_type == DRI2_FLIP.
+ /* Correct target_msc by 'flip' if swap_info->type == DRI2_FLIP.
* Do it early, so handling of different timing constraints
* for divisor, remainder and msc vs. target_msc works.
*/
@@ -1446,21 +1431,17 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
if (current_msc >= *target_msc)
*target_msc = current_msc;
- vbl.request.sequence = *target_msc;
- vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc);
- vbl.request.signal = (unsigned long)swap_info;
+ vbl.request.sequence = *target_msc - msc_delta;
+ vbl.request.signal = (unsigned long)swap;
ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"divisor 0 get vblank counter failed: %s\n",
strerror(errno));
- *target_msc = 0;
- radeon_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
- return TRUE;
+ goto blit_fallback;
}
- *target_msc = vbl.reply.sequence + flip;
- *target_msc += radeon_get_interpolated_vblanks(crtc);
+ *target_msc = vbl.reply.sequence + flip + msc_delta;
swap_info->frame = *target_msc;
return TRUE;
@@ -1477,7 +1458,7 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
vbl.request.type |= radeon_populate_vbl_request_type(crtc);
vbl.request.sequence = current_msc - (current_msc % divisor) +
- remainder;
+ remainder - msc_delta;
/*
* If the calculated deadline vbl.request.sequence is smaller than
@@ -1492,53 +1473,49 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
*/
if (vbl.request.sequence <= current_msc)
vbl.request.sequence += divisor;
- vbl.request.sequence -= radeon_get_interpolated_vblanks(crtc);
/* Account for 1 frame extra pageflip delay if flip > 0 */
vbl.request.sequence -= flip;
- vbl.request.signal = (unsigned long)swap_info;
+ vbl.request.signal = (unsigned long)swap;
ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
if (ret) {
xf86DrvMsg(scrn->scrnIndex, X_WARNING,
"final get vblank counter failed: %s\n",
strerror(errno));
- *target_msc = 0;
- radeon_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
- return TRUE;
+ goto blit_fallback;
}
/* Adjust returned value for 1 fame pageflip offset of flip > 0 */
- *target_msc = vbl.reply.sequence + flip;
- *target_msc += radeon_get_interpolated_vblanks(crtc);
+ *target_msc = vbl.reply.sequence + flip + msc_delta;
+ *target_msc &= 0xffffffff;
swap_info->frame = *target_msc;
return TRUE;
blit_fallback:
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = draw->width;
- box.y2 = draw->height;
- REGION_INIT(pScreen, &region, &box, 0);
+ if (swap_info) {
+ swap_info->type = DRI2_SWAP;
+ radeon_dri2_schedule_event(FALLBACK_SWAP_DELAY, swap_info);
+ } else {
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = draw->width;
+ box.y2 = draw->height;
+ REGION_INIT(pScreen, &region, &box, 0);
- radeon_dri2_copy_region(draw, &region, front, back);
+ radeon_dri2_copy_region(draw, &region, front, back);
- DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
- if (swap_info) {
- ListDelDRI2ClientEvents(swap_info->client, &swap_info->link);
- free(swap_info);
- }
+ DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
- radeon_dri2_unref_buffer(front);
- radeon_dri2_unref_buffer(back);
+ radeon_dri2_unref_buffer(front);
+ radeon_dri2_unref_buffer(back);
+ }
*target_msc = 0; /* offscreen, so zero out target vblank count */
return TRUE;
}
-#endif /* USE_DRI2_SCHEDULING */
-
Bool
radeon_dri2_screen_init(ScreenPtr pScreen)
@@ -1546,10 +1523,8 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
RADEONInfoPtr info = RADEONPTR(pScrn);
DRI2InfoRec dri2_info = { 0 };
-#ifdef USE_DRI2_SCHEDULING
const char *driverNames[2];
Bool scheduling_works = TRUE;
-#endif
if (!info->dri2.available)
return FALSE;
@@ -1574,14 +1549,13 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
dri2_info.DestroyBuffer = radeon_dri2_destroy_buffer;
dri2_info.CopyRegion = radeon_dri2_copy_region;
-#ifdef USE_DRI2_SCHEDULING
if (info->dri2.pKernelDRMVersion->version_minor < 4) {
xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "You need a newer kernel for "
"sync extension\n");
scheduling_works = FALSE;
}
- if (scheduling_works && info->drmmode.mode_res->count_crtcs > 2) {
+ if (scheduling_works && info->drmmode.count_crtcs > 2) {
#ifdef DRM_CAP_VBLANK_HIGH_CRTC
uint64_t cap_value;
@@ -1608,31 +1582,32 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
dri2_info.ScheduleWaitMSC = radeon_dri2_schedule_wait_msc;
dri2_info.numDrivers = RADEON_ARRAY_SIZE(driverNames);
dri2_info.driverNames = driverNames;
- driverNames[0] = driverNames[1] = dri2_info.driverName;
+ driverNames[0] = dri2_info.driverName;
+
+ if (info->ChipFamily >= CHIP_FAMILY_R300)
+ driverNames[1] = driverNames[0];
+ else
+ driverNames[1] = NULL; /* no VDPAU support */
if (DRI2InfoCnt == 0) {
#if HAS_DIXREGISTERPRIVATEKEY
- if (!dixRegisterPrivateKey(DRI2ClientEventsPrivateKey,
- PRIVATE_CLIENT, sizeof(DRI2ClientEventsRec))) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 registering "
- "private key to client failed\n");
- return FALSE;
- }
+ if (!dixRegisterPrivateKey(dri2_window_private_key,
+ PRIVATE_WINDOW,
+ sizeof(struct dri2_window_priv))) {
#else
- if (!dixRequestPrivate(DRI2ClientEventsPrivateKey,
- sizeof(DRI2ClientEventsRec))) {
- xf86DrvMsg(pScrn->scrnIndex, X_WARNING, "DRI2 requesting "
- "private key to client failed\n");
+ if (!dixRequestPrivate(dri2_window_private_key,
+ sizeof(struct dri2_window_priv))) {
+#endif
+ xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
+ "Failed to get DRI2 window private\n");
return FALSE;
}
-#endif
AddCallback(&ClientStateCallback, radeon_dri2_client_state_changed, 0);
}
DRI2InfoCnt++;
}
-#endif
#if DRI2INFOREC_VERSION >= 9
dri2_info.version = 9;
@@ -1650,10 +1625,8 @@ void radeon_dri2_close_screen(ScreenPtr pScreen)
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
RADEONInfoPtr info = RADEONPTR(pScrn);
-#ifdef USE_DRI2_SCHEDULING
if (--DRI2InfoCnt == 0)
DeleteCallback(&ClientStateCallback, radeon_dri2_client_state_changed, 0);
-#endif
DRI2CloseScreen(pScreen);
drmFree(info->dri2.device_name);
diff --git a/driver/xf86-video-ati/src/radeon_dri2.h b/driver/xf86-video-ati/src/radeon_dri2.h
index 37d46f3d0..9ba47c78f 100644
--- a/driver/xf86-video-ati/src/radeon_dri2.h
+++ b/driver/xf86-video-ati/src/radeon_dri2.h
@@ -43,48 +43,11 @@ struct radeon_dri2 {
Bool radeon_dri2_screen_init(ScreenPtr pScreen);
void radeon_dri2_close_screen(ScreenPtr pScreen);
-int drmmode_get_crtc_id(xf86CrtcPtr crtc);
-void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data);
-void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data);
-
#else
static inline Bool radeon_dri2_screen_init(ScreenPtr pScreen) { return FALSE; }
static inline void radeon_dri2_close_screen(ScreenPtr pScreen) {}
-static inline void
-radeon_dri2_dummy_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data,
- const char *name)
-{
- static Bool warned;
-
- if (!warned) {
- ErrorF("%s called but DRI2 disabled at build time\n", name);
- warned = TRUE;
- }
-
- free(event_data);
-}
-
-static inline void
-radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
-{
- radeon_dri2_dummy_event_handler(frame, tv_sec, tv_usec, event_data,
- __func__);
-}
-
-static inline void
-radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
-{
- radeon_dri2_dummy_event_handler(frame, tv_sec, tv_usec, event_data,
- __func__);
-}
-
#endif
#endif /* RADEON_DRI2_H */
diff --git a/driver/xf86-video-ati/src/radeon_dri3.c b/driver/xf86-video-ati/src/radeon_dri3.c
new file mode 100644
index 000000000..1415a0df7
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_dri3.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright © 2013-2014 Intel Corporation
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "radeon.h"
+
+#ifdef HAVE_DRI3_H
+
+#include "radeon_bo_gem.h"
+#include "radeon_glamor.h"
+#include "dri3.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+
+static int
+radeon_dri3_open(ScreenPtr screen, RRProviderPtr provider, int *out)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ drm_magic_t magic;
+ int fd;
+
+ fd = open(info->dri2.device_name, O_RDWR | O_CLOEXEC);
+ if (fd < 0)
+ return BadAlloc;
+
+ /* Before FD passing in the X protocol with DRI3 (and increased
+ * security of rendering with per-process address spaces on the
+ * GPU), the kernel had to come up with a way to have the server
+ * decide which clients got to access the GPU, which was done by
+ * each client getting a unique (magic) number from the kernel,
+ * passing it to the server, and the server then telling the
+ * kernel which clients were authenticated for using the device.
+ *
+ * Now that we have FD passing, the server can just set up the
+ * authentication on its own and hand the prepared FD off to the
+ * client.
+ */
+ if (drmGetMagic(fd, &magic) < 0) {
+ if (errno == EACCES) {
+ /* Assume that we're on a render node, and the fd is
+ * already as authenticated as it should be.
+ */
+ *out = fd;
+ return Success;
+ } else {
+ close(fd);
+ return BadMatch;
+ }
+ }
+
+ if (drmAuthMagic(info->dri2.drm_fd, magic) < 0) {
+ close(fd);
+ return BadMatch;
+ }
+
+ *out = fd;
+ return Success;
+}
+
+static PixmapPtr radeon_dri3_pixmap_from_fd(ScreenPtr screen,
+ int fd,
+ CARD16 width,
+ CARD16 height,
+ CARD16 stride,
+ CARD8 depth,
+ CARD8 bpp)
+{
+ PixmapPtr pixmap;
+
+#ifdef USE_GLAMOR
+ /* Avoid generating a GEM flink name if possible */
+ if (RADEONPTR(xf86ScreenToScrn(screen))->use_glamor) {
+ pixmap = glamor_pixmap_from_fd(screen, fd, width, height,
+ stride, depth, bpp);
+ if (pixmap) {
+ struct radeon_pixmap *priv =
+ calloc(1, sizeof(struct radeon_pixmap));
+
+ if (priv) {
+ radeon_set_pixmap_private(pixmap, priv);
+ return pixmap;
+ }
+
+ screen->DestroyPixmap(pixmap);
+ }
+ }
+#endif
+
+ if (depth < 8)
+ return NULL;
+
+ switch (bpp) {
+ case 8:
+ case 16:
+ case 32:
+ break;
+ default:
+ return NULL;
+ }
+
+ pixmap = screen->CreatePixmap(screen, 0, 0, depth, RADEON_CREATE_PIXMAP_DRI2);
+ if (!pixmap)
+ return NULL;
+
+ if (!screen->ModifyPixmapHeader(pixmap, width, height, 0, bpp, stride,
+ NULL))
+ goto free_pixmap;
+
+ if (screen->SetSharedPixmapBacking(pixmap, (void*)(intptr_t)fd))
+ return pixmap;
+
+free_pixmap:
+ fbDestroyPixmap(pixmap);
+ return NULL;
+}
+
+static int radeon_dri3_fd_from_pixmap(ScreenPtr screen,
+ PixmapPtr pixmap,
+ CARD16 *stride,
+ CARD32 *size)
+{
+ struct radeon_bo *bo;
+ int fd;
+
+ bo = radeon_get_pixmap_bo(pixmap);
+ if (!bo) {
+#ifdef USE_GLAMOR
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ if (info->use_glamor)
+ return glamor_fd_from_pixmap(screen, pixmap, stride, size);
+#endif
+
+ exaMoveInPixmap(pixmap);
+ bo = radeon_get_pixmap_bo(pixmap);
+ if (!bo)
+ return -1;
+ }
+
+ if (pixmap->devKind > UINT16_MAX)
+ return -1;
+
+ if (radeon_gem_prime_share_bo(bo, &fd) < 0)
+ return -1;
+
+ *stride = pixmap->devKind;
+ *size = bo->size;
+ return fd;
+}
+
+static dri3_screen_info_rec radeon_dri3_screen_info = {
+ .version = 0,
+
+ .open = radeon_dri3_open,
+ .pixmap_from_fd = radeon_dri3_pixmap_from_fd,
+ .fd_from_pixmap = radeon_dri3_fd_from_pixmap
+};
+
+Bool
+radeon_dri3_screen_init(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+
+ if (!dri3_screen_init(screen, &radeon_dri3_screen_info)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "dri3_screen_init failed\n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+#else /* !HAVE_DRI3_H */
+
+Bool
+radeon_dri3_screen_init(ScreenPtr screen)
+{
+ xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+ "Can't initialize DRI3 because dri3.h not available at "
+ "build time\n");
+
+ return FALSE;
+}
+
+#endif
diff --git a/driver/xf86-video-ati/src/radeon_drm_queue.c b/driver/xf86-video-ati/src/radeon_drm_queue.c
new file mode 100644
index 000000000..5e54ef8bb
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_drm_queue.c
@@ -0,0 +1,181 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xorg-server.h>
+
+#include "radeon.h"
+#include "radeon_drm_queue.h"
+#include "radeon_list.h"
+
+
+struct radeon_drm_queue_entry {
+ struct xorg_list list;
+ uint64_t id;
+ void *data;
+ ClientPtr client;
+ ScrnInfoPtr scrn;
+ radeon_drm_handler_proc handler;
+ radeon_drm_abort_proc abort;
+};
+
+static int radeon_drm_queue_refcnt;
+static struct xorg_list radeon_drm_queue;
+
+
+/*
+ * Handle a DRM event
+ */
+void
+radeon_drm_queue_handler(int fd, unsigned int frame, unsigned int sec,
+ unsigned int usec, void *user_ptr)
+{
+ struct radeon_drm_queue_entry *user_data = user_ptr;
+ struct radeon_drm_queue_entry *e, *tmp;
+
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+ if (e == user_data) {
+ xorg_list_del(&e->list);
+ e->handler(e->scrn, frame,
+ (uint64_t)sec * 1000000 + usec, e->data);
+ free(e);
+ break;
+ }
+ }
+}
+
+/*
+ * Enqueue a potential drm response; when the associated response
+ * appears, we've got data to pass to the handler from here
+ */
+struct radeon_drm_queue_entry *
+radeon_drm_queue_alloc(ScrnInfoPtr scrn, ClientPtr client,
+ uint64_t id, void *data,
+ radeon_drm_handler_proc handler,
+ radeon_drm_abort_proc abort)
+{
+ struct radeon_drm_queue_entry *e;
+
+ e = calloc(1, sizeof(struct radeon_drm_queue_entry));
+ if (!e)
+ return NULL;
+
+ e->client = client;
+ e->scrn = scrn;
+ e->id = id;
+ e->data = data;
+ e->handler = handler;
+ e->abort = abort;
+
+ xorg_list_add(&e->list, &radeon_drm_queue);
+
+ return 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->scrn, e->data);
+ free(e);
+}
+
+/*
+ * Abort drm queue entries for a client
+ */
+void
+radeon_drm_abort_client(ClientPtr client)
+{
+ struct radeon_drm_queue_entry *e, *tmp;
+
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+ if (e->client == client)
+ radeon_drm_abort_one(e);
+ }
+}
+
+/*
+ * Abort specific drm queue entry
+ */
+void
+radeon_drm_abort_entry(struct radeon_drm_queue_entry *entry)
+{
+ radeon_drm_abort_one(entry);
+}
+
+/*
+ * Abort specific drm queue entry by ID
+ */
+void
+radeon_drm_abort_id(uint64_t id)
+{
+ struct radeon_drm_queue_entry *e, *tmp;
+
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+ if (e->id == id) {
+ radeon_drm_abort_one(e);
+ break;
+ }
+ }
+}
+
+/*
+ * Initialize the DRM event queue
+ */
+void
+radeon_drm_queue_init()
+{
+ if (radeon_drm_queue_refcnt++)
+ return;
+
+ xorg_list_init(&radeon_drm_queue);
+}
+
+/*
+ * Deinitialize the DRM event queue
+ */
+void
+radeon_drm_queue_close(ScrnInfoPtr scrn)
+{
+ struct radeon_drm_queue_entry *e, *tmp;
+
+ xorg_list_for_each_entry_safe(e, tmp, &radeon_drm_queue, list) {
+ if (e->scrn == scrn)
+ radeon_drm_abort_one(e);
+ }
+
+ radeon_drm_queue_refcnt--;
+}
diff --git a/driver/xf86-video-ati/src/radeon_drm_queue.h b/driver/xf86-video-ati/src/radeon_drm_queue.h
new file mode 100644
index 000000000..8fc1c42e0
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_drm_queue.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright © 2007 Red Hat, Inc.
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ *
+ */
+
+#ifndef _RADEON_DRM_QUEUE_H_
+#define _RADEON_DRM_QUEUE_H_
+
+#define RADEON_DRM_QUEUE_CLIENT_DEFAULT serverClient
+#define RADEON_DRM_QUEUE_ID_DEFAULT ~0ULL
+
+struct radeon_drm_queue_entry;
+
+typedef void (*radeon_drm_handler_proc)(ScrnInfoPtr scrn, uint32_t seq,
+ uint64_t usec, void *data);
+typedef void (*radeon_drm_abort_proc)(ScrnInfoPtr scrn, void *data);
+
+void radeon_drm_queue_handler(int fd, unsigned int frame,
+ unsigned int tv_sec, unsigned int tv_usec,
+ void *user_ptr);
+struct radeon_drm_queue_entry *radeon_drm_queue_alloc(ScrnInfoPtr scrn,
+ ClientPtr client,
+ uint64_t id,
+ void *data,
+ radeon_drm_handler_proc handler,
+ radeon_drm_abort_proc abort);
+void radeon_drm_abort_client(ClientPtr client);
+void radeon_drm_abort_entry(struct radeon_drm_queue_entry *entry);
+void radeon_drm_abort_id(uint64_t id);
+void radeon_drm_queue_init();
+void radeon_drm_queue_close(ScrnInfoPtr scrn);
+
+#endif /* _RADEON_DRM_QUEUE_H_ */
diff --git a/driver/xf86-video-ati/src/radeon_exa.c b/driver/xf86-video-ati/src/radeon_exa.c
index 0d6cd2400..1e457a8bb 100644
--- a/driver/xf86-video-ati/src/radeon_exa.c
+++ b/driver/xf86-video-ati/src/radeon_exa.c
@@ -330,7 +330,6 @@ Bool RADEONEXASetSharedPixmapBacking(PixmapPtr ppix, void *fd_handle)
return FALSE;
driver_priv->shared = TRUE;
- driver_priv->tiling_flags = 0;
return TRUE;
}
#endif
diff --git a/driver/xf86-video-ati/src/radeon_glamor.c b/driver/xf86-video-ati/src/radeon_glamor.c
index 210ddcf27..fdd5aeac4 100644
--- a/driver/xf86-video-ati/src/radeon_glamor.c
+++ b/driver/xf86-video-ati/src/radeon_glamor.c
@@ -29,11 +29,10 @@
#endif
#include <xf86.h>
-#define GLAMOR_FOR_XORG 1
-#include <glamor.h>
#include "radeon.h"
#include "radeon_bo_helper.h"
+#include "radeon_glamor.h"
#if HAS_DEVPRIVATEKEYREC
DevPrivateKeyRec glamor_pixmap_index;
@@ -61,8 +60,10 @@ radeon_glamor_create_screen_resources(ScreenPtr screen)
if (!info->use_glamor)
return TRUE;
+#ifdef HAVE_GLAMOR_GLYPHS_INIT
if (!glamor_glyphs_init(screen))
return FALSE;
+#endif
if (!glamor_egl_create_textured_screen_ext(screen,
info->front_bo->handle,
@@ -152,51 +153,30 @@ radeon_glamor_pre_init(ScrnInfoPtr scrn)
}
Bool
-radeon_glamor_create_textured_pixmap(PixmapPtr pixmap)
-{
- ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
- RADEONInfoPtr info = RADEONPTR(scrn);
- struct radeon_pixmap *priv;
-
- if ((info->use_glamor) == 0)
- return TRUE;
-
- priv = radeon_get_pixmap_private(pixmap);
- if (!priv->stride)
- priv->stride = pixmap->devKind;
- if (glamor_egl_create_textured_pixmap(pixmap, priv->bo->handle,
- priv->stride))
- return TRUE;
- else
- return FALSE;
-}
-
-Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap)
+radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *priv)
{
- struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
- return priv && priv->bo;
+ return glamor_egl_create_textured_pixmap(pixmap, priv->bo->handle,
+ pixmap->devKind);
}
-#ifndef CREATE_PIXMAP_USAGE_SHARED
-#define CREATE_PIXMAP_USAGE_SHARED RADEON_CREATE_PIXMAP_DRI2
-#endif
-
-#define RADEON_CREATE_PIXMAP_SHARED(usage) \
- (((usage) & ~RADEON_CREATE_PIXMAP_TILING_FLAGS) == RADEON_CREATE_PIXMAP_DRI2 || \
- (usage) == CREATE_PIXMAP_USAGE_SHARED)
-
static PixmapPtr
radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
unsigned usage)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
struct radeon_pixmap *priv;
PixmapPtr pixmap, new_pixmap = NULL;
if (!RADEON_CREATE_PIXMAP_SHARED(usage)) {
- pixmap = glamor_create_pixmap(screen, w, h, depth, usage);
- if (pixmap)
- return pixmap;
+ if (info->shadow_primary) {
+ if (usage != CREATE_PIXMAP_USAGE_BACKING_PIXMAP)
+ return fbCreatePixmap(screen, w, h, depth, usage);
+ } else {
+ pixmap = glamor_create_pixmap(screen, w, h, depth, usage);
+ if (pixmap)
+ return pixmap;
+ }
}
if (w > 32767 || h > 32767)
@@ -213,13 +193,15 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
return pixmap;
if (w && h) {
+ int stride;
+
priv = calloc(1, sizeof (struct radeon_pixmap));
if (priv == NULL)
goto fallback_pixmap;
priv->bo = radeon_alloc_pixmap_bo(scrn, w, h, depth, usage,
pixmap->drawable.bitsPerPixel,
- &priv->stride,
+ &stride,
&priv->surface,
&priv->tiling_flags);
if (!priv->bo)
@@ -227,10 +209,12 @@ radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
radeon_set_pixmap_private(pixmap, priv);
- screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, priv->stride, NULL);
+ screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, stride, NULL);
- if (!radeon_glamor_create_textured_pixmap(pixmap))
+ if (!radeon_glamor_create_textured_pixmap(pixmap, priv))
goto fallback_glamor;
+
+ pixmap->devPrivate.ptr = NULL;
}
return pixmap;
@@ -269,6 +253,13 @@ fallback_pixmap:
static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap)
{
if (pixmap->refcnt == 1) {
+ if (pixmap->devPrivate.ptr) {
+ struct radeon_bo *bo = radeon_get_pixmap_bo(pixmap);
+
+ if (bo)
+ radeon_bo_unmap(bo);
+ }
+
glamor_egl_destroy_textured_pixmap(pixmap);
radeon_set_pixmap_bo(pixmap, NULL);
}
@@ -302,11 +293,9 @@ radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle)
return FALSE;
priv = radeon_get_pixmap_private(pixmap);
- priv->stride = pixmap->devKind;
priv->surface = surface;
- priv->tiling_flags = 0;
- if (!radeon_glamor_create_textured_pixmap(pixmap)) {
+ if (!radeon_glamor_create_textured_pixmap(pixmap, priv)) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"Failed to get PRIME drawable for glamor pixmap.\n");
return FALSE;
@@ -315,9 +304,7 @@ radeon_glamor_set_shared_pixmap_backing(PixmapPtr pixmap, void *handle)
screen->ModifyPixmapHeader(pixmap,
pixmap->drawable.width,
pixmap->drawable.height,
- 0, 0,
- priv->stride,
- NULL);
+ 0, 0, 0, NULL);
return TRUE;
}
@@ -328,12 +315,30 @@ Bool
radeon_glamor_init(ScreenPtr screen)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+#ifdef RENDER
+#ifdef HAVE_FBGLYPHS
+ UnrealizeGlyphProcPtr SavedUnrealizeGlyph = NULL;
+#endif
+ PictureScreenPtr ps = NULL;
+
+ if (info->shadow_primary) {
+ ps = GetPictureScreenIfSet(screen);
- if (!glamor_init(screen, GLAMOR_INVERTED_Y_AXIS | GLAMOR_USE_EGL_SCREEN |
-#ifdef GLAMOR_NO_DRI3
- GLAMOR_NO_DRI3 |
+ if (ps) {
+#ifdef HAVE_FBGLYPHS
+ SavedUnrealizeGlyph = ps->UnrealizeGlyph;
#endif
- GLAMOR_USE_SCREEN | GLAMOR_USE_PICTURE_SCREEN)) {
+ info->glamor.SavedGlyphs = ps->Glyphs;
+ info->glamor.SavedTriangles = ps->Triangles;
+ info->glamor.SavedTrapezoids = ps->Trapezoids;
+ }
+ }
+#endif /* RENDER */
+
+ if (!glamor_init(screen, GLAMOR_USE_EGL_SCREEN | GLAMOR_USE_SCREEN |
+ GLAMOR_USE_PICTURE_SCREEN | GLAMOR_INVERTED_Y_AXIS |
+ GLAMOR_NO_DRI3)) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"Failed to initialize glamor.\n");
return FALSE;
@@ -352,6 +357,17 @@ radeon_glamor_init(ScreenPtr screen)
#endif
return FALSE;
+ if (info->shadow_primary)
+ radeon_glamor_screen_init(screen);
+
+#if defined(RENDER) && defined(HAVE_FBGLYPHS)
+ /* For ShadowPrimary, we need fbUnrealizeGlyph instead of
+ * glamor_unrealize_glyph
+ */
+ if (ps)
+ ps->UnrealizeGlyph = SavedUnrealizeGlyph;
+#endif
+
screen->CreatePixmap = radeon_glamor_create_pixmap;
screen->DestroyPixmap = radeon_glamor_destroy_pixmap;
#ifdef RADEON_PIXMAP_SHARING
@@ -364,15 +380,6 @@ radeon_glamor_init(ScreenPtr screen)
return TRUE;
}
-void
-radeon_glamor_flush(ScrnInfoPtr pScrn)
-{
- RADEONInfoPtr info = RADEONPTR(pScrn);
-
- if (info->use_glamor)
- glamor_block_handler(pScrn->pScreen);
-}
-
XF86VideoAdaptorPtr radeon_glamor_xv_init(ScreenPtr pScreen, int num_adapt)
{
return glamor_xv_init(pScreen, num_adapt);
diff --git a/driver/xf86-video-ati/src/radeon_glamor.h b/driver/xf86-video-ati/src/radeon_glamor.h
index 36addd70d..246336b18 100644
--- a/driver/xf86-video-ati/src/radeon_glamor.h
+++ b/driver/xf86-video-ati/src/radeon_glamor.h
@@ -28,52 +28,51 @@
#define RADEON_GLAMOR_H
#include "xf86xv.h"
+
+struct radeon_pixmap;
+
#ifdef USE_GLAMOR
+#define GLAMOR_FOR_XORG 1
+#include <glamor.h>
+
#include "radeon_surface.h"
+#ifndef CREATE_PIXMAP_USAGE_SHARED
+#define CREATE_PIXMAP_USAGE_SHARED RADEON_CREATE_PIXMAP_DRI2
+#endif
+
+#define RADEON_CREATE_PIXMAP_SHARED(usage) \
+ (((usage) & ~RADEON_CREATE_PIXMAP_TILING_FLAGS) == RADEON_CREATE_PIXMAP_DRI2 || \
+ (usage) == CREATE_PIXMAP_USAGE_SHARED)
+
+#ifndef GLAMOR_NO_DRI3
+#define GLAMOR_NO_DRI3 0
+#define glamor_fd_from_pixmap glamor_dri3_fd_from_pixmap
+#define glamor_pixmap_from_fd glamor_egl_dri3_pixmap_from_fd
+#endif
+
+#ifndef GLAMOR_INVERTED_Y_AXIS
+#define GLAMOR_INVERTED_Y_AXIS 0
+#endif
+#ifndef GLAMOR_USE_SCREEN
+#define GLAMOR_USE_SCREEN 0
+#endif
+#ifndef GLAMOR_USE_PICTURE_SCREEN
+#define GLAMOR_USE_PICTURE_SCREEN 0
+#endif
+
Bool radeon_glamor_pre_init(ScrnInfoPtr scrn);
Bool radeon_glamor_init(ScreenPtr screen);
+void radeon_glamor_screen_init(ScreenPtr screen);
Bool radeon_glamor_create_screen_resources(ScreenPtr screen);
void radeon_glamor_free_screen(int scrnIndex, int flags);
-void radeon_glamor_flush(ScrnInfoPtr pScrn);
-
-Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap);
+Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *priv);
void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst);
-Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap);
-
XF86VideoAdaptorPtr radeon_glamor_xv_init(ScreenPtr pScreen, int num_adapt);
-struct radeon_pixmap {
- struct radeon_surface surface;
- struct radeon_bo *bo;
-
- uint32_t tiling_flags;
- int stride;
-};
-
-#if HAS_DEVPRIVATEKEYREC
-extern DevPrivateKeyRec glamor_pixmap_index;
-#else
-extern int glamor_pixmap_index;
-#endif
-
-static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap)
-{
-#if HAS_DEVPRIVATEKEYREC
- return dixGetPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
-#else
- return dixLookupPrivate(&pixmap->devPrivates, &glamor_pixmap_index);
-#endif
-}
-
-static inline void radeon_set_pixmap_private(PixmapPtr pixmap, struct radeon_pixmap *priv)
-{
- dixSetPrivate(&pixmap->devPrivates, &glamor_pixmap_index, priv);
-}
-
#else
static inline Bool radeon_glamor_pre_init(ScrnInfoPtr scrn) { return FALSE; }
@@ -81,14 +80,10 @@ static inline Bool radeon_glamor_init(ScreenPtr screen) { return FALSE; }
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 void radeon_glamor_flush(ScrnInfoPtr pScrn) { }
-
-static inline Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap) { return TRUE; }
+static inline Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap, struct radeon_pixmap *priv) { return TRUE; }
static inline void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst) {}
-static inline Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap) { return FALSE; }
-
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; }
diff --git a/driver/xf86-video-ati/src/radeon_glamor_wrappers.c b/driver/xf86-video-ati/src/radeon_glamor_wrappers.c
new file mode 100644
index 000000000..ec81560cc
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_glamor_wrappers.c
@@ -0,0 +1,994 @@
+/*
+ * Copyright © 2001 Keith Packard
+ * 2010 Intel Corporation
+ * 2012,2015 Advanced Micro Devices, Inc.
+ *
+ * Partly based on code Copyright © 2008 Red Hat, Inc.
+ * Partly based on code Copyright © 2000 SuSE, Inc.
+ *
+ * Partly based on code that is Copyright © The XFree86 Project Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of the opyright holders not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. The copyright holders make no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef USE_GLAMOR
+
+#include "radeon.h"
+#include "radeon_glamor.h"
+
+
+/**
+ * get_drawable_pixmap() returns the backing pixmap for a given drawable.
+ *
+ * @param pDrawable the drawable being requested.
+ *
+ * This function returns the backing pixmap for a drawable, whether it is a
+ * redirected window, unredirected window, or already a pixmap.
+ */
+static PixmapPtr
+get_drawable_pixmap(DrawablePtr pDrawable)
+{
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ return pDrawable->pScreen->
+ GetWindowPixmap((WindowPtr) pDrawable);
+ else
+ return (PixmapPtr) pDrawable;
+}
+
+/* Are there any outstanding GPU operations for this pixmap? */
+static Bool
+radeon_glamor_gpu_pending(uint_fast32_t gpu_synced, uint_fast32_t gpu_access)
+{
+ return (int_fast32_t)(gpu_access - gpu_synced) > 0;
+}
+
+/*
+ * Pixmap CPU access wrappers
+ */
+
+static Bool
+radeon_glamor_prepare_access_cpu(ScrnInfoPtr scrn, RADEONInfoPtr info,
+ PixmapPtr pixmap, struct radeon_pixmap *priv,
+ Bool need_sync)
+{
+ struct radeon_bo *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);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "%s: bo map (tiling_flags %d) failed: %s\n",
+ __FUNCTION__,
+ priv->tiling_flags,
+ strerror(-ret));
+ 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;
+ }
+
+ return TRUE;
+}
+
+static Bool
+radeon_glamor_prepare_access_cpu_ro(ScrnInfoPtr scrn, PixmapPtr pixmap,
+ struct radeon_pixmap *priv)
+{
+ RADEONInfoPtr info;
+ Bool need_sync;
+
+ if (!priv)
+ return TRUE;
+
+ info = RADEONPTR(scrn);
+ need_sync = radeon_glamor_gpu_pending(info->gpu_synced, priv->gpu_write);
+ return radeon_glamor_prepare_access_cpu(scrn, RADEONPTR(scrn), pixmap,
+ priv, need_sync);
+}
+
+static Bool
+radeon_glamor_prepare_access_cpu_rw(ScrnInfoPtr scrn, PixmapPtr pixmap,
+ struct radeon_pixmap *priv)
+{
+ RADEONInfoPtr info;
+ uint_fast32_t gpu_synced;
+ Bool need_sync;
+
+ if (!priv)
+ return TRUE;
+
+ info = RADEONPTR(scrn);
+ gpu_synced = info->gpu_synced;
+ need_sync = radeon_glamor_gpu_pending(gpu_synced, priv->gpu_write) |
+ radeon_glamor_gpu_pending(gpu_synced, priv->gpu_read);
+ return radeon_glamor_prepare_access_cpu(scrn, info, pixmap, priv,
+ need_sync);
+}
+
+static void
+radeon_glamor_finish_access_cpu(PixmapPtr pixmap)
+{
+ /* Nothing to do */
+}
+
+/*
+ * Pixmap GPU access wrappers
+ */
+
+static Bool
+radeon_glamor_prepare_access_gpu(struct radeon_pixmap *priv)
+{
+ return priv != NULL;
+}
+
+static void
+radeon_glamor_finish_access_gpu_ro(RADEONInfoPtr info,
+ struct radeon_pixmap *priv)
+{
+ priv->gpu_read = info->gpu_flushed + 1;
+}
+
+static void
+radeon_glamor_finish_access_gpu_rw(RADEONInfoPtr info,
+ struct radeon_pixmap *priv)
+{
+ priv->gpu_write = priv->gpu_read = info->gpu_flushed + 1;
+}
+
+/*
+ * GC CPU access wrappers
+ */
+
+static Bool
+radeon_glamor_prepare_access_gc(ScrnInfoPtr scrn, GCPtr pGC)
+{
+ struct radeon_pixmap *priv;
+
+ if (pGC->stipple) {
+ priv = radeon_get_pixmap_private(pGC->stipple);
+ if (!radeon_glamor_prepare_access_cpu_ro(scrn, pGC->stipple, priv))
+ return FALSE;
+ }
+ if (pGC->fillStyle == FillTiled) {
+ priv = radeon_get_pixmap_private(pGC->tile.pixmap);
+ if (!radeon_glamor_prepare_access_cpu_ro(scrn, pGC->tile.pixmap,
+ priv)) {
+ if (pGC->stipple)
+ radeon_glamor_finish_access_cpu(pGC->stipple);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static void
+radeon_glamor_finish_access_gc(GCPtr pGC)
+{
+ if (pGC->fillStyle == FillTiled)
+ radeon_glamor_finish_access_cpu(pGC->tile.pixmap);
+ if (pGC->stipple)
+ radeon_glamor_finish_access_cpu(pGC->stipple);
+}
+
+/*
+ * Picture CPU access wrappers
+ */
+
+static void
+radeon_glamor_picture_finish_access_cpu(PicturePtr picture)
+{
+ /* Nothing to do */
+}
+
+static Bool
+radeon_glamor_picture_prepare_access_cpu_ro(ScrnInfoPtr scrn,
+ PicturePtr picture)
+{
+ PixmapPtr pixmap;
+ struct radeon_pixmap *priv;
+
+ if (picture->pDrawable == NULL)
+ return TRUE;
+
+ pixmap = get_drawable_pixmap(picture->pDrawable);
+ priv = radeon_get_pixmap_private(pixmap);
+ if (!radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv))
+ return FALSE;
+
+ if (picture->alphaMap) {
+ pixmap = get_drawable_pixmap(picture->alphaMap->pDrawable);
+ priv = radeon_get_pixmap_private(pixmap);
+ if (!radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) {
+ radeon_glamor_picture_finish_access_cpu(picture);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+static Bool
+radeon_glamor_picture_prepare_access_cpu_rw(ScrnInfoPtr scrn,
+ PicturePtr picture)
+{
+ PixmapPtr pixmap;
+ struct radeon_pixmap *priv;
+
+ pixmap = get_drawable_pixmap(picture->pDrawable);
+ priv = radeon_get_pixmap_private(pixmap);
+ if (!radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv))
+ return FALSE;
+
+ if (picture->alphaMap) {
+ pixmap = get_drawable_pixmap(picture->alphaMap->pDrawable);
+ priv = radeon_get_pixmap_private(pixmap);
+ if (!radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ radeon_glamor_picture_finish_access_cpu(picture);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/*
+ * GC rendering wrappers
+ */
+
+static void
+radeon_glamor_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
+ DDXPointPtr ppt, int *pwidth, int fSorted)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbFillSpans(pDrawable, pGC, nspans, ppt, pwidth,
+ fSorted);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_set_spans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
+ DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ fbSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
+ int x, int y, int w, int h, int leftPad, int format,
+ char *bits)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ fbPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
+ bits);
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static RegionPtr
+radeon_glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h, int dstx, int dsty,
+ unsigned long bitPlane)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pScreen);
+ PixmapPtr dst_pix = get_drawable_pixmap(pDst);
+ struct radeon_pixmap *dst_priv = radeon_get_pixmap_private(dst_pix);
+ RegionPtr ret = NULL;
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, dst_pix, dst_priv)) {
+ PixmapPtr src_pix = get_drawable_pixmap(pSrc);
+ struct radeon_pixmap *src_priv = radeon_get_pixmap_private(src_pix);
+ if (radeon_glamor_prepare_access_cpu_ro(scrn, src_pix, src_priv)) {
+ ret =
+ fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx,
+ dsty, bitPlane);
+ radeon_glamor_finish_access_cpu(src_pix);
+ }
+ radeon_glamor_finish_access_cpu(dst_pix);
+ }
+ return ret;
+}
+
+static RegionPtr
+radeon_glamor_copy_plane_nodstbo(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h,
+ int dstx, int dsty, unsigned long bitPlane)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pScreen);
+ PixmapPtr src_pix = get_drawable_pixmap(pSrc);
+ struct radeon_pixmap *src_priv = radeon_get_pixmap_private(src_pix);
+ RegionPtr ret = NULL;
+
+ if (radeon_glamor_prepare_access_cpu_ro(scrn, src_pix, src_priv)) {
+ ret = fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h,
+ dstx, dsty, bitPlane);
+ radeon_glamor_finish_access_cpu(src_pix);
+ }
+ return ret;
+}
+
+static void
+radeon_glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+ DDXPointPtr pptInit)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ fbPolyPoint(pDrawable, pGC, mode, npt, pptInit);
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_poly_lines(DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr ppt)
+{
+ if (pGC->lineWidth == 0) {
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbPolyLine(pDrawable, pGC, mode, npt, ppt);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+ return;
+ }
+ /* fb calls mi functions in the lineWidth != 0 case. */
+ fbPolyLine(pDrawable, pGC, mode, npt, ppt);
+}
+
+static void
+radeon_glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC,
+ int nsegInit, xSegment *pSegInit)
+{
+ if (pGC->lineWidth == 0) {
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbPolySegment(pDrawable, pGC, nsegInit,
+ pSegInit);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+ return;
+ }
+ /* fb calls mi functions in the lineWidth != 0 case. */
+ fbPolySegment(pDrawable, pGC, nsegInit, pSegInit);
+}
+
+static void
+radeon_glamor_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC,
+ int nrect, xRectangle *prect)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if ((info->accel_state->force || (priv && !priv->bo)) &&
+ radeon_glamor_prepare_access_gpu(priv)) {
+ info->glamor.SavedPolyFillRect(pDrawable, pGC, nrect, prect);
+ radeon_glamor_finish_access_gpu_rw(info, priv);
+ return;
+ }
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbPolyFillRect(pDrawable, pGC, nrect, prect);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci,
+ pglyphBase);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci,
+ pglyphBase);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
+ DrawablePtr pDrawable, int w, int h, int x, int y)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ priv = radeon_get_pixmap_private(pBitmap);
+ if (radeon_glamor_prepare_access_cpu_ro(scrn, pBitmap, priv)) {
+ if (radeon_glamor_prepare_access_gc(scrn, pGC)) {
+ fbPushPixels(pGC, pBitmap, pDrawable, w, h, x,
+ y);
+ radeon_glamor_finish_access_gc(pGC);
+ }
+ radeon_glamor_finish_access_cpu(pBitmap);
+ }
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_push_pixels_nodstbo(GCPtr pGC, PixmapPtr pBitmap,
+ DrawablePtr pDrawable, int w, int h,
+ int x, int y)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pBitmap);
+
+ if (radeon_glamor_prepare_access_cpu_ro(scrn, pBitmap, priv)) {
+ fbPushPixels(pGC, pBitmap, pDrawable, w, h, x, y);
+ radeon_glamor_finish_access_cpu(pBitmap);
+ }
+}
+
+static RegionPtr
+radeon_glamor_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable,
+ GCPtr pGC, int srcx, int srcy, int width, int height,
+ int dstx, int dsty)
+{
+ ScreenPtr screen = pDstDrawable->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ PixmapPtr src_pixmap = get_drawable_pixmap(pSrcDrawable);
+ PixmapPtr dst_pixmap = get_drawable_pixmap(pDstDrawable);
+ struct radeon_pixmap *src_priv = radeon_get_pixmap_private(src_pixmap);
+ struct radeon_pixmap *dst_priv = radeon_get_pixmap_private(dst_pixmap);
+ RegionPtr ret = NULL;
+
+ if (info->accel_state->force || (src_priv && !src_priv->bo) ||
+ (dst_priv && !dst_priv->bo)) {
+ if (!radeon_glamor_prepare_access_gpu(dst_priv))
+ goto fallback;
+ if (src_priv != dst_priv &&
+ !radeon_glamor_prepare_access_gpu(src_priv))
+ goto fallback;
+
+ ret = info->glamor.SavedCopyArea(pSrcDrawable, pDstDrawable,
+ pGC, srcx, srcy,
+ width, height, dstx, dsty);
+ radeon_glamor_finish_access_gpu_rw(info, dst_priv);
+ if (src_priv != dst_priv)
+ radeon_glamor_finish_access_gpu_ro(info, src_priv);
+
+ return ret;
+ }
+
+fallback:
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, dst_pixmap, dst_priv)) {
+ if (pSrcDrawable == pDstDrawable ||
+ radeon_glamor_prepare_access_cpu_ro(scrn, src_pixmap,
+ src_priv)) {
+ ret = fbCopyArea(pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height, dstx, dsty);
+ if (pSrcDrawable != pDstDrawable)
+ radeon_glamor_finish_access_cpu(src_pixmap);
+ }
+ radeon_glamor_finish_access_cpu(dst_pixmap);
+ }
+
+ return ret;
+}
+
+static RegionPtr
+radeon_glamor_copy_area_nodstbo(DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height,
+ int dstx, int dsty)
+{
+ ScreenPtr screen = pDstDrawable->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ PixmapPtr src_pixmap = get_drawable_pixmap(pSrcDrawable);
+ PixmapPtr dst_pixmap = get_drawable_pixmap(pDstDrawable);
+ struct radeon_pixmap *src_priv;
+ RegionPtr ret = NULL;
+
+ if (src_pixmap != dst_pixmap) {
+ src_priv = radeon_get_pixmap_private(src_pixmap);
+
+ if (!radeon_glamor_prepare_access_cpu_ro(scrn, src_pixmap,
+ src_priv))
+ return ret;
+ }
+
+ ret = fbCopyArea(pSrcDrawable, pDstDrawable, pGC, srcx, srcy,
+ width, height, dstx, dsty);
+
+ if (src_pixmap != dst_pixmap)
+ radeon_glamor_finish_access_cpu(src_pixmap);
+
+ return ret;
+}
+
+static const GCOps radeon_glamor_ops = {
+ radeon_glamor_fill_spans,
+ radeon_glamor_set_spans,
+ radeon_glamor_put_image,
+ radeon_glamor_copy_area,
+ radeon_glamor_copy_plane,
+ radeon_glamor_poly_point,
+ radeon_glamor_poly_lines,
+ radeon_glamor_poly_segment,
+ miPolyRectangle,
+ miPolyArc,
+ miFillPolygon,
+ radeon_glamor_poly_fill_rect,
+ miPolyFillArc,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ radeon_glamor_image_glyph_blt,
+ radeon_glamor_poly_glyph_blt,
+ radeon_glamor_push_pixels,
+};
+
+static GCOps radeon_glamor_nodstbo_ops;
+
+/**
+ * radeon_glamor_validate_gc() sets the ops to our implementations, which may be
+ * accelerated or may sync the card and fall back to fb.
+ */
+static void
+radeon_glamor_validate_gc(GCPtr pGC, unsigned long changes, DrawablePtr pDrawable)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pGC->pScreen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ glamor_validate_gc(pGC, changes, pDrawable);
+ info->glamor.SavedCopyArea = pGC->ops->CopyArea;
+ info->glamor.SavedPolyFillRect = pGC->ops->PolyFillRect;
+
+ if (radeon_get_pixmap_private(get_drawable_pixmap(pDrawable)) ||
+ (pGC->stipple && radeon_get_pixmap_private(pGC->stipple)) ||
+ (pGC->fillStyle == FillTiled &&
+ radeon_get_pixmap_private(pGC->tile.pixmap)))
+ pGC->ops = (GCOps *)&radeon_glamor_ops;
+ else
+ pGC->ops = &radeon_glamor_nodstbo_ops;
+}
+
+static GCFuncs glamorGCFuncs = {
+ radeon_glamor_validate_gc,
+ miChangeGC,
+ miCopyGC,
+ miDestroyGC,
+ miChangeClip,
+ miDestroyClip,
+ miCopyClip
+};
+
+/**
+ * radeon_glamor_create_gc makes a new GC and hooks up its funcs handler, so that
+ * radeon_glamor_validate_gc() will get called.
+ */
+static int
+radeon_glamor_create_gc(GCPtr pGC)
+{
+ static Bool nodstbo_ops_initialized;
+
+ if (!fbCreateGC(pGC))
+ return FALSE;
+
+ if (!nodstbo_ops_initialized) {
+ radeon_glamor_nodstbo_ops = radeon_glamor_ops;
+
+ radeon_glamor_nodstbo_ops.FillSpans = pGC->ops->FillSpans;
+ radeon_glamor_nodstbo_ops.SetSpans = pGC->ops->SetSpans;
+ radeon_glamor_nodstbo_ops.PutImage = pGC->ops->PutImage;
+ radeon_glamor_nodstbo_ops.CopyArea = radeon_glamor_copy_area_nodstbo;
+ radeon_glamor_nodstbo_ops.CopyPlane = radeon_glamor_copy_plane_nodstbo;
+ radeon_glamor_nodstbo_ops.PolyPoint = pGC->ops->PolyPoint;
+ radeon_glamor_nodstbo_ops.Polylines = pGC->ops->Polylines;
+ radeon_glamor_nodstbo_ops.PolySegment = pGC->ops->PolySegment;
+ radeon_glamor_nodstbo_ops.PolyFillRect = pGC->ops->PolyFillRect;
+ radeon_glamor_nodstbo_ops.ImageGlyphBlt = pGC->ops->ImageGlyphBlt;
+ radeon_glamor_nodstbo_ops.PolyGlyphBlt = pGC->ops->PolyGlyphBlt;
+ radeon_glamor_nodstbo_ops.PushPixels = radeon_glamor_push_pixels_nodstbo;
+
+ nodstbo_ops_initialized = TRUE;
+ }
+
+ pGC->funcs = &glamorGCFuncs;
+
+ return TRUE;
+}
+
+/*
+ * Screen rendering wrappers
+ */
+
+static RegionPtr
+radeon_glamor_bitmap_to_region(PixmapPtr pPix)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pPix->drawable.pScreen);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pPix);
+ RegionPtr ret;
+
+ if (!radeon_glamor_prepare_access_cpu_ro(scrn, pPix, priv))
+ return NULL;
+ ret = fbPixmapToRegion(pPix);
+ radeon_glamor_finish_access_cpu(pPix);
+ return ret;
+}
+
+static void
+radeon_glamor_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg,
+ RegionPtr prgnSrc)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pWin->drawable.pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(&pWin->drawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_rw(scrn, pixmap, priv)) {
+ fbCopyWindow(pWin, ptOldOrg, prgnSrc);
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long planeMask, char *d)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) {
+ fbGetImage(pDrawable, x, y, w, h, format, planeMask, d);
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+static void
+radeon_glamor_get_spans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt,
+ int *pwidth, int nspans, char *pdstStart)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDrawable->pScreen);
+ PixmapPtr pixmap = get_drawable_pixmap(pDrawable);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+
+ if (radeon_glamor_prepare_access_cpu_ro(scrn, pixmap, priv)) {
+ fbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
+ radeon_glamor_finish_access_cpu(pixmap);
+ }
+}
+
+/*
+ * Picture screen rendering wrappers
+ */
+
+#ifdef RENDER
+
+static void
+radeon_glamor_composite(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc,
+ INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst,
+ CARD16 width, CARD16 height)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pDst->pDrawable->pScreen);
+ RADEONInfoPtr info;
+ PixmapPtr pixmap;
+ struct radeon_pixmap *dst_priv, *src_priv = NULL, *mask_priv = NULL;
+ Bool gpu_done = FALSE;
+
+ if (pDst->alphaMap || pSrc->alphaMap || (pMask && pMask->alphaMap))
+ goto fallback;
+
+ pixmap = get_drawable_pixmap(pDst->pDrawable);
+ if (&pixmap->drawable != pDst->pDrawable ||
+ pixmap->usage_hint != RADEON_CREATE_PIXMAP_SCANOUT)
+ goto fallback;
+
+ dst_priv = radeon_get_pixmap_private(pixmap);
+ if (!radeon_glamor_prepare_access_gpu(dst_priv))
+ goto fallback;
+
+ info = RADEONPTR(scrn);
+ if (!pSrc->pDrawable ||
+ ((pixmap = get_drawable_pixmap(pSrc->pDrawable)) &&
+ (src_priv = radeon_get_pixmap_private(pixmap)) &&
+ radeon_glamor_prepare_access_gpu(src_priv))) {
+ if (!pMask || !pMask->pDrawable ||
+ ((pixmap = get_drawable_pixmap(pMask->pDrawable)) &&
+ (mask_priv = radeon_get_pixmap_private(pixmap)) &&
+ radeon_glamor_prepare_access_gpu(mask_priv))) {
+ info->glamor.SavedComposite(op, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask,
+ xDst, yDst, width, height);
+ gpu_done = TRUE;
+
+ if (mask_priv)
+ radeon_glamor_finish_access_gpu_ro(info, mask_priv);
+ }
+
+ if (src_priv)
+ radeon_glamor_finish_access_gpu_ro(info, src_priv);
+ }
+ radeon_glamor_finish_access_gpu_rw(info, dst_priv);
+
+ if (gpu_done)
+ return;
+
+fallback:
+ if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, pDst)) {
+ if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, pSrc)) {
+ if (!pMask ||
+ radeon_glamor_picture_prepare_access_cpu_ro(scrn, pMask)) {
+ fbComposite(op, pSrc, pMask, pDst,
+ xSrc, ySrc,
+ xMask, yMask,
+ xDst, yDst,
+ width, height);
+ if (pMask)
+ radeon_glamor_picture_finish_access_cpu(pMask);
+ }
+ radeon_glamor_picture_finish_access_cpu(pSrc);
+ }
+ radeon_glamor_picture_finish_access_cpu(pDst);
+ }
+}
+
+static void
+radeon_glamor_add_traps(PicturePtr pPicture,
+ INT16 x_off, INT16 y_off, int ntrap, xTrap *traps)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pPicture->pDrawable->pScreen);
+
+ if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, pPicture)) {
+ fbAddTraps(pPicture, x_off, y_off, ntrap, traps);
+ radeon_glamor_picture_finish_access_cpu(pPicture);
+ }
+}
+
+static void
+radeon_glamor_glyphs(CARD8 op,
+ PicturePtr src,
+ PicturePtr dst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr *glyphs)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen);
+
+ if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, dst)) {
+ if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, src)) {
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ info->glamor.SavedGlyphs(op, src, dst, maskFormat, xSrc,
+ ySrc, nlist, list, glyphs);
+ radeon_glamor_picture_finish_access_cpu(src);
+ }
+ radeon_glamor_picture_finish_access_cpu(dst);
+ }
+}
+
+static void
+radeon_glamor_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid *traps)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen);
+
+ if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, dst)) {
+ if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, src)) {
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ info->glamor.SavedTrapezoids(op, src, dst, maskFormat,
+ xSrc, ySrc, ntrap, traps);
+ radeon_glamor_picture_finish_access_cpu(src);
+ }
+ radeon_glamor_picture_finish_access_cpu(dst);
+ }
+}
+
+static void
+radeon_glamor_triangles(CARD8 op, PicturePtr src, PicturePtr dst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntri, xTriangle *tri)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(dst->pDrawable->pScreen);
+
+ if (radeon_glamor_picture_prepare_access_cpu_rw(scrn, dst)) {
+ if (radeon_glamor_picture_prepare_access_cpu_ro(scrn, src)) {
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ info->glamor.SavedTriangles(op, src, dst, maskFormat,
+ xSrc, ySrc, ntri, tri);
+ radeon_glamor_picture_finish_access_cpu(src);
+ }
+ radeon_glamor_picture_finish_access_cpu(dst);
+ }
+}
+
+#endif /* RENDER */
+
+
+/**
+ * radeon_glamor_close_screen() unwraps its wrapped screen functions and tears
+ * down our screen private, before calling down to the next CloseScreen.
+ */
+static Bool
+radeon_glamor_close_screen(CLOSE_SCREEN_ARGS_DECL)
+{
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pScreen));
+#ifdef RENDER
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+#endif
+
+ pScreen->CreateGC = info->glamor.SavedCreateGC;
+ pScreen->CloseScreen = info->glamor.SavedCloseScreen;
+ pScreen->GetImage = info->glamor.SavedGetImage;
+ pScreen->GetSpans = info->glamor.SavedGetSpans;
+ pScreen->CreatePixmap = info->glamor.SavedCreatePixmap;
+ pScreen->DestroyPixmap = info->glamor.SavedDestroyPixmap;
+ pScreen->CopyWindow = info->glamor.SavedCopyWindow;
+ pScreen->ChangeWindowAttributes =
+ info->glamor.SavedChangeWindowAttributes;
+ pScreen->BitmapToRegion = info->glamor.SavedBitmapToRegion;
+#ifdef RENDER
+ if (ps) {
+ ps->Composite = info->glamor.SavedComposite;
+ ps->Glyphs = info->glamor.SavedGlyphs;
+ ps->UnrealizeGlyph = info->glamor.SavedUnrealizeGlyph;
+ ps->Trapezoids = info->glamor.SavedTrapezoids;
+ ps->AddTraps = info->glamor.SavedAddTraps;
+ ps->Triangles = info->glamor.SavedTriangles;
+
+ ps->UnrealizeGlyph = info->glamor.SavedUnrealizeGlyph;
+ }
+#endif
+
+ return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS);
+}
+
+/**
+ * @param screen screen being initialized
+ */
+void
+radeon_glamor_screen_init(ScreenPtr screen)
+{
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(screen));
+
+ /*
+ * Replace various fb screen functions
+ */
+ info->glamor.SavedCloseScreen = screen->CloseScreen;
+ screen->CloseScreen = radeon_glamor_close_screen;
+
+ info->glamor.SavedCreateGC = screen->CreateGC;
+ screen->CreateGC = radeon_glamor_create_gc;
+
+ info->glamor.SavedGetImage = screen->GetImage;
+ screen->GetImage = radeon_glamor_get_image;
+
+ info->glamor.SavedGetSpans = screen->GetSpans;
+ screen->GetSpans = radeon_glamor_get_spans;
+
+ info->glamor.SavedCreatePixmap = screen->CreatePixmap;
+ info->glamor.SavedDestroyPixmap = screen->DestroyPixmap;
+
+ info->glamor.SavedCopyWindow = screen->CopyWindow;
+ screen->CopyWindow = radeon_glamor_copy_window;
+
+ info->glamor.SavedBitmapToRegion = screen->BitmapToRegion;
+ screen->BitmapToRegion = radeon_glamor_bitmap_to_region;
+
+#ifdef RENDER
+ {
+ PictureScreenPtr ps = GetPictureScreenIfSet(screen);
+ if (ps) {
+ info->glamor.SavedComposite = ps->Composite;
+ ps->Composite = radeon_glamor_composite;
+
+ info->glamor.SavedUnrealizeGlyph = ps->UnrealizeGlyph;
+
+ ps->Glyphs = radeon_glamor_glyphs;
+ ps->Triangles = radeon_glamor_triangles;
+ ps->Trapezoids = radeon_glamor_trapezoids;
+
+ info->glamor.SavedAddTraps = ps->AddTraps;
+ ps->AddTraps = radeon_glamor_add_traps;
+ }
+ }
+#endif
+}
+
+#endif /* USE_GLAMOR */
diff --git a/driver/xf86-video-ati/src/radeon_kms.c b/driver/xf86-video-ati/src/radeon_kms.c
index 1703349f1..8aa763327 100644
--- a/driver/xf86-video-ati/src/radeon_kms.c
+++ b/driver/xf86-video-ati/src/radeon_kms.c
@@ -32,6 +32,8 @@
#include <sys/ioctl.h>
/* Driver data structures */
#include "radeon.h"
+#include "radeon_drm_queue.h"
+#include "radeon_glamor.h"
#include "radeon_reg.h"
#include "radeon_probe.h"
#include "micmap.h"
@@ -68,12 +70,16 @@ const OptionInfoRec RADEONOptions_KMS[] = {
{ OPTION_SUBPIXEL_ORDER, "SubPixelOrder", OPTV_ANYSTR, {0}, FALSE },
#ifdef USE_GLAMOR
{ OPTION_ACCELMETHOD, "AccelMethod", OPTV_STRING, {0}, FALSE },
+ { OPTION_SHADOW_PRIMARY, "ShadowPrimary", OPTV_BOOLEAN, {0}, FALSE },
#endif
{ OPTION_EXA_VSYNC, "EXAVSync", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_EXA_PIXMAPS, "EXAPixmaps", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE },
- { OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE },
{ OPTION_SWAPBUFFERS_WAIT,"SwapbuffersWait", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DELETE_DP12, "DeleteUnusedDP12Displays", OPTV_BOOLEAN, {0}, FALSE},
+ { OPTION_DRI3, "DRI3", OPTV_BOOLEAN, {0}, FALSE },
+ { OPTION_DRI, "DRI", OPTV_INTEGER, {0}, FALSE },
+ { OPTION_TEAR_FREE, "TearFree", OPTV_BOOLEAN, {0}, FALSE },
{ -1, NULL, OPTV_NONE, {0}, FALSE }
};
@@ -82,12 +88,22 @@ const OptionInfoRec *RADEONOptionsWeak(void) { return RADEONOptions_KMS; }
void radeon_cs_flush_indirect(ScrnInfoPtr pScrn)
{
RADEONInfoPtr info = RADEONPTR(pScrn);
- struct radeon_accel_state *accel_state = info->accel_state;
+ struct radeon_accel_state *accel_state;
int ret;
+#ifdef USE_GLAMOR
+ if (info->use_glamor) {
+ glamor_block_handler(pScrn->pScreen);
+ info->gpu_flushed++;
+ return;
+ }
+#endif
+
if (!info->cs->cdw)
return;
+ accel_state = info->accel_state;
+
/* release the current VBO so we don't block on mapping it later */
if (info->accel_state->vbo.vb_offset && info->accel_state->vbo.vb_bo) {
radeon_vbo_put(pScrn, &info->accel_state->vbo);
@@ -171,6 +187,9 @@ static void RADEONFreeRec(ScrnInfoPtr pScrn)
info = RADEONPTR(pScrn);
+ if (info->fbcon_pixmap)
+ pScrn->pScreen->DestroyPixmap(info->fbcon_pixmap);
+
if (info->dri2.drm_fd > 0) {
DevUnion *pPriv;
RADEONEntPtr pRADEONEnt;
@@ -230,7 +249,7 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
return FALSE;
pScreen->CreateScreenResources = RADEONCreateScreenResources_KMS;
- if (!drmmode_set_desired_modes(pScrn, &info->drmmode))
+ if (!drmmode_set_desired_modes(pScrn, &info->drmmode, FALSE))
return FALSE;
drmmode_uevent_init(pScrn, &info->drmmode);
@@ -269,7 +288,11 @@ redisplay_dirty(ScreenPtr screen, PixmapDirtyUpdatePtr dirty)
PixmapRegionInit(&pixregion, dirty->slave_dst);
DamageRegionAppend(&dirty->slave_dst->drawable, &pixregion);
+#ifdef HAS_DIRTYTRACKING_ROTATION
+ PixmapSyncDirtyHelper(dirty);
+#else
PixmapSyncDirtyHelper(dirty, &pixregion);
+#endif
radeon_cs_flush_indirect(pScrn);
DamageRegionProcessPending(&dirty->slave_dst->drawable);
@@ -295,6 +318,204 @@ radeon_dirty_update(ScreenPtr screen)
}
#endif
+static Bool
+radeon_scanout_extents_intersect(BoxPtr extents, int x, int y, int w, int h)
+{
+ extents->x1 = max(extents->x1 - x, 0);
+ extents->y1 = max(extents->y1 - y, 0);
+ extents->x2 = min(extents->x2 - x, w);
+ extents->y2 = min(extents->y2 - y, h);
+
+ return (extents->x1 < extents->x2 && extents->y1 < extents->y2);
+}
+
+static Bool
+radeon_scanout_do_update(xf86CrtcPtr xf86_crtc, int scanout_id)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+ ScrnInfoPtr scrn;
+ DamagePtr pDamage;
+ RegionPtr pRegion;
+ DrawablePtr pDraw;
+ ScreenPtr pScreen;
+ GCPtr gc;
+ BoxRec extents;
+ RADEONInfoPtr info;
+ Bool force;
+
+ if (!xf86_crtc->enabled ||
+ drmmode_crtc->dpms_mode != DPMSModeOn ||
+ !drmmode_crtc->scanout[scanout_id].pixmap)
+ return FALSE;
+
+ pDamage = drmmode_crtc->scanout[scanout_id].damage;
+ if (!pDamage)
+ return FALSE;
+
+ pRegion = DamageRegion(pDamage);
+ if (!RegionNotEmpty(pRegion))
+ return FALSE;
+
+ pDraw = &drmmode_crtc->scanout[scanout_id].pixmap->drawable;
+ extents = *RegionExtents(pRegion);
+ RegionEmpty(pRegion);
+ if (!radeon_scanout_extents_intersect(&extents, xf86_crtc->x, xf86_crtc->y,
+ pDraw->width, pDraw->height))
+ return FALSE;
+
+ pScreen = pDraw->pScreen;
+ gc = GetScratchGC(pDraw->depth, pScreen);
+ scrn = xf86_crtc->scrn;
+ info = RADEONPTR(scrn);
+ force = info->accel_state->force;
+ info->accel_state->force = TRUE;
+
+ ValidateGC(pDraw, gc);
+ (*gc->ops->CopyArea)(&pScreen->GetScreenPixmap(pScreen)->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);
+ FreeScratchGC(gc);
+
+ info->accel_state->force = force;
+
+ radeon_cs_flush_indirect(scrn);
+
+ return TRUE;
+}
+
+static void
+radeon_scanout_update_abort(ScrnInfoPtr scrn, void *event_data)
+{
+ xf86CrtcPtr xf86_crtc = event_data;
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+
+ drmmode_crtc->scanout_update_pending = FALSE;
+}
+
+void
+radeon_scanout_update_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec,
+ void *event_data)
+{
+ radeon_scanout_do_update(event_data, 0);
+
+ radeon_scanout_update_abort(scrn, event_data);
+}
+
+static void
+radeon_scanout_update(xf86CrtcPtr xf86_crtc)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+ struct radeon_drm_queue_entry *drm_queue_entry;
+ ScrnInfoPtr scrn;
+ drmVBlank vbl;
+ DamagePtr pDamage;
+ RegionPtr pRegion;
+ DrawablePtr pDraw;
+ BoxRec extents;
+
+ if (!xf86_crtc->enabled ||
+ drmmode_crtc->scanout_update_pending ||
+ !drmmode_crtc->scanout[0].pixmap ||
+ drmmode_crtc->dpms_mode != DPMSModeOn)
+ return;
+
+ pDamage = drmmode_crtc->scanout[0].damage;
+ if (!pDamage)
+ return;
+
+ pRegion = DamageRegion(pDamage);
+ if (!RegionNotEmpty(pRegion))
+ return;
+
+ pDraw = &drmmode_crtc->scanout[0].pixmap->drawable;
+ extents = *RegionExtents(pRegion);
+ if (!radeon_scanout_extents_intersect(&extents, xf86_crtc->x, xf86_crtc->y,
+ pDraw->width, pDraw->height))
+ return;
+
+ scrn = xf86_crtc->scrn;
+ drm_queue_entry = radeon_drm_queue_alloc(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT,
+ RADEON_DRM_QUEUE_ID_DEFAULT,
+ xf86_crtc,
+ radeon_scanout_update_handler,
+ radeon_scanout_update_abort);
+ if (!drm_queue_entry) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "radeon_drm_queue_alloc failed for scanout update\n");
+ return;
+ }
+
+ vbl.request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT;
+ vbl.request.type |= radeon_populate_vbl_request_type(xf86_crtc);
+ vbl.request.sequence = 1;
+ vbl.request.signal = (unsigned long)drm_queue_entry;
+ if (drmWaitVBlank(RADEONPTR(scrn)->dri2.drm_fd, &vbl)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "drmWaitVBlank failed for scanout update: %s\n",
+ strerror(errno));
+ radeon_drm_abort_entry(drm_queue_entry);
+ return;
+ }
+
+ drmmode_crtc->scanout_update_pending = TRUE;
+}
+
+static void
+radeon_scanout_flip_abort(ScrnInfoPtr scrn, void *event_data)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = event_data;
+
+ drmmode_crtc->scanout_update_pending = FALSE;
+}
+
+static void
+radeon_scanout_flip_handler(ScrnInfoPtr scrn, uint32_t frame, uint64_t usec, void *event_data)
+{
+ radeon_scanout_flip_abort(scrn, event_data);
+}
+
+static void
+radeon_scanout_flip(ScreenPtr pScreen, RADEONInfoPtr info,
+ xf86CrtcPtr xf86_crtc)
+{
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+ ScrnInfoPtr scrn;
+ struct radeon_drm_queue_entry *drm_queue_entry;
+ unsigned scanout_id;
+
+ if (drmmode_crtc->scanout_update_pending)
+ return;
+
+ scanout_id = drmmode_crtc->scanout_id ^ 1;
+ if (!radeon_scanout_do_update(xf86_crtc, scanout_id))
+ return;
+
+ scrn = xf86_crtc->scrn;
+ drm_queue_entry = radeon_drm_queue_alloc(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT,
+ RADEON_DRM_QUEUE_ID_DEFAULT,
+ drmmode_crtc,
+ radeon_scanout_flip_handler,
+ radeon_scanout_flip_abort);
+ if (!drm_queue_entry) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Allocating DRM event queue entry failed.\n");
+ return;
+ }
+
+ if (drmModePageFlip(drmmode_crtc->drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
+ drmmode_crtc->scanout[scanout_id].fb_id,
+ DRM_MODE_PAGE_FLIP_EVENT, drm_queue_entry)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING, "flip queue failed in %s: %s\n",
+ __func__, strerror(errno));
+ return;
+ }
+
+ drmmode_crtc->scanout_id = scanout_id;
+ drmmode_crtc->scanout_update_pending = TRUE;
+}
+
static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
{
SCREEN_PTR(arg);
@@ -305,25 +526,44 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
(*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
pScreen->BlockHandler = RADEONBlockHandler_KMS;
- if (info->use_glamor)
- radeon_glamor_flush(pScrn);
+ if (info->tear_free || info->shadow_primary) {
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ if (info->tear_free)
+ radeon_scanout_flip(pScreen, info, xf86_config->crtc[c]);
+ else
+ radeon_scanout_update(xf86_config->crtc[c]);
+ }
+ }
radeon_cs_flush_indirect(pScrn);
+
#ifdef RADEON_PIXMAP_SHARING
radeon_dirty_update(pScreen);
#endif
}
+static void RADEONBlockHandler_oneshot(BLOCKHANDLER_ARGS_DECL)
+{
+ SCREEN_PTR(arg);
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE);
+
+ RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS);
+}
+
static void
radeon_flush_callback(CallbackListPtr *list,
pointer user_data, pointer call_data)
{
ScrnInfoPtr pScrn = user_data;
- if (pScrn->vtSema) {
+ if (pScrn->vtSema)
radeon_cs_flush_indirect(pScrn);
- radeon_glamor_flush(pScrn);
- }
}
static Bool RADEONIsFastFBWorking(ScrnInfoPtr pScrn)
@@ -779,14 +1019,48 @@ static void RADEONSetupCapabilities(ScrnInfoPtr pScrn)
pScrn->capabilities = 0;
ret = drmGetCap(info->dri2.drm_fd, DRM_CAP_PRIME, &value);
if (ret == 0) {
- if (value & DRM_PRIME_CAP_EXPORT)
- pScrn->capabilities |= RR_Capability_SourceOutput | RR_Capability_SinkOffload;
- if (value & DRM_PRIME_CAP_IMPORT)
- pScrn->capabilities |= RR_Capability_SourceOffload | RR_Capability_SinkOutput;
+ if (value & DRM_PRIME_CAP_EXPORT) {
+ pScrn->capabilities |= RR_Capability_SourceOutput;
+ if (!info->r600_shadow_fb && info->dri2.available)
+ pScrn->capabilities |= RR_Capability_SinkOffload;
+ }
+ if (value & DRM_PRIME_CAP_IMPORT) {
+ pScrn->capabilities |= RR_Capability_SinkOutput;
+ if (!info->r600_shadow_fb && info->dri2.available)
+ pScrn->capabilities |= RR_Capability_SourceOffload;
+ }
}
#endif
}
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
+
+/* When the root window is created, initialize the screen contents from
+ * console if -background none was specified on the command line
+ */
+static Bool RADEONCreateWindow_oneshot(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ ScrnInfoPtr pScrn;
+ RADEONInfoPtr info;
+ Bool ret;
+
+ if (pWin != pScreen->root)
+ ErrorF("%s called for non-root window %p\n", __func__, pWin);
+
+ pScrn = xf86ScreenToScrn(pScreen);
+ info = RADEONPTR(pScrn);
+ pScreen->CreateWindow = info->CreateWindow;
+ ret = pScreen->CreateWindow(pWin);
+
+ if (ret)
+ drmmode_copy_fb(pScrn, &info->drmmode);
+
+ return ret;
+}
+
+#endif
+
Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
{
RADEONInfoPtr info;
@@ -806,7 +1080,6 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
info = RADEONPTR(pScrn);
info->IsSecondary = FALSE;
- info->IsPrimary = FALSE;
info->pEnt = xf86GetEntityInfo(pScrn->entityList[pScrn->numEntities - 1]);
if (info->pEnt->location.type != BUS_PCI
#ifdef XSERVER_PLATFORM_BUS
@@ -824,14 +1097,10 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
if(xf86IsPrimInitDone(pScrn->entityList[0]))
{
info->IsSecondary = TRUE;
- pRADEONEnt->pSecondaryScrn = pScrn;
}
else
{
- info->IsPrimary = TRUE;
xf86SetPrimInitDone(pScrn->entityList[0]);
- pRADEONEnt->pPrimaryScrn = pScrn;
- pRADEONEnt->HasSecondary = FALSE;
}
}
@@ -870,6 +1139,8 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
if (!RADEONPreInitAccel_KMS(pScrn)) goto fail;
+ radeon_drm_queue_init();
+
info->allowColorTiling2D = FALSE;
RADEONSetupCapabilities(pScrn);
@@ -920,11 +1191,37 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"KMS Color Tiling 2D: %sabled\n", info->allowColorTiling2D ? "en" : "dis");
+#if USE_GLAMOR
+ if (info->use_glamor) {
+ info->shadow_primary = xf86ReturnOptValBool(info->Options,
+ OPTION_SHADOW_PRIMARY, FALSE);
+
+ if (info->shadow_primary)
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "ShadowPrimary enabled\n");
+ }
+#endif
+
+ info->tear_free = xf86ReturnOptValBool(info->Options, OPTION_TEAR_FREE,
+ FALSE);
+
+ if (info->tear_free)
+ xf86DrvMsg(pScrn->scrnIndex, X_CONFIG, "TearFree enabled\n");
+
if (info->dri2.pKernelDRMVersion->version_minor >= 8) {
info->allowPageFlip = xf86ReturnOptValBool(info->Options,
OPTION_PAGE_FLIP, TRUE);
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "KMS Pageflipping: %sabled\n", info->allowPageFlip ? "en" : "dis");
+
+ if (info->tear_free || info->shadow_primary) {
+ xf86DrvMsg(pScrn->scrnIndex,
+ info->allowPageFlip ? X_WARNING : X_DEFAULT,
+ "KMS Pageflipping: disabled%s\n",
+ info->allowPageFlip ?
+ " because of ShadowPrimary/TearFree" : "");
+ info->allowPageFlip = FALSE;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "KMS Pageflipping: %sabled\n", info->allowPageFlip ? "en" : "dis");
+ }
}
info->swapBuffersWait = xf86ReturnOptValBool(info->Options,
@@ -932,12 +1229,16 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"SwapBuffers wait for vsync: %sabled\n", info->swapBuffersWait ? "en" : "dis");
+ if (xf86ReturnOptValBool(info->Options, OPTION_DELETE_DP12, FALSE)) {
+ info->drmmode.delete_dp_12_displays = TRUE;
+ }
+
if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) == FALSE) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
goto fail;
}
- if (info->drmmode.mode_res->count_crtcs == 1)
+ if (info->drmmode.count_crtcs == 1)
pRADEONEnt->HasCRTC2 = FALSE;
else
pRADEONEnt->HasCRTC2 = TRUE;
@@ -1158,11 +1459,16 @@ static Bool RADEONCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
{
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
RADEONInfoPtr info = RADEONPTR(pScrn);
+ RADEONEntPtr pRADEONEnt = RADEONEntPriv(pScrn);
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
"RADEONCloseScreen\n");
+ /* Clear mask of assigned crtc's in this generation */
+ pRADEONEnt->assigned_crtcs = 0;
+
drmmode_uevent_fini(pScrn, &info->drmmode);
+ radeon_drm_queue_close(pScrn);
radeon_cs_flush_indirect(pScrn);
DeleteCallback(&FlushCallback, radeon_flush_callback, pScrn);
@@ -1173,6 +1479,8 @@ static Bool RADEONCloseScreen_KMS(CLOSE_SCREEN_ARGS_DECL)
info->accel_state->exa = NULL;
}
+ radeon_sync_close(pScreen);
+
if (info->accel_state->use_vbos)
radeon_vbo_free_lists(pScrn);
@@ -1209,6 +1517,9 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
RADEONInfoPtr info = RADEONPTR(pScrn);
int subPixelOrder = SubPixelUnknown;
+ MessageType from;
+ Bool value;
+ int driLevel;
const char *s;
void *front_ptr;
@@ -1319,6 +1630,28 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
}
#endif
+ value = FALSE;
+ from = X_DEFAULT;
+ if (xf86GetOptValBool(info->Options, OPTION_DRI3, &value))
+ from = X_CONFIG;
+
+ if (xf86GetOptValInteger(info->Options, OPTION_DRI, &driLevel) &&
+ (driLevel == 2 || driLevel == 3)) {
+ from = X_CONFIG;
+ value = driLevel == 3;
+ }
+
+ if (value) {
+ value = radeon_sync_init(pScreen) &&
+ radeon_present_screen_init(pScreen) &&
+ radeon_dri3_screen_init(pScreen);
+
+ if (!value)
+ from = X_WARNING;
+ }
+
+ xf86DrvMsg(pScrn->scrnIndex, from, "DRI3 %sabled\n", value ? "en" : "dis");
+
pScrn->vtSema = TRUE;
xf86SetBackingStore(pScreen);
@@ -1388,13 +1721,20 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
}
pScrn->pScreen = pScreen;
+#if GET_ABI_MAJOR(ABI_VIDEODRV_VERSION) >= 10
+ if (serverGeneration == 1 && bgNoneRoot && info->accelOn) {
+ info->CreateWindow = pScreen->CreateWindow;
+ pScreen->CreateWindow = RADEONCreateWindow_oneshot;
+ }
+#endif
+
/* Provide SaveScreen & wrap BlockHandler and CloseScreen */
/* Wrap CloseScreen */
info->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = RADEONCloseScreen_KMS;
pScreen->SaveScreen = RADEONSaveScreen_KMS;
info->BlockHandler = pScreen->BlockHandler;
- pScreen->BlockHandler = RADEONBlockHandler_KMS;
+ pScreen->BlockHandler = RADEONBlockHandler_oneshot;
if (!AddCallback(&FlushCallback, radeon_flush_callback, pScrn))
return FALSE;
@@ -1447,7 +1787,7 @@ Bool RADEONEnterVT_KMS(VT_FUNC_ARGS_DECL)
pScrn->vtSema = TRUE;
- if (!drmmode_set_desired_modes(pScrn, &info->drmmode))
+ if (!drmmode_set_desired_modes(pScrn, &info->drmmode, TRUE))
return FALSE;
return TRUE;
@@ -1465,6 +1805,7 @@ void RADEONLeaveVT_KMS(VT_FUNC_ARGS_DECL)
radeon_drop_drm_master(pScrn);
xf86RotateFreeShadow(pScrn);
+ drmmode_scanout_free(pScrn);
xf86_hide_cursors (pScrn);
info->accel_state->XInited3D = FALSE;
@@ -1515,7 +1856,7 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
}
}
- if (info->allowColorTiling) {
+ if (info->allowColorTiling && !info->shadow_primary) {
if (info->ChipFamily >= CHIP_FAMILY_R600) {
if (info->allowColorTiling2D) {
tiling_flags |= RADEON_TILING_MACRO;
@@ -1578,7 +1919,9 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
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;
- tiling_flags |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_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;
@@ -1618,7 +1961,10 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
if (info->front_bo == NULL) {
info->front_bo = radeon_bo_open(info->bufmgr, 0, screen_size,
- base_align, RADEON_GEM_DOMAIN_VRAM, 0);
+ base_align,
+ info->shadow_primary ?
+ RADEON_GEM_DOMAIN_GTT :
+ RADEON_GEM_DOMAIN_VRAM, 0);
if (info->r600_shadow_fb == TRUE) {
if (radeon_bo_map(info->front_bo, 1)) {
ErrorF("Failed to map cursor buffer memory\n");
diff --git a/driver/xf86-video-ati/src/radeon_list.h b/driver/xf86-video-ati/src/radeon_list.h
new file mode 100644
index 000000000..77f74affc
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_list.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef _RADEON_LIST_H_
+#define _RADEON_LIST_H_
+
+#include <xorg-server.h>
+#include <list.h>
+
+#if !HAVE_XORG_LIST
+#define xorg_list list
+#define xorg_list_init list_init
+#define xorg_list_add list_add
+#define xorg_list_del list_del
+#define xorg_list_for_each_entry list_for_each_entry
+#define xorg_list_for_each_entry_safe list_for_each_entry_safe
+#endif
+
+#endif /* _RADEON_LIST_H_ */
diff --git a/driver/xf86-video-ati/src/radeon_pci_chipset_gen.h b/driver/xf86-video-ati/src/radeon_pci_chipset_gen.h
index bd689201f..4b4b8e454 100644
--- a/driver/xf86-video-ati/src/radeon_pci_chipset_gen.h
+++ b/driver/xf86-video-ati/src/radeon_pci_chipset_gen.h
@@ -612,6 +612,7 @@ static PciChipsets RADEONPciChipsets[] = {
{ PCI_CHIP_OLAND_6610, PCI_CHIP_OLAND_6610, RES_SHARED_VGA },
{ PCI_CHIP_OLAND_6611, PCI_CHIP_OLAND_6611, RES_SHARED_VGA },
{ PCI_CHIP_OLAND_6613, PCI_CHIP_OLAND_6613, RES_SHARED_VGA },
+ { PCI_CHIP_OLAND_6617, PCI_CHIP_OLAND_6617, RES_SHARED_VGA },
{ PCI_CHIP_OLAND_6620, PCI_CHIP_OLAND_6620, RES_SHARED_VGA },
{ PCI_CHIP_OLAND_6621, PCI_CHIP_OLAND_6621, RES_SHARED_VGA },
{ PCI_CHIP_OLAND_6623, PCI_CHIP_OLAND_6623, RES_SHARED_VGA },
@@ -632,6 +633,7 @@ static PciChipsets RADEONPciChipsets[] = {
{ PCI_CHIP_BONAIRE_6658, PCI_CHIP_BONAIRE_6658, RES_SHARED_VGA },
{ PCI_CHIP_BONAIRE_665C, PCI_CHIP_BONAIRE_665C, RES_SHARED_VGA },
{ PCI_CHIP_BONAIRE_665D, PCI_CHIP_BONAIRE_665D, RES_SHARED_VGA },
+ { PCI_CHIP_BONAIRE_665F, PCI_CHIP_BONAIRE_665F, RES_SHARED_VGA },
{ PCI_CHIP_KABINI_9830, PCI_CHIP_KABINI_9830, RES_SHARED_VGA },
{ PCI_CHIP_KABINI_9831, PCI_CHIP_KABINI_9831, RES_SHARED_VGA },
{ PCI_CHIP_KABINI_9832, PCI_CHIP_KABINI_9832, RES_SHARED_VGA },
diff --git a/driver/xf86-video-ati/src/radeon_pci_device_match_gen.h b/driver/xf86-video-ati/src/radeon_pci_device_match_gen.h
index eaf280a28..6dfe1e42f 100644
--- a/driver/xf86-video-ati/src/radeon_pci_device_match_gen.h
+++ b/driver/xf86-video-ati/src/radeon_pci_device_match_gen.h
@@ -612,6 +612,7 @@ static const struct pci_id_match radeon_device_match[] = {
ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6610, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6611, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6613, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6617, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6620, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6621, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_OLAND_6623, 0 ),
@@ -632,6 +633,7 @@ static const struct pci_id_match radeon_device_match[] = {
ATI_DEVICE_MATCH( PCI_CHIP_BONAIRE_6658, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_BONAIRE_665C, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_BONAIRE_665D, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_BONAIRE_665F, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_KABINI_9830, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_KABINI_9831, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_KABINI_9832, 0 ),
diff --git a/driver/xf86-video-ati/src/radeon_present.c b/driver/xf86-video-ati/src/radeon_present.c
new file mode 100644
index 000000000..bd4d8f284
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_present.c
@@ -0,0 +1,465 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "radeon.h"
+
+#ifdef HAVE_PRESENT_H
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <poll.h>
+#include <sys/time.h>
+#include <time.h>
+#include <errno.h>
+
+#include "radeon_bo_helper.h"
+#include "radeon_glamor.h"
+#include "radeon_video.h"
+
+#include "present.h"
+
+struct radeon_present_vblank_event {
+ uint64_t event_id;
+ xf86CrtcPtr crtc;
+};
+
+static uint32_t crtc_select(int crtc_id)
+{
+ if (crtc_id > 1)
+ return crtc_id << DRM_VBLANK_HIGH_CRTC_SHIFT;
+ else if (crtc_id > 0)
+ return DRM_VBLANK_SECONDARY;
+ else
+ return 0;
+}
+
+static RRCrtcPtr
+radeon_present_get_crtc(WindowPtr window)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ ScrnInfoPtr pScrn = xf86ScreenToScrn(screen);
+ xf86CrtcPtr crtc;
+ RRCrtcPtr randr_crtc = NULL;
+
+ crtc = radeon_pick_best_crtc(pScrn, FALSE,
+ window->drawable.x,
+ window->drawable.x + window->drawable.width,
+ window->drawable.y,
+ window->drawable.y + window->drawable.height);
+
+ /* Make sure the CRTC is valid and this is the real front buffer */
+ if (crtc != NULL && !crtc->rotatedData)
+ randr_crtc = crtc->randr_crtc;
+
+ return randr_crtc;
+}
+
+static int
+radeon_present_get_ust_msc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc)
+{
+ xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_crtc->driver_private;
+
+ if (drmmode_crtc->dpms_mode != DPMSModeOn)
+ return BadAlloc;
+
+ return drmmode_crtc_get_ust_msc(xf86_crtc, ust, msc);
+}
+
+/*
+ * Flush the DRM event queue when full; this
+ * makes space for new requests
+ */
+static Bool
+radeon_present_flush_drm_events(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ drmmode_crtc_private_ptr drmmode_crtc = xf86_config->crtc[0]->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ struct pollfd p = { .fd = drmmode->fd, .events = POLLIN };
+ int r;
+
+ do {
+ r = poll(&p, 1, 0);
+ } while (r == -1 && (errno == EINTR || errno == EAGAIN));
+
+ if (r <= 0)
+ return 0;
+
+ return drmHandleEvent(drmmode->fd, &drmmode->event_context) >= 0;
+}
+
+/*
+ * Called when the queued vblank event has occurred
+ */
+static void
+radeon_present_vblank_handler(ScrnInfoPtr scrn, unsigned int msc,
+ uint64_t usec, void *data)
+{
+ struct radeon_present_vblank_event *event = data;
+
+ present_event_notify(event->event_id, usec, msc);
+ free(event);
+}
+
+/*
+ * Called when the queued vblank is aborted
+ */
+static void
+radeon_present_vblank_abort(ScrnInfoPtr scrn, void *data)
+{
+ struct radeon_present_vblank_event *event = data;
+
+ free(event);
+}
+
+/*
+ * Queue an event to report back to the Present extension when the specified
+ * MSC has past
+ */
+static int
+radeon_present_queue_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
+{
+ xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+ ScreenPtr screen = crtc->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ int crtc_id = drmmode_get_crtc_id(xf86_crtc);
+ struct radeon_present_vblank_event *event;
+ struct radeon_drm_queue_entry *queue;
+ drmVBlank vbl;
+ int ret;
+
+ event = calloc(sizeof(struct radeon_present_vblank_event), 1);
+ if (!event)
+ return BadAlloc;
+ event->event_id = event_id;
+ queue = radeon_drm_queue_alloc(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT,
+ event_id, event,
+ radeon_present_vblank_handler,
+ radeon_present_vblank_abort);
+ if (!queue) {
+ free(event);
+ return BadAlloc;
+ }
+
+ vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT | crtc_select(crtc_id);
+ vbl.request.sequence = msc;
+ vbl.request.signal = (unsigned long)queue;
+ for (;;) {
+ ret = drmWaitVBlank(info->dri2.drm_fd, &vbl);
+ if (!ret)
+ break;
+ if (errno != EBUSY || !radeon_present_flush_drm_events(screen)) {
+ radeon_drm_abort_entry(queue);
+ return BadAlloc;
+ }
+ }
+
+ return Success;
+}
+
+/*
+ * Remove a pending vblank event from the DRM queue so that it is not reported
+ * to the extension
+ */
+static void
+radeon_present_abort_vblank(RRCrtcPtr crtc, uint64_t event_id, uint64_t msc)
+{
+ radeon_drm_abort_id(event_id);
+}
+
+/*
+ * Flush our batch buffer when requested by the Present extension.
+ */
+static void
+radeon_present_flush(WindowPtr window)
+{
+ radeon_cs_flush_indirect(xf86ScreenToScrn(window->drawable.pScreen));
+}
+
+static uint32_t
+radeon_present_get_pixmap_tiling_flags(RADEONInfoPtr info, PixmapPtr pixmap)
+{
+ uint32_t tiling_flags = radeon_get_pixmap_tiling_flags(pixmap);
+
+ /* Micro tiling is always enabled with macro tiling on >= R600, so we
+ * can ignore the micro tiling bit in that case
+ */
+ if ((tiling_flags & RADEON_TILING_MACRO) &&
+ info->ChipFamily >= CHIP_FAMILY_R600)
+ tiling_flags &= ~RADEON_TILING_MICRO;
+
+ return tiling_flags;
+}
+
+/*
+ * Test to see if page flipping is possible on the target crtc
+ */
+static Bool
+radeon_present_check_flip(RRCrtcPtr crtc, WindowPtr window, PixmapPtr pixmap,
+ Bool sync_flip)
+{
+ ScreenPtr screen = window->drawable.pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ PixmapPtr screen_pixmap;
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int num_crtcs_on;
+ int i;
+
+ if (!scrn->vtSema)
+ return FALSE;
+
+ if (!info->allowPageFlip)
+ return FALSE;
+
+ if (!sync_flip)
+ return FALSE;
+
+ if (info->drmmode.dri2_flipping)
+ 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;
+
+ for (i = 0, num_crtcs_on = 0; i < config->num_crtc; i++) {
+ drmmode_crtc_private_ptr drmmode_crtc = config->crtc[i]->driver_private;
+
+ if (!config->crtc[i]->enabled)
+ continue;
+
+ if (!drmmode_crtc || drmmode_crtc->rotate.bo != NULL)
+ return FALSE;
+
+ if (drmmode_crtc->dpms_mode == DPMSModeOn)
+ num_crtcs_on++;
+ }
+
+ return num_crtcs_on > 0;
+}
+
+/*
+ * Once the flip has been completed on all CRTCs, notify the
+ * extension code telling it when that happened
+ */
+static void
+radeon_present_flip_event(ScrnInfoPtr scrn, uint32_t msc, uint64_t ust, void *pageflip_data)
+{
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ struct radeon_present_vblank_event *event = pageflip_data;
+
+ if (!event->crtc)
+ info->drmmode.present_flipping = FALSE;
+
+ present_event_notify(event->event_id, ust, msc);
+ free(event);
+}
+
+/*
+ * The flip has been aborted, free the structure
+ */
+static void
+radeon_present_flip_abort(ScrnInfoPtr scrn, void *pageflip_data)
+{
+ struct radeon_present_vblank_event *event = pageflip_data;
+
+ free(event);
+}
+
+/*
+ * Queue a flip on 'crtc' to 'pixmap' at 'target_msc'. If 'sync_flip' is true,
+ * then wait for vblank. Otherwise, flip immediately
+ */
+static Bool
+radeon_present_flip(RRCrtcPtr crtc, uint64_t event_id, uint64_t target_msc,
+ PixmapPtr pixmap, Bool sync_flip)
+{
+ ScreenPtr screen = crtc->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ struct radeon_present_vblank_event *event;
+ xf86CrtcPtr xf86_crtc = crtc->devPrivate;
+ int crtc_id = xf86_crtc ? drmmode_get_crtc_id(xf86_crtc) : -1;
+ uint32_t handle;
+ Bool ret;
+
+ if (!radeon_present_check_flip(crtc, screen->root, pixmap, sync_flip))
+ return FALSE;
+
+ if (!radeon_get_pixmap_handle(pixmap, &handle))
+ return FALSE;
+
+ event = calloc(1, sizeof(struct radeon_present_vblank_event));
+ if (!event)
+ return FALSE;
+
+ event->event_id = event_id;
+ event->crtc = xf86_crtc;
+
+ ret = radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle,
+ event_id, event, crtc_id,
+ radeon_present_flip_event,
+ radeon_present_flip_abort);
+ if (!ret)
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR, "present flip failed\n");
+ else
+ info->drmmode.present_flipping = TRUE;
+
+ return ret;
+}
+
+/*
+ * Queue a flip back to the normal frame buffer
+ */
+static void
+radeon_present_unflip(ScreenPtr screen, uint64_t event_id)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ struct radeon_present_vblank_event *event;
+ PixmapPtr pixmap = screen->GetScreenPixmap(screen);
+ uint32_t handle;
+ int i;
+
+ if (!radeon_present_check_flip(NULL, screen->root, pixmap, TRUE))
+ goto modeset;
+
+ if (!radeon_get_pixmap_handle(pixmap, &handle)) {
+ ErrorF("%s: radeon_get_pixmap_handle failed, display might freeze\n",
+ __func__);
+ goto modeset;
+ }
+
+ event = calloc(1, sizeof(struct radeon_present_vblank_event));
+ if (!event) {
+ ErrorF("%s: calloc failed, display might freeze\n", __func__);
+ goto modeset;
+ }
+
+ event->event_id = event_id;
+
+ if (radeon_do_pageflip(scrn, RADEON_DRM_QUEUE_CLIENT_DEFAULT, handle,
+ event_id, event, -1, radeon_present_flip_event,
+ radeon_present_flip_abort))
+ return;
+
+modeset:
+ for (i = 0; i < config->num_crtc; i++) {
+ xf86CrtcPtr crtc = config->crtc[i];
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ if (!crtc->enabled)
+ continue;
+
+ if (drmmode_crtc->dpms_mode == DPMSModeOn)
+ crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation,
+ crtc->x, crtc->y);
+ else
+ drmmode_crtc->need_modeset = TRUE;
+ }
+
+ present_event_notify(event_id, 0, 0);
+
+ info->drmmode.present_flipping = FALSE;
+}
+
+static present_screen_info_rec radeon_present_screen_info = {
+ .version = 0,
+
+ .get_crtc = radeon_present_get_crtc,
+ .get_ust_msc = radeon_present_get_ust_msc,
+ .queue_vblank = radeon_present_queue_vblank,
+ .abort_vblank = radeon_present_abort_vblank,
+ .flush = radeon_present_flush,
+
+ .capabilities = PresentCapabilityNone,
+ .check_flip = radeon_present_check_flip,
+ .flip = radeon_present_flip,
+ .unflip = radeon_present_unflip,
+};
+
+static Bool
+radeon_present_has_async_flip(ScreenPtr screen)
+{
+#ifdef DRM_CAP_ASYNC_PAGE_FLIP
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ int ret;
+ uint64_t value;
+
+ ret = drmGetCap(info->dri2.drm_fd, DRM_CAP_ASYNC_PAGE_FLIP, &value);
+ if (ret == 0)
+ return value == 1;
+#endif
+ return FALSE;
+}
+
+Bool
+radeon_present_screen_init(ScreenPtr screen)
+{
+ if (radeon_present_has_async_flip(screen))
+ radeon_present_screen_info.capabilities |= PresentCapabilityAsync;
+
+ if (!present_screen_init(screen, &radeon_present_screen_info)) {
+ xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_WARNING,
+ "Present extension disabled because present_screen_init failed\n");
+ return FALSE;
+ }
+
+ xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+ "Present extension enabled\n");
+
+ return TRUE;
+}
+
+#else /* !HAVE_PRESENT_H */
+
+Bool
+radeon_present_screen_init(ScreenPtr screen)
+{
+ xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+ "Present extension disabled because present.h not available at "
+ "build time\n");
+
+ return FALSE;
+}
+
+#endif
diff --git a/driver/xf86-video-ati/src/radeon_probe.c b/driver/xf86-video-ati/src/radeon_probe.c
index ad1e96ea9..65cf0c9fa 100644
--- a/driver/xf86-video-ati/src/radeon_probe.c
+++ b/driver/xf86-video-ati/src/radeon_probe.c
@@ -154,7 +154,6 @@ radeon_get_scrninfo(int entity_num, void *pci_dev)
*/
{
DevUnion *pPriv;
- RADEONEntPtr pRADEONEnt;
xf86SetEntitySharable(entity_num);
@@ -166,14 +165,8 @@ radeon_get_scrninfo(int entity_num, void *pci_dev)
xf86SetEntityInstanceForScreen(pScrn, pEnt->index, xf86GetNumEntityInstances(pEnt->index) - 1);
- if (!pPriv->ptr) {
+ if (!pPriv->ptr)
pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1);
- pRADEONEnt = pPriv->ptr;
- pRADEONEnt->HasSecondary = FALSE;
- } else {
- pRADEONEnt = pPriv->ptr;
- pRADEONEnt->HasSecondary = TRUE;
- }
}
free(pEnt);
@@ -271,10 +264,8 @@ radeon_platform_probe(DriverPtr pDriver,
if (!pPriv->ptr) {
pPriv->ptr = xnfcalloc(sizeof(RADEONEntRec), 1);
pRADEONEnt = pPriv->ptr;
- pRADEONEnt->HasSecondary = FALSE;
} else {
pRADEONEnt = pPriv->ptr;
- pRADEONEnt->HasSecondary = TRUE;
}
pRADEONEnt->platform_dev = dev;
}
diff --git a/driver/xf86-video-ati/src/radeon_probe.h b/driver/xf86-video-ati/src/radeon_probe.h
index 3fe4644c3..258c7be1d 100644
--- a/driver/xf86-video-ati/src/radeon_probe.h
+++ b/driver/xf86-video-ati/src/radeon_probe.h
@@ -132,16 +132,13 @@ typedef struct {
typedef struct
{
- Bool HasSecondary;
Bool HasCRTC2; /* All cards except original Radeon */
- ScrnInfoPtr pSecondaryScrn;
- ScrnInfoPtr pPrimaryScrn;
-
int fd; /* for sharing across zaphod heads */
int fd_ref;
unsigned long fd_wakeup_registered; /* server generation for which fd has been registered for wakeup handling */
int fd_wakeup_ref;
+ unsigned int assigned_crtcs;
#ifdef XSERVER_PLATFORM_BUS
struct xf86_platform_device *platform_dev;
#endif
diff --git a/driver/xf86-video-ati/src/radeon_sync.c b/driver/xf86-video-ati/src/radeon_sync.c
new file mode 100644
index 000000000..d9ffbaf8e
--- /dev/null
+++ b/driver/xf86-video-ati/src/radeon_sync.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright © 2013-2014 Intel Corporation
+ * Copyright © 2015 Advanced Micro Devices, Inc.
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting documentation, and
+ * that the name of the copyright holders not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. The copyright holders make no representations
+ * about the suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+#include "radeon.h"
+
+#ifdef HAVE_MISYNCSHM_H
+
+#include "misync.h"
+#include "misyncshm.h"
+#include "misyncstr.h"
+
+/*
+ * This whole file exists to wrap a sync fence trigger operation
+ * so that we can flush the batch buffer to provide serialization
+ * between the server and the shm fence client
+ */
+
+static DevPrivateKeyRec radeon_sync_fence_private_key;
+
+typedef struct _radeon_sync_fence_private {
+ SyncFenceSetTriggeredFunc set_triggered;
+} radeon_sync_fence_private;
+
+#define SYNC_FENCE_PRIV(pFence) \
+ (radeon_sync_fence_private *) dixLookupPrivate(&pFence->devPrivates, &radeon_sync_fence_private_key)
+
+static void
+radeon_sync_fence_set_triggered (SyncFence *fence)
+{
+ ScreenPtr screen = fence->pScreen;
+ radeon_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
+
+ /* Flush pending rendering operations */
+ radeon_cs_flush_indirect(xf86ScreenToScrn(screen));
+
+ fence->funcs.SetTriggered = private->set_triggered;
+ fence->funcs.SetTriggered(fence);
+ private->set_triggered = fence->funcs.SetTriggered;
+ fence->funcs.SetTriggered = radeon_sync_fence_set_triggered;
+}
+
+static void
+radeon_sync_create_fence(ScreenPtr screen,
+ SyncFence *fence,
+ Bool initially_triggered)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
+ radeon_sync_fence_private *private = SYNC_FENCE_PRIV(fence);
+
+ screen_funcs->CreateFence = info->CreateFence;
+ screen_funcs->CreateFence(screen, fence, initially_triggered);
+ info->CreateFence = screen_funcs->CreateFence;
+ screen_funcs->CreateFence = radeon_sync_create_fence;
+
+ private->set_triggered = fence->funcs.SetTriggered;
+ fence->funcs.SetTriggered = radeon_sync_fence_set_triggered;
+}
+
+Bool
+radeon_sync_init(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ SyncScreenFuncsPtr screen_funcs;
+
+ if (!miSyncShmScreenInit(screen)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "SYNC extension fences disabled because "
+ "miSyncShmScreenInit failed\n");
+ return FALSE;
+ }
+
+ if (!dixPrivateKeyRegistered(&radeon_sync_fence_private_key)) {
+ if (!dixRegisterPrivateKey(&radeon_sync_fence_private_key,
+ PRIVATE_SYNC_FENCE,
+ sizeof (radeon_sync_fence_private))) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "SYNC extension fences disabled because "
+ "dixRegisterPrivateKey failed\n");
+ return FALSE;
+ }
+ }
+
+ xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+ "SYNC extension fences enabled\n");
+
+ screen_funcs = miSyncGetScreenFuncs(screen);
+ info->CreateFence = screen_funcs->CreateFence;
+ screen_funcs->CreateFence = radeon_sync_create_fence;
+ return TRUE;
+}
+
+void
+radeon_sync_close(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ SyncScreenFuncsPtr screen_funcs = miSyncGetScreenFuncs(screen);
+
+ if (screen_funcs && info->CreateFence)
+ screen_funcs->CreateFence = info->CreateFence;
+
+ info->CreateFence = NULL;
+}
+
+#else /* !HAVE_MISYNCSHM_H */
+
+Bool
+radeon_sync_init(ScreenPtr screen)
+{
+ xf86DrvMsg(xf86ScreenToScrn(screen)->scrnIndex, X_INFO,
+ "SYNC extension fences disabled because misyncshm.h not "
+ "available at build time\n");
+
+ return FALSE;
+}
+
+void
+radeon_sync_close(ScreenPtr screen)
+{
+}
+
+#endif
diff --git a/driver/xf86-video-ati/src/radeon_video.c b/driver/xf86-video-ati/src/radeon_video.c
index cbfd554b2..48b06e26d 100644
--- a/driver/xf86-video-ati/src/radeon_video.c
+++ b/driver/xf86-video-ati/src/radeon_video.c
@@ -9,6 +9,7 @@
#include <math.h>
#include "radeon.h"
+#include "radeon_glamor.h"
#include "radeon_reg.h"
#include "radeon_probe.h"
#include "radeon_video.h"
@@ -73,18 +74,12 @@ Bool radeon_crtc_is_enabled(xf86CrtcPtr crtc)
return drmmode_crtc->dpms_mode == DPMSModeOn;
}
-uint32_t radeon_get_interpolated_vblanks(xf86CrtcPtr crtc)
-{
- drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
- return drmmode_crtc->interpolated_vblanks;
-}
-
xf86CrtcPtr
radeon_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled,
int x1, int x2, int y1, int y2)
{
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
- int coverage, best_coverage, c;
+ int coverage, best_coverage, c, cd;
BoxRec box, crtc_box, cover_box;
RROutputPtr primary_output = NULL;
xf86CrtcPtr best_crtc = NULL, primary_crtc = NULL;
@@ -108,38 +103,30 @@ radeon_pick_best_crtc(ScrnInfoPtr pScrn, Bool consider_disabled,
if (primary_output && primary_output->crtc)
primary_crtc = primary_output->crtc->devPrivate;
- /* first consider only enabled CRTCs */
- for (c = 0; c < xf86_config->num_crtc; c++) {
- xf86CrtcPtr crtc = xf86_config->crtc[c];
-
- if (!radeon_crtc_is_enabled(crtc))
- continue;
-
- radeon_crtc_box(crtc, &crtc_box);
- radeon_box_intersect(&cover_box, &crtc_box, &box);
- coverage = radeon_box_area(&cover_box);
- if (coverage > best_coverage ||
- (coverage == best_coverage && crtc == primary_crtc)) {
- best_crtc = crtc;
- best_coverage = coverage;
- }
- }
- if (best_crtc || !consider_disabled)
- return best_crtc;
-
- /* if we found nothing, repeat the search including disabled CRTCs */
- for (c = 0; c < xf86_config->num_crtc; c++) {
- xf86CrtcPtr crtc = xf86_config->crtc[c];
-
- radeon_crtc_box(crtc, &crtc_box);
- radeon_box_intersect(&cover_box, &crtc_box, &box);
- coverage = radeon_box_area(&cover_box);
- if (coverage > best_coverage ||
- (coverage == best_coverage && crtc == primary_crtc)) {
- best_crtc = crtc;
- best_coverage = coverage;
+ /* first consider only enabled CRTCs
+ * then on second pass consider disabled ones
+ */
+ for (cd = 0; cd < (consider_disabled ? 2 : 1); cd++) {
+ for (c = 0; c < xf86_config->num_crtc; c++) {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (!cd && !radeon_crtc_is_enabled(crtc))
+ continue;
+
+ radeon_crtc_box(crtc, &crtc_box);
+ radeon_box_intersect(&cover_box, &crtc_box, &box);
+ coverage = radeon_box_area(&cover_box);
+ if (coverage > best_coverage ||
+ (coverage == best_coverage &&
+ crtc == primary_crtc)) {
+ best_crtc = crtc;
+ best_coverage = coverage;
+ }
}
+ if (best_crtc)
+ break;
}
+
return best_crtc;
}
@@ -158,7 +145,7 @@ void RADEONInitVideo(ScreenPtr pScreen)
return;
num_adaptors = xf86XVListGenericAdaptors(pScrn, &adaptors);
- newAdaptors = malloc((num_adaptors + 2) * sizeof(XF86VideoAdaptorPtr *));
+ newAdaptors = malloc((num_adaptors + 2) * sizeof(*newAdaptors));
if (newAdaptors == NULL)
return;
diff --git a/driver/xf86-video-ati/src/radeon_video.h b/driver/xf86-video-ati/src/radeon_video.h
index 2a0929546..e6068e86b 100644
--- a/driver/xf86-video-ati/src/radeon_video.h
+++ b/driver/xf86-video-ati/src/radeon_video.h
@@ -101,6 +101,5 @@ RADEONCopyMungedData(ScrnInfoPtr pScrn,
unsigned int dstPitch, unsigned int h, unsigned int w);
Bool radeon_crtc_is_enabled(xf86CrtcPtr crtc);
-uint32_t radeon_get_interpolated_vblanks(xf86CrtcPtr crtc);
#endif