xf86-video-ati: Branch 'master' - 3 commits
Michel Dänzer
daenzer at kemper.freedesktop.org
Wed Jul 11 04:45:37 PDT 2012
configure.ac | 14
man/radeon.man | 45
src/Makefile.am | 14
src/ati_pciids_gen.h | 39
src/drmmode_display.c | 8
src/pcidb/ati_pciids.csv | 39
src/radeon.h | 125 ++
src/radeon_accel.c | 7
src/radeon_bo_helper.c | 177 +++
src/radeon_bo_helper.h | 31
src/radeon_chipinfo_gen.h | 39
src/radeon_chipset_gen.h | 39
src/radeon_dri2.c | 244 +++-
src/radeon_exa.c | 192 ---
src/radeon_glamor.c | 347 +++++++
src/radeon_glamor.h | 98 +
src/radeon_glamor_wrappers.c | 1870 ++++++++++++++++++++++++++++++++++++++
src/radeon_glamor_wrappers.h | 179 +++
src/radeon_kms.c | 44
src/radeon_pci_chipset_gen.h | 39
src/radeon_pci_device_match_gen.h | 39
src/radeon_probe.h | 3
src/radeon_version.h | 1
23 files changed, 3333 insertions(+), 300 deletions(-)
New commits:
commit ef8a404391036d8aa814dbda2407c789b8a64b92
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Thu Jul 5 20:14:48 2012 +0200
Initial SI support.
Defaults to shadowfb. 3D acceleration is available with glamor. 2D
acceleration is disabled until the radeonsi driver can handle glamor's
shaders.
v2: add chip flags (Alex Deucher)
Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
Signed-off-by: Alex Deucher <alexander.deucher at amd.com>
diff --git a/man/radeon.man b/man/radeon.man
index be50314..de1f6ec 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -180,6 +180,12 @@ Radeon HD 6430/6450/6470/6490
Radeon HD 6950/6970/6990
.TP 12
.B ARUBA
+.TP 12
+.B TAHITI
+.TP 12
+.B PITCAIRN
+.TP 12
+.B VERDE
.PD
.SH CONFIGURATION DETAILS
Please refer to __xconfigfile__(__filemansuffix__) for general configuration
diff --git a/src/Makefile.am b/src/Makefile.am
index da94927..3ee292a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -68,6 +68,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
@@ -96,6 +97,7 @@ EXTRA_DIST = \
radeon_exa_funcs.c \
radeon_exa_shared.h \
radeon_glamor.h \
+ radeon_glamor_wrappers.h \
radeon.h \
radeon_probe.h \
radeon_reg.h \
diff --git a/src/ati_pciids_gen.h b/src/ati_pciids_gen.h
index b08ad88..5509120 100644
--- a/src/ati_pciids_gen.h
+++ b/src/ati_pciids_gen.h
@@ -617,3 +617,42 @@
#define PCI_CHIP_ARUBA_99A0 0x99A0
#define PCI_CHIP_ARUBA_99A2 0x99A2
#define PCI_CHIP_ARUBA_99A4 0x99A4
+#define PCI_CHIP_TAHITI_6780 0x6780
+#define PCI_CHIP_TAHITI_6784 0x6784
+#define PCI_CHIP_TAHITI_6788 0x6788
+#define PCI_CHIP_TAHITI_678A 0x678A
+#define PCI_CHIP_TAHITI_6790 0x6790
+#define PCI_CHIP_TAHITI_6798 0x6798
+#define PCI_CHIP_TAHITI_6799 0x6799
+#define PCI_CHIP_TAHITI_679A 0x679A
+#define PCI_CHIP_TAHITI_679E 0x679E
+#define PCI_CHIP_TAHITI_679F 0x679F
+#define PCI_CHIP_PITCAIRN_6800 0x6800
+#define PCI_CHIP_PITCAIRN_6801 0x6801
+#define PCI_CHIP_PITCAIRN_6802 0x6802
+#define PCI_CHIP_PITCAIRN_6808 0x6808
+#define PCI_CHIP_PITCAIRN_6809 0x6809
+#define PCI_CHIP_PITCAIRN_6810 0x6810
+#define PCI_CHIP_PITCAIRN_6818 0x6818
+#define PCI_CHIP_PITCAIRN_6819 0x6819
+#define PCI_CHIP_PITCAIRN_684C 0x684C
+#define PCI_CHIP_VERDE_6820 0x6820
+#define PCI_CHIP_VERDE_6821 0x6821
+#define PCI_CHIP_VERDE_6823 0x6823
+#define PCI_CHIP_VERDE_6824 0x6824
+#define PCI_CHIP_VERDE_6825 0x6825
+#define PCI_CHIP_VERDE_6826 0x6826
+#define PCI_CHIP_VERDE_6827 0x6827
+#define PCI_CHIP_VERDE_6828 0x6828
+#define PCI_CHIP_VERDE_6829 0x6829
+#define PCI_CHIP_VERDE_682B 0x682B
+#define PCI_CHIP_VERDE_682D 0x682D
+#define PCI_CHIP_VERDE_682F 0x682F
+#define PCI_CHIP_VERDE_6830 0x6830
+#define PCI_CHIP_VERDE_6831 0x6831
+#define PCI_CHIP_VERDE_6837 0x6837
+#define PCI_CHIP_VERDE_6838 0x6838
+#define PCI_CHIP_VERDE_6839 0x6839
+#define PCI_CHIP_VERDE_683B 0x683B
+#define PCI_CHIP_VERDE_683D 0x683D
+#define PCI_CHIP_VERDE_683F 0x683F
diff --git a/src/pcidb/ati_pciids.csv b/src/pcidb/ati_pciids.csv
index 501a0f6..29ff26b 100644
--- a/src/pcidb/ati_pciids.csv
+++ b/src/pcidb/ati_pciids.csv
@@ -618,3 +618,42 @@
"0x99A0","ARUBA_99A0","ARUBA",1,,,,,"ARUBA"
"0x99A2","ARUBA_99A2","ARUBA",1,,,,,"ARUBA"
"0x99A4","ARUBA_99A4","ARUBA",,,,,,"ARUBA"
+"0x6780","TAHITI_6780","TAHITI",,,,,,"TAHITI"
+"0x6784","TAHITI_6784","TAHITI",,,,,,"TAHITI"
+"0x6788","TAHITI_6788","TAHITI",,,,,,"TAHITI"
+"0x678A","TAHITI_678A","TAHITI",,,,,,"TAHITI"
+"0x6790","TAHITI_6790","TAHITI",,,,,,"TAHITI"
+"0x6798","TAHITI_6798","TAHITI",,,,,,"TAHITI"
+"0x6799","TAHITI_6799","TAHITI",,,,,,"TAHITI"
+"0x679A","TAHITI_679A","TAHITI",,,,,,"TAHITI"
+"0x679E","TAHITI_679E","TAHITI",,,,,,"TAHITI"
+"0x679F","TAHITI_679F","TAHITI",,,,,,"TAHITI"
+"0x6800","PITCAIRN_6800","PITCAIRN",1,,,,,"PITCAIRN"
+"0x6801","PITCAIRN_6801","PITCAIRN",1,,,,,"PITCAIRN"
+"0x6802","PITCAIRN_6802","PITCAIRN",1,,,,,"PITCAIRN"
+"0x6808","PITCAIRN_6808","PITCAIRN",,,,,,"PITCAIRN"
+"0x6809","PITCAIRN_6809","PITCAIRN",,,,,,"PITCAIRN"
+"0x6810","PITCAIRN_6810","PITCAIRN",,,,,,"PITCAIRN"
+"0x6818","PITCAIRN_6818","PITCAIRN",,,,,,"PITCAIRN"
+"0x6819","PITCAIRN_6819","PITCAIRN",,,,,,"PITCAIRN"
+"0x684C","PITCAIRN_684C","PITCAIRN",,,,,,"PITCAIRN"
+"0x6820","VERDE_6820","VERDE",1,,,,,"VERDE"
+"0x6821","VERDE_6821","VERDE",1,,,,,"VERDE"
+"0x6823","VERDE_6823","VERDE",1,,,,,"VERDE"
+"0x6824","VERDE_6824","VERDE",1,,,,,"VERDE"
+"0x6825","VERDE_6825","VERDE",1,,,,,"VERDE"
+"0x6826","VERDE_6826","VERDE",1,,,,,"VERDE"
+"0x6827","VERDE_6827","VERDE",1,,,,,"VERDE"
+"0x6828","VERDE_6828","VERDE",,,,,,"VERDE"
+"0x6829","VERDE_6829","VERDE",,,,,,"VERDE"
+"0x682B","VERDE_682B","VERDE",1,,,,,"VERDE"
+"0x682D","VERDE_682D","VERDE",1,,,,,"VERDE"
+"0x682F","VERDE_682F","VERDE",1,,,,,"VERDE"
+"0x6830","VERDE_6830","VERDE",1,,,,,"VERDE"
+"0x6831","VERDE_6831","VERDE",1,,,,,"VERDE"
+"0x6837","VERDE_6837","VERDE",,,,,,"VERDE"
+"0x6838","VERDE_6838","VERDE",,,,,,"VERDE"
+"0x6839","VERDE_6839","VERDE",,,,,,"VERDE"
+"0x683B","VERDE_683B","VERDE",,,,,,"VERDE"
+"0x683D","VERDE_683D","VERDE",,,,,,"VERDE"
+"0x683F","VERDE_683F","VERDE",,,,,,"VERDE"
diff --git a/src/radeon_chipinfo_gen.h b/src/radeon_chipinfo_gen.h
index c64c921..295a824 100644
--- a/src/radeon_chipinfo_gen.h
+++ b/src/radeon_chipinfo_gen.h
@@ -537,4 +537,43 @@ static RADEONCardInfo RADEONCards[] = {
{ 0x99A0, CHIP_FAMILY_ARUBA, 1, 0, 0, 0, 0 },
{ 0x99A2, CHIP_FAMILY_ARUBA, 1, 0, 0, 0, 0 },
{ 0x99A4, CHIP_FAMILY_ARUBA, 0, 0, 0, 0, 0 },
+ { 0x6780, CHIP_FAMILY_TAHITI, 0, 0, 0, 0, 0 },
+ { 0x6784, CHIP_FAMILY_TAHITI, 0, 0, 0, 0, 0 },
+ { 0x6788, CHIP_FAMILY_TAHITI, 0, 0, 0, 0, 0 },
+ { 0x678A, CHIP_FAMILY_TAHITI, 0, 0, 0, 0, 0 },
+ { 0x6790, CHIP_FAMILY_TAHITI, 0, 0, 0, 0, 0 },
+ { 0x6798, CHIP_FAMILY_TAHITI, 0, 0, 0, 0, 0 },
+ { 0x6799, CHIP_FAMILY_TAHITI, 0, 0, 0, 0, 0 },
+ { 0x679A, CHIP_FAMILY_TAHITI, 0, 0, 0, 0, 0 },
+ { 0x679E, CHIP_FAMILY_TAHITI, 0, 0, 0, 0, 0 },
+ { 0x679F, CHIP_FAMILY_TAHITI, 0, 0, 0, 0, 0 },
+ { 0x6800, CHIP_FAMILY_PITCAIRN, 1, 0, 0, 0, 0 },
+ { 0x6801, CHIP_FAMILY_PITCAIRN, 1, 0, 0, 0, 0 },
+ { 0x6802, CHIP_FAMILY_PITCAIRN, 1, 0, 0, 0, 0 },
+ { 0x6808, CHIP_FAMILY_PITCAIRN, 0, 0, 0, 0, 0 },
+ { 0x6809, CHIP_FAMILY_PITCAIRN, 0, 0, 0, 0, 0 },
+ { 0x6810, CHIP_FAMILY_PITCAIRN, 0, 0, 0, 0, 0 },
+ { 0x6818, CHIP_FAMILY_PITCAIRN, 0, 0, 0, 0, 0 },
+ { 0x6819, CHIP_FAMILY_PITCAIRN, 0, 0, 0, 0, 0 },
+ { 0x684C, CHIP_FAMILY_PITCAIRN, 0, 0, 0, 0, 0 },
+ { 0x6820, CHIP_FAMILY_VERDE, 1, 0, 0, 0, 0 },
+ { 0x6821, CHIP_FAMILY_VERDE, 1, 0, 0, 0, 0 },
+ { 0x6823, CHIP_FAMILY_VERDE, 1, 0, 0, 0, 0 },
+ { 0x6824, CHIP_FAMILY_VERDE, 1, 0, 0, 0, 0 },
+ { 0x6825, CHIP_FAMILY_VERDE, 1, 0, 0, 0, 0 },
+ { 0x6826, CHIP_FAMILY_VERDE, 1, 0, 0, 0, 0 },
+ { 0x6827, CHIP_FAMILY_VERDE, 1, 0, 0, 0, 0 },
+ { 0x6828, CHIP_FAMILY_VERDE, 0, 0, 0, 0, 0 },
+ { 0x6829, CHIP_FAMILY_VERDE, 0, 0, 0, 0, 0 },
+ { 0x682B, CHIP_FAMILY_VERDE, 1, 0, 0, 0, 0 },
+ { 0x682D, CHIP_FAMILY_VERDE, 1, 0, 0, 0, 0 },
+ { 0x682F, CHIP_FAMILY_VERDE, 1, 0, 0, 0, 0 },
+ { 0x6830, CHIP_FAMILY_VERDE, 1, 0, 0, 0, 0 },
+ { 0x6831, CHIP_FAMILY_VERDE, 1, 0, 0, 0, 0 },
+ { 0x6837, CHIP_FAMILY_VERDE, 0, 0, 0, 0, 0 },
+ { 0x6838, CHIP_FAMILY_VERDE, 0, 0, 0, 0, 0 },
+ { 0x6839, CHIP_FAMILY_VERDE, 0, 0, 0, 0, 0 },
+ { 0x683B, CHIP_FAMILY_VERDE, 0, 0, 0, 0, 0 },
+ { 0x683D, CHIP_FAMILY_VERDE, 0, 0, 0, 0, 0 },
+ { 0x683F, CHIP_FAMILY_VERDE, 0, 0, 0, 0, 0 },
};
diff --git a/src/radeon_chipset_gen.h b/src/radeon_chipset_gen.h
index 31b31ab..8e887ac 100644
--- a/src/radeon_chipset_gen.h
+++ b/src/radeon_chipset_gen.h
@@ -537,5 +537,44 @@ SymTabRec RADEONChipsets[] = {
{ PCI_CHIP_ARUBA_99A0, "ARUBA" },
{ PCI_CHIP_ARUBA_99A2, "ARUBA" },
{ PCI_CHIP_ARUBA_99A4, "ARUBA" },
+ { PCI_CHIP_TAHITI_6780, "TAHITI" },
+ { PCI_CHIP_TAHITI_6784, "TAHITI" },
+ { PCI_CHIP_TAHITI_6788, "TAHITI" },
+ { PCI_CHIP_TAHITI_678A, "TAHITI" },
+ { PCI_CHIP_TAHITI_6790, "TAHITI" },
+ { PCI_CHIP_TAHITI_6798, "TAHITI" },
+ { PCI_CHIP_TAHITI_6799, "TAHITI" },
+ { PCI_CHIP_TAHITI_679A, "TAHITI" },
+ { PCI_CHIP_TAHITI_679E, "TAHITI" },
+ { PCI_CHIP_TAHITI_679F, "TAHITI" },
+ { PCI_CHIP_PITCAIRN_6800, "PITCAIRN" },
+ { PCI_CHIP_PITCAIRN_6801, "PITCAIRN" },
+ { PCI_CHIP_PITCAIRN_6802, "PITCAIRN" },
+ { PCI_CHIP_PITCAIRN_6808, "PITCAIRN" },
+ { PCI_CHIP_PITCAIRN_6809, "PITCAIRN" },
+ { PCI_CHIP_PITCAIRN_6810, "PITCAIRN" },
+ { PCI_CHIP_PITCAIRN_6818, "PITCAIRN" },
+ { PCI_CHIP_PITCAIRN_6819, "PITCAIRN" },
+ { PCI_CHIP_PITCAIRN_684C, "PITCAIRN" },
+ { PCI_CHIP_VERDE_6820, "VERDE" },
+ { PCI_CHIP_VERDE_6821, "VERDE" },
+ { PCI_CHIP_VERDE_6823, "VERDE" },
+ { PCI_CHIP_VERDE_6824, "VERDE" },
+ { PCI_CHIP_VERDE_6825, "VERDE" },
+ { PCI_CHIP_VERDE_6826, "VERDE" },
+ { PCI_CHIP_VERDE_6827, "VERDE" },
+ { PCI_CHIP_VERDE_6828, "VERDE" },
+ { PCI_CHIP_VERDE_6829, "VERDE" },
+ { PCI_CHIP_VERDE_682B, "VERDE" },
+ { PCI_CHIP_VERDE_682D, "VERDE" },
+ { PCI_CHIP_VERDE_682F, "VERDE" },
+ { PCI_CHIP_VERDE_6830, "VERDE" },
+ { PCI_CHIP_VERDE_6831, "VERDE" },
+ { PCI_CHIP_VERDE_6837, "VERDE" },
+ { PCI_CHIP_VERDE_6838, "VERDE" },
+ { PCI_CHIP_VERDE_6839, "VERDE" },
+ { PCI_CHIP_VERDE_683B, "VERDE" },
+ { PCI_CHIP_VERDE_683D, "VERDE" },
+ { PCI_CHIP_VERDE_683F, "VERDE" },
{ -1, NULL }
};
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 12b198c..e16d551 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -1400,7 +1400,9 @@ radeon_dri2_screen_init(ScreenPtr pScreen)
info->dri2.device_name = drmGetDeviceNameFromFd(info->dri2.drm_fd);
- if ( (info->ChipFamily >= CHIP_FAMILY_R600) ) {
+ if ( (info->ChipFamily >= CHIP_FAMILY_TAHITI) ) {
+ dri2_info.driverName = SI_DRIVER_NAME;
+ } else if ( (info->ChipFamily >= CHIP_FAMILY_R600) ) {
dri2_info.driverName = R600_DRIVER_NAME;
} else if ( (info->ChipFamily >= CHIP_FAMILY_R300) ) {
dri2_info.driverName = R300_DRIVER_NAME;
diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c
index 232332e..714dde9 100644
--- a/src/radeon_glamor.c
+++ b/src/radeon_glamor.c
@@ -135,18 +135,85 @@ radeon_glamor_create_textured_pixmap(PixmapPtr pixmap)
return FALSE;
}
+Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap)
+{
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+ return priv && priv->bo;
+}
+
+Bool radeon_glamor_prepare_access(PixmapPtr pixmap, glamor_access_t access)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(pixmap->drawable.pScreen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ struct radeon_bo *bo;
+ int ret;
+
+ if (access == GLAMOR_GPU_ACCESS_RW || access == GLAMOR_GPU_ACCESS_RO)
+ return info->ChipFamily < CHIP_FAMILY_TAHITI;
+
+ bo = radeon_get_pixmap_bo(pixmap);
+ if (bo) {
+ /* When falling back to swrast, flush all pending operations */
+ if (info->ChipFamily < CHIP_FAMILY_TAHITI)
+ radeon_glamor_flush(scrn);
+
+ ret = radeon_bo_map(bo, 1);
+ if (ret) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "%s: bo map (tiling_flags %d, access %d) failed: %s\n",
+ __FUNCTION__,
+ radeon_get_pixmap_private(pixmap)->tiling_flags,
+ access,
+ strerror(-ret));
+ return FALSE;
+ }
+
+ pixmap->devPrivate.ptr = bo->ptr;
+ }
+
+ return TRUE;
+}
+
+void
+radeon_glamor_finish_access(PixmapPtr pixmap, glamor_access_t access)
+{
+ struct radeon_bo *bo;
+
+ switch(access) {
+ case GLAMOR_GPU_ACCESS_RW:
+ case GLAMOR_GPU_ACCESS_RO:
+ break;
+ case GLAMOR_CPU_ACCESS_RO:
+ case GLAMOR_CPU_ACCESS_RW:
+ bo = radeon_get_pixmap_bo(pixmap);
+ if (bo) {
+ radeon_bo_unmap(bo);
+ pixmap->devPrivate.ptr = NULL;
+ }
+ break;
+ default:
+ ErrorF("Invalid access mode %d\n", access);
+ }
+
+ return;
+}
+
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 (!(usage & RADEON_CREATE_PIXMAP_DRI2)) {
- pixmap = glamor_create_pixmap(screen, w, h, depth, usage);
- if (pixmap)
- return pixmap;
+ if (info->ChipFamily < CHIP_FAMILY_TAHITI) {
+ pixmap = glamor_create_pixmap(screen, w, h, depth, usage);
+ if (pixmap)
+ return pixmap;
+ } else
+ return fbCreatePixmap(screen, w, h, depth, usage);
}
if (w > 32767 || h > 32767)
@@ -230,9 +297,13 @@ Bool
radeon_glamor_init(ScreenPtr screen)
{
ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ unsigned int glamor_init_flags = GLAMOR_INVERTED_Y_AXIS | GLAMOR_USE_EGL_SCREEN;
- if (!glamor_init(screen, GLAMOR_INVERTED_Y_AXIS | GLAMOR_USE_EGL_SCREEN |
- GLAMOR_USE_SCREEN | GLAMOR_USE_PICTURE_SCREEN)) {
+ if (info->ChipFamily < CHIP_FAMILY_TAHITI)
+ glamor_init_flags |= GLAMOR_USE_SCREEN | GLAMOR_USE_PICTURE_SCREEN;
+
+ if (!glamor_init(screen, glamor_init_flags)) {
xf86DrvMsg(scrn->scrnIndex, X_ERROR,
"Failed to initialize glamor.\n");
return FALSE;
@@ -251,6 +322,13 @@ radeon_glamor_init(ScreenPtr screen)
#endif
return FALSE;
+ if (!(glamor_init_flags & GLAMOR_USE_SCREEN) &&
+ !glamor_screen_init(screen)) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "GLAMOR initialization failed\n");
+ return FALSE;
+ }
+
screen->CreatePixmap = radeon_glamor_create_pixmap;
screen->DestroyPixmap = radeon_glamor_destroy_pixmap;
diff --git a/src/radeon_glamor.h b/src/radeon_glamor.h
index 40c9092..f814e46 100644
--- a/src/radeon_glamor.h
+++ b/src/radeon_glamor.h
@@ -29,6 +29,7 @@
#ifdef USE_GLAMOR
+#include "radeon_glamor_wrappers.h"
#include "radeon_surface.h"
Bool radeon_glamor_pre_init(ScrnInfoPtr scrn);
@@ -42,6 +43,8 @@ Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap);
void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst);
Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap);
+Bool radeon_glamor_prepare_access(PixmapPtr pixmap, glamor_access_t access);
+void radeon_glamor_finish_access(PixmapPtr pixmap, glamor_access_t access);
struct radeon_pixmap {
struct radeon_surface surface;
@@ -85,6 +88,8 @@ static inline Bool radeon_glamor_create_textured_pixmap(PixmapPtr pixmap) { retu
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 Bool radeon_glamor_prepare_access(PixmapPtr pixmap, int access) { return FALSE; }
+static inline void radeon_glamor_finish_access(PixmapPtr pixmap, int access) {}
static inline struct radeon_pixmap *radeon_get_pixmap_private(PixmapPtr pixmap) { return NULL; }
diff --git a/src/radeon_glamor_wrappers.c b/src/radeon_glamor_wrappers.c
new file mode 100644
index 0000000..d0eb383
--- /dev/null
+++ b/src/radeon_glamor_wrappers.c
@@ -0,0 +1,1870 @@
+/*
+ * Copyright © 2001 Keith Packard
+ * 2010 Intel Corporation
+ * 2012 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_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "radeon_glamor_wrappers.h"
+#include "mipict.h"
+
+
+#if HAS_DEVPRIVATEKEYREC
+DevPrivateKeyRec glamor_screen_index;
+#else
+int glamor_screen_index;
+#endif
+
+/**
+ * glamor_get_drawable_pixmap() returns a 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. Note that
+ * coordinate translation is needed when drawing to the backing pixmap of a
+ * redirected window, and the translation coordinates are provided by calling
+ * glamor_get_drawable_pixmap() on the drawable.
+ */
+static PixmapPtr glamor_get_drawable_pixmap(DrawablePtr pDrawable)
+{
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ return pDrawable->pScreen->
+ GetWindowPixmap((WindowPtr) pDrawable);
+ else
+ return (PixmapPtr) pDrawable;
+}
+
+/**
+ * Sets the offsets to add to coordinates to make them address the same bits in
+ * the backing drawable. These coordinates are nonzero only for redirected
+ * windows.
+ */
+static void
+glamor_get_drawable_deltas(DrawablePtr pDrawable, PixmapPtr pPixmap,
+ int *xp, int *yp)
+{
+#ifdef COMPOSITE
+ if (pDrawable->type == DRAWABLE_WINDOW) {
+ *xp = -pPixmap->screen_x;
+ *yp = -pPixmap->screen_y;
+ return;
+ }
+#endif
+
+ *xp = 0;
+ *yp = 0;
+}
+
+/**
+ * glamor_drawable_is_offscreen() is a convenience wrapper for
+ * radeon_glamor_pixmap_is_offscreen().
+ */
+static Bool glamor_drawable_is_offscreen(DrawablePtr pDrawable)
+{
+ return radeon_glamor_pixmap_is_offscreen(glamor_get_drawable_pixmap(pDrawable));
+}
+
+/**
+ * glamor_prepare_access() is GLAMOR's wrapper for the driver's PrepareAccess() handler.
+ *
+ * It deals with waiting for synchronization with the card, determining if
+ * PrepareAccess() is necessary, and working around PrepareAccess() failure.
+ */
+static Bool glamor_prepare_access(DrawablePtr pDrawable, glamor_access_t access)
+{
+ PixmapPtr pPixmap = glamor_get_drawable_pixmap(pDrawable);
+
+ return radeon_glamor_prepare_access(pPixmap, access);
+}
+
+/**
+ * glamor_finish_access() is GLAMOR's wrapper for the driver's finish_access() handler.
+ *
+ * It deals with calling the driver's finish_access() only if necessary.
+ */
+static void glamor_finish_access(DrawablePtr pDrawable, glamor_access_t access)
+{
+ PixmapPtr pPixmap = glamor_get_drawable_pixmap(pDrawable);
+
+ radeon_glamor_finish_access(pPixmap, access);
+}
+
+static Bool glamor_prepare_access_window(WindowPtr pWin)
+{
+ if (pWin->backgroundState == BackgroundPixmap) {
+ if (!glamor_prepare_access
+ (&pWin->background.pixmap->drawable, GLAMOR_CPU_ACCESS_RO))
+ return FALSE;
+ }
+
+ if (pWin->borderIsPixel == FALSE) {
+ if (!glamor_prepare_access
+ (&pWin->border.pixmap->drawable, GLAMOR_CPU_ACCESS_RO)) {
+ if (pWin->backgroundState == BackgroundPixmap)
+ glamor_finish_access(&pWin->background.pixmap->
+ drawable, GLAMOR_CPU_ACCESS_RO);
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+static void glamor_finish_access_window(WindowPtr pWin)
+{
+ if (pWin->backgroundState == BackgroundPixmap)
+ glamor_finish_access(&pWin->background.pixmap->drawable, GLAMOR_CPU_ACCESS_RO);
+
+ if (pWin->borderIsPixel == FALSE)
+ glamor_finish_access(&pWin->border.pixmap->drawable, GLAMOR_CPU_ACCESS_RO);
+}
+
+static Bool glamor_change_window_attributes(WindowPtr pWin, unsigned long mask)
+{
+ Bool ret;
+
+ if (!glamor_prepare_access_window(pWin))
+ return FALSE;
+ ret = fbChangeWindowAttributes(pWin, mask);
+ glamor_finish_access_window(pWin);
+ return ret;
+}
+
+static RegionPtr glamor_bitmap_to_region(PixmapPtr pPix)
+{
+ RegionPtr ret;
+ if (!glamor_prepare_access(&pPix->drawable, GLAMOR_CPU_ACCESS_RO))
+ return NULL;
+ ret = fbPixmapToRegion(pPix);
+ glamor_finish_access(&pPix->drawable, GLAMOR_CPU_ACCESS_RO);
+ return ret;
+}
+
+void glamor_set_fallback_debug(ScreenPtr screen, Bool enable)
+{
+ glamor_screen_t *glamor_screen = glamor_get_screen(screen);
+
+ glamor_screen->fallback_debug = enable;
+}
+
+
+/*
+ * These functions wrap the low-level fb rendering functions and
+ * synchronize framebuffer/accelerated drawing by stalling until
+ * the accelerator is idle
+ */
+
+/**
+ * Calls glamor_prepare_access with GLAMOR_PREPARE_SRC for the tile, if that is the
+ * current fill style.
+ *
+ * Solid doesn't use an extra pixmap source, and Stippled/OpaqueStippled are
+ * 1bpp and never in fb, so we don't worry about them.
+ * We should worry about them for completeness sake and going forward.
+ */
+static Bool glamor_prepare_access_gc(GCPtr pGC)
+{
+ if (pGC->stipple)
+ if (!glamor_prepare_access(&pGC->stipple->drawable, GLAMOR_CPU_ACCESS_RO))
+ return FALSE;
+ if (pGC->fillStyle == FillTiled)
+ if (!glamor_prepare_access
+ (&pGC->tile.pixmap->drawable, GLAMOR_CPU_ACCESS_RO)) {
+ if (pGC->stipple)
+ glamor_finish_access(&pGC->stipple->drawable, GLAMOR_CPU_ACCESS_RO);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+ * Finishes access to the tile in the GC, if used.
+ */
+static void glamor_finish_access_gc(GCPtr pGC)
+{
+ if (pGC->fillStyle == FillTiled)
+ glamor_finish_access(&pGC->tile.pixmap->drawable, GLAMOR_CPU_ACCESS_RO);
+ if (pGC->stipple)
+ glamor_finish_access(&pGC->stipple->drawable, GLAMOR_CPU_ACCESS_RO);
+}
+
+static Bool glamor_picture_prepare_access(PicturePtr picture, int mode)
+{
+ if (picture->pDrawable == NULL)
+ return TRUE;
+
+ if (!glamor_prepare_access(picture->pDrawable, mode))
+ return FALSE;
+
+ if (picture->alphaMap &&
+ !glamor_prepare_access(picture->alphaMap->pDrawable, mode)) {
+ glamor_finish_access(picture->pDrawable, mode);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void glamor_picture_finish_access(PicturePtr picture, int mode)
+{
+ if (picture->pDrawable == NULL)
+ return;
+
+ glamor_finish_access(picture->pDrawable, mode);
+ if (picture->alphaMap)
+ glamor_finish_access(picture->alphaMap->pDrawable, mode);
+}
+
+
+static char glamor_drawable_location(DrawablePtr pDrawable)
+{
+ return glamor_drawable_is_offscreen(pDrawable) ? 's' : 'm';
+}
+
+static void
+glamor_check_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int nspans,
+ DDXPointPtr ppt, int *pwidth, int fSorted)
+{
+ ScreenPtr screen = pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("to %p (%c)\n", pDrawable,
+ glamor_drawable_location(pDrawable)));
+ if (glamor_prepare_access(pDrawable, GLAMOR_CPU_ACCESS_RW)) {
+ if (glamor_prepare_access_gc(pGC)) {
+ fbFillSpans(pDrawable, pGC, nspans, ppt, pwidth,
+ fSorted);
+ glamor_finish_access_gc(pGC);
+ }
+ glamor_finish_access(pDrawable, GLAMOR_CPU_ACCESS_RW);
+ }
+}
+
+static void
+glamor_check_set_spans(DrawablePtr pDrawable, GCPtr pGC, char *psrc,
+ DDXPointPtr ppt, int *pwidth, int nspans, int fSorted)
+{
+ ScreenPtr screen = pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("to %p (%c)\n", pDrawable,
+ glamor_drawable_location(pDrawable)));
+ if (glamor_prepare_access(pDrawable, GLAMOR_CPU_ACCESS_RW)) {
+ fbSetSpans(pDrawable, pGC, psrc, ppt, pwidth, nspans, fSorted);
+ glamor_finish_access(pDrawable, GLAMOR_CPU_ACCESS_RW);
+ }
+}
+
+static void
+glamor_check_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth,
+ int x, int y, int w, int h, int leftPad, int format,
+ char *bits)
+{
+ ScreenPtr screen = pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("to %p (%c)\n", pDrawable,
+ glamor_drawable_location(pDrawable)));
+ if (glamor_prepare_access(pDrawable, GLAMOR_CPU_ACCESS_RW)) {
+ fbPutImage(pDrawable, pGC, depth, x, y, w, h, leftPad, format,
+ bits);
+ glamor_finish_access(pDrawable, GLAMOR_CPU_ACCESS_RW);
+ }
+}
+
+static RegionPtr
+glamor_check_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h, int dstx, int dsty,
+ unsigned long bitPlane)
+{
+ ScreenPtr screen = pSrc->pScreen;
+ RegionPtr ret = NULL;
+
+ GLAMOR_FALLBACK(("from %p to %p (%c,%c)\n", pSrc, pDst,
+ glamor_drawable_location(pSrc),
+ glamor_drawable_location(pDst)));
+ if (glamor_prepare_access(pDst, GLAMOR_CPU_ACCESS_RW)) {
+ if (glamor_prepare_access(pSrc, GLAMOR_CPU_ACCESS_RO)) {
+ ret =
+ fbCopyPlane(pSrc, pDst, pGC, srcx, srcy, w, h, dstx,
+ dsty, bitPlane);
+ glamor_finish_access(pSrc, GLAMOR_CPU_ACCESS_RO);
+ }
+ glamor_finish_access(pDst, GLAMOR_CPU_ACCESS_RW);
+ }
+ return ret;
+}
+
+static void
+glamor_check_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+ DDXPointPtr pptInit)
+{
+ ScreenPtr screen = pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("to %p (%c)\n", pDrawable,
+ glamor_drawable_location(pDrawable)));
+ if (glamor_prepare_access(pDrawable, GLAMOR_CPU_ACCESS_RW)) {
+ fbPolyPoint(pDrawable, pGC, mode, npt, pptInit);
+ glamor_finish_access(pDrawable, GLAMOR_CPU_ACCESS_RW);
+ }
+}
+
+static void
+glamor_check_poly_lines(DrawablePtr pDrawable, GCPtr pGC,
+ int mode, int npt, DDXPointPtr ppt)
+{
+ ScreenPtr screen = pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("to %p (%c), width %d, mode %d, count %d\n",
+ pDrawable, glamor_drawable_location(pDrawable),
+ pGC->lineWidth, mode, npt));
+
+ if (pGC->lineWidth == 0) {
+ if (glamor_prepare_access(pDrawable, GLAMOR_CPU_ACCESS_RW)) {
+ if (glamor_prepare_access_gc(pGC)) {
+ fbPolyLine(pDrawable, pGC, mode, npt, ppt);
+ glamor_finish_access_gc(pGC);
+ }
+ glamor_finish_access(pDrawable, GLAMOR_CPU_ACCESS_RW);
+ }
+ return;
+ }
+ /* fb calls mi functions in the lineWidth != 0 case. */
+ fbPolyLine(pDrawable, pGC, mode, npt, ppt);
+}
+
+static void
+glamor_check_poly_segment(DrawablePtr pDrawable, GCPtr pGC,
+ int nsegInit, xSegment * pSegInit)
+{
+ ScreenPtr screen = pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("to %p (%c) width %d, count %d\n", pDrawable,
+ glamor_drawable_location(pDrawable), pGC->lineWidth,
+ nsegInit));
+ if (pGC->lineWidth == 0) {
+ if (glamor_prepare_access(pDrawable, GLAMOR_CPU_ACCESS_RW)) {
+ if (glamor_prepare_access_gc(pGC)) {
+ fbPolySegment(pDrawable, pGC, nsegInit,
+ pSegInit);
+ glamor_finish_access_gc(pGC);
+ }
+ glamor_finish_access(pDrawable, GLAMOR_CPU_ACCESS_RW);
+ }
+ return;
+ }
+ /* fb calls mi functions in the lineWidth != 0 case. */
+ fbPolySegment(pDrawable, pGC, nsegInit, pSegInit);
+}
+
+static void
+glamor_check_poly_arc(DrawablePtr pDrawable, GCPtr pGC, int narcs, xArc * pArcs)
+{
+ ScreenPtr screen = pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("to %p (%c)\n", pDrawable,
+ glamor_drawable_location(pDrawable)));
+
+ /* Disable this as fbPolyArc can call miZeroPolyArc which in turn
+ * can call accelerated functions, that as yet, haven't been notified
+ * with glamor_finish_access().
+ */
+#if 0
+ if (pGC->lineWidth == 0) {
+ if (glamor_prepare_access(pDrawable, GLAMOR_CPU_ACCESS_RW)) {
+ if (glamor_prepare_access_gc(pGC)) {
+ fbPolyArc(pDrawable, pGC, narcs, pArcs);
+ glamor_finish_access_gc(pGC);
+ }
+ glamor_finish_access(pDrawable, GLAMOR_CPU_ACCESS_RW);
+ }
+ return;
+ }
+#endif
+ miPolyArc(pDrawable, pGC, narcs, pArcs);
+}
+
+static void
+glamor_check_poly_fill_rect(DrawablePtr pDrawable, GCPtr pGC,
+ int nrect, xRectangle * prect)
+{
+ ScreenPtr screen = pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("to %p (%c)\n", pDrawable,
+ glamor_drawable_location(pDrawable)));
+
+ if (glamor_prepare_access(pDrawable, GLAMOR_CPU_ACCESS_RW)) {
+ if (glamor_prepare_access_gc(pGC)) {
+ fbPolyFillRect(pDrawable, pGC, nrect, prect);
+ glamor_finish_access_gc(pGC);
+ }
+ glamor_finish_access(pDrawable, GLAMOR_CPU_ACCESS_RW);
+ }
+}
+
+static void
+glamor_check_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr * ppci, pointer pglyphBase)
+{
+ ScreenPtr screen = pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("to %p (%c)\n", pDrawable,
+ glamor_drawable_location(pDrawable)));
+ if (glamor_prepare_access(pDrawable, GLAMOR_CPU_ACCESS_RW)) {
+ if (glamor_prepare_access_gc(pGC)) {
+ fbImageGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci,
+ pglyphBase);
+ glamor_finish_access_gc(pGC);
+ }
+ glamor_finish_access(pDrawable, GLAMOR_CPU_ACCESS_RW);
+ }
+}
+
+static void
+glamor_check_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr * ppci, pointer pglyphBase)
+{
+ ScreenPtr screen = pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("to %p (%c), style %d alu %d\n", pDrawable,
+ glamor_drawable_location(pDrawable), pGC->fillStyle,
+ pGC->alu));
+ if (glamor_prepare_access(pDrawable, GLAMOR_CPU_ACCESS_RW)) {
+ if (glamor_prepare_access_gc(pGC)) {
+ fbPolyGlyphBlt(pDrawable, pGC, x, y, nglyph, ppci,
+ pglyphBase);
+ glamor_finish_access_gc(pGC);
+ }
+ glamor_finish_access(pDrawable, GLAMOR_CPU_ACCESS_RW);
+ }
+}
+
+static void
+glamor_check_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
+ DrawablePtr pDrawable, int w, int h, int x, int y)
+{
+ ScreenPtr screen = pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("from %p to %p (%c,%c)\n", pBitmap, pDrawable,
+ glamor_drawable_location(&pBitmap->drawable),
+ glamor_drawable_location(pDrawable)));
+ if (glamor_prepare_access(pDrawable, GLAMOR_CPU_ACCESS_RW)) {
+ if (glamor_prepare_access(&pBitmap->drawable, GLAMOR_CPU_ACCESS_RO)) {
+ if (glamor_prepare_access_gc(pGC)) {
+ fbPushPixels(pGC, pBitmap, pDrawable, w, h, x,
+ y);
+ glamor_finish_access_gc(pGC);
+ }
+ glamor_finish_access(&pBitmap->drawable, GLAMOR_CPU_ACCESS_RO);
+ }
+ glamor_finish_access(pDrawable, GLAMOR_CPU_ACCESS_RW);
+ }
+}
+
+static void
+glamor_check_get_spans(DrawablePtr pDrawable,
+ int wMax,
+ DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart)
+{
+ ScreenPtr screen = pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("from %p (%c)\n", pDrawable,
+ glamor_drawable_location(pDrawable)));
+ if (glamor_prepare_access(pDrawable, GLAMOR_CPU_ACCESS_RO)) {
+ fbGetSpans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
+ glamor_finish_access(pDrawable, GLAMOR_CPU_ACCESS_RO);
+ }
+}
+
+static void
+glamor_check_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)
+{
+ ScreenPtr screen = pDst->pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("from picts %p/%p to pict %p\n", pSrc, pMask, pDst));
+
+ if (glamor_picture_prepare_access(pDst, GLAMOR_CPU_ACCESS_RW)) {
+ if (glamor_picture_prepare_access(pSrc, GLAMOR_CPU_ACCESS_RO)) {
+ if (!pMask || glamor_picture_prepare_access(pMask, GLAMOR_CPU_ACCESS_RO)) {
+ fbComposite(op, pSrc, pMask, pDst,
+ xSrc, ySrc,
+ xMask, yMask,
+ xDst, yDst,
+ width, height);
+ if (pMask)
+ glamor_picture_finish_access(pMask, GLAMOR_CPU_ACCESS_RO);
+ }
+ glamor_picture_finish_access(pSrc, GLAMOR_CPU_ACCESS_RO);
+ }
+ glamor_picture_finish_access(pDst, GLAMOR_CPU_ACCESS_RW);
+ }
+}
+
+static void
+glamor_check_add_traps(PicturePtr pPicture,
+ INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
+{
+ ScreenPtr screen = pPicture->pDrawable->pScreen;
+
+ GLAMOR_FALLBACK(("to pict %p (%c)\n", pPicture,
+ glamor_drawable_location(pPicture->pDrawable)));
+ if (glamor_picture_prepare_access(pPicture, GLAMOR_CPU_ACCESS_RW)) {
+ fbAddTraps(pPicture, x_off, y_off, ntrap, traps);
+ glamor_picture_finish_access(pPicture, GLAMOR_CPU_ACCESS_RW);
+ }
+}
+
+
+static void
+glamor_fill_spans(DrawablePtr pDrawable, GCPtr pGC, int n,
+ DDXPointPtr ppt, int *pwidth, int fSorted)
+{
+ int ok;
+
+ ok = glamor_prepare_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ if (ok) {
+ ok = glamor_fill_spans_nf(pDrawable,
+ pGC, n, ppt, pwidth, fSorted);
+ glamor_finish_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ }
+
+ if (!ok)
+ glamor_check_fill_spans(pDrawable, pGC, n, ppt, pwidth, fSorted);
+}
+
+static void
+glamor_put_image(DrawablePtr pDrawable, GCPtr pGC, int depth, int x, int y,
+ int w, int h, int leftPad, int format, char *bits)
+{
+ int ok;
+
+ ok = glamor_prepare_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ if (ok) {
+ ok = glamor_put_image_nf(pDrawable,
+ pGC, depth, x, y, w, h,
+ leftPad, format, bits);
+ glamor_finish_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ }
+
+ if (!ok)
+ glamor_check_put_image(pDrawable, pGC, depth, x, y, w, h, leftPad,
+ format, bits);
+}
+
+static void
+glamor_copy_n_to_n(DrawablePtr pSrcDrawable,
+ DrawablePtr pDstDrawable,
+ GCPtr pGC,
+ BoxPtr pbox,
+ int nbox,
+ int dx,
+ int dy,
+ Bool reverse, Bool upsidedown, Pixel bitplane, void *closure)
+{
+ ScreenPtr screen = pDstDrawable->pScreen;
+ int ok;
+
+ if (!glamor_prepare_access(pSrcDrawable, GLAMOR_GPU_ACCESS_RO))
+ goto fallback;
+ ok = glamor_prepare_access(pDstDrawable, GLAMOR_GPU_ACCESS_RW);
+ if (!ok)
+ goto finish_src;
+ ok = glamor_copy_n_to_n_nf(pSrcDrawable, pDstDrawable,
+ pGC, pbox, nbox, dx, dy,
+ reverse, upsidedown, bitplane,
+ closure);
+ glamor_finish_access(pDstDrawable, GLAMOR_GPU_ACCESS_RW);
+finish_src:
+ glamor_finish_access(pSrcDrawable, GLAMOR_GPU_ACCESS_RO);
+
+ if (ok)
+ return;
+
+fallback:
+ GLAMOR_FALLBACK(("from %p to %p (%c,%c)\n", pSrcDrawable, pDstDrawable,
+ glamor_drawable_location(pSrcDrawable),
+ glamor_drawable_location(pDstDrawable)));
+ if (glamor_prepare_access(pDstDrawable, GLAMOR_CPU_ACCESS_RW)) {
+ if (pSrcDrawable == pDstDrawable ||
+ glamor_prepare_access(pSrcDrawable, GLAMOR_CPU_ACCESS_RO)) {
+ fbCopyNtoN(pSrcDrawable, pDstDrawable, pGC, pbox, nbox,
+ dx, dy, reverse, upsidedown, bitplane,
+ closure);
+ if (pSrcDrawable != pDstDrawable)
+ glamor_finish_access(pSrcDrawable, GLAMOR_CPU_ACCESS_RO);
+ }
+ glamor_finish_access(pDstDrawable, GLAMOR_CPU_ACCESS_RW);
+ }
+}
+
+static RegionPtr
+glamor_copy_area(DrawablePtr pSrcDrawable, DrawablePtr pDstDrawable, GCPtr pGC,
+ int srcx, int srcy, int width, int height, int dstx, int dsty)
+{
+ return miDoCopy(pSrcDrawable, pDstDrawable, pGC,
+ srcx, srcy, width, height,
+ dstx, dsty, glamor_copy_n_to_n, 0, NULL);
+}
+
+static void
+glamor_poly_point(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+ DDXPointPtr ppt)
+{
+ int i;
+ xRectangle *prect;
+ int ok;
+
+ ok = glamor_prepare_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ if (ok) {
+ ok = glamor_poly_point_nf(pDrawable, pGC, mode, npt, ppt);
+ glamor_finish_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ }
+
+ if (ok)
+ return;
+
+ /* If we can't reuse the current GC as is, don't bother accelerating the
+ * points.
+ */
+ if (pGC->fillStyle != FillSolid) {
+ glamor_check_poly_point(pDrawable, pGC, mode, npt, ppt);
+ return;
+ }
+
+ prect = malloc(sizeof(xRectangle) * npt);
+ if (!prect)
+ return;
+ for (i = 0; i < npt; i++) {
+ prect[i].x = ppt[i].x;
+ prect[i].y = ppt[i].y;
+ if (i > 0 && mode == CoordModePrevious) {
+ prect[i].x += prect[i - 1].x;
+ prect[i].y += prect[i - 1].y;
+ }
+ prect[i].width = 1;
+ prect[i].height = 1;
+ }
+ pGC->ops->PolyFillRect(pDrawable, pGC, npt, prect);
+ free(prect);
+}
+
+/**
+ * glamor_poly_lines() checks if it can accelerate the lines as a group of
+ * horizontal or vertical lines (rectangles), and uses existing rectangle fill
+ * acceleration if so.
+ */
+static void
+glamor_poly_lines(DrawablePtr pDrawable, GCPtr pGC, int mode, int npt,
+ DDXPointPtr ppt)
+{
+ xRectangle *prect;
+ int x1, x2, y1, y2;
+ int i;
+ int ok;
+
+ if (!glamor_prepare_access(pDrawable, GLAMOR_GPU_ACCESS_RW))
+ goto fallback;
+ ok = glamor_poly_lines_nf(pDrawable, pGC, mode, npt, ppt);
+ glamor_finish_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+
+ if (ok)
+ return;
+
+fallback:
+ /* Don't try to do wide lines or non-solid fill style. */
+ if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
+ pGC->fillStyle != FillSolid) {
+ glamor_check_poly_lines(pDrawable, pGC, mode, npt, ppt);
+ return;
+ }
+
+ prect = malloc(sizeof(xRectangle) * (npt - 1));
+ if (!prect)
+ return;
+ x1 = ppt[0].x;
+ y1 = ppt[0].y;
+ /* If we have any non-horizontal/vertical, fall back. */
+ for (i = 0; i < npt - 1; i++) {
+ if (mode == CoordModePrevious) {
+ x2 = x1 + ppt[i + 1].x;
+ y2 = y1 + ppt[i + 1].y;
+ } else {
+ x2 = ppt[i + 1].x;
+ y2 = ppt[i + 1].y;
+ }
+
+ if (x1 != x2 && y1 != y2) {
+ free(prect);
+ glamor_check_poly_lines(pDrawable, pGC, mode, npt, ppt);
+ return;
+ }
+
+ if (x1 < x2) {
+ prect[i].x = x1;
+ prect[i].width = x2 - x1 + 1;
+ } else {
+ prect[i].x = x2;
+ prect[i].width = x1 - x2 + 1;
+ }
+ if (y1 < y2) {
+ prect[i].y = y1;
+ prect[i].height = y2 - y1 + 1;
+ } else {
+ prect[i].y = y2;
+ prect[i].height = y1 - y2 + 1;
+ }
+
+ x1 = x2;
+ y1 = y2;
+ }
+ pGC->ops->PolyFillRect(pDrawable, pGC, npt - 1, prect);
+ free(prect);
+}
+
+/**
+ * glamor_poly_segment() checks if it can accelerate the lines as a group of
+ * horizontal or vertical lines (rectangles), and uses existing rectangle fill
+ * acceleration if so.
+ */
+static void
+glamor_poly_segment(DrawablePtr pDrawable, GCPtr pGC, int nseg, xSegment * pSeg)
+{
+ xRectangle *prect;
+ int i;
+ int ok;
+
+ if (!glamor_prepare_access(pDrawable, GLAMOR_GPU_ACCESS_RW))
+ goto fallback;
+ ok = glamor_poly_segment_nf(pDrawable, pGC, nseg, pSeg);
+ glamor_finish_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+
+ if (ok)
+ return;
+
+fallback:
+ /* Don't try to do wide lines or non-solid fill style. */
+ if (pGC->lineWidth != 0 || pGC->lineStyle != LineSolid ||
+ pGC->fillStyle != FillSolid) {
+ glamor_check_poly_segment(pDrawable, pGC, nseg, pSeg);
+ return;
+ }
+
+ /* If we have any non-horizontal/vertical, fall back. */
+ for (i = 0; i < nseg; i++) {
+ if (pSeg[i].x1 != pSeg[i].x2 && pSeg[i].y1 != pSeg[i].y2) {
+ glamor_check_poly_segment(pDrawable, pGC, nseg, pSeg);
+ return;
+ }
+ }
+
+ prect = malloc(sizeof(xRectangle) * nseg);
+ if (!prect)
+ return;
+ for (i = 0; i < nseg; i++) {
+ if (pSeg[i].x1 < pSeg[i].x2) {
+ prect[i].x = pSeg[i].x1;
+ prect[i].width = pSeg[i].x2 - pSeg[i].x1 + 1;
+ } else {
+ prect[i].x = pSeg[i].x2;
+ prect[i].width = pSeg[i].x1 - pSeg[i].x2 + 1;
+ }
+ if (pSeg[i].y1 < pSeg[i].y2) {
+ prect[i].y = pSeg[i].y1;
+ prect[i].height = pSeg[i].y2 - pSeg[i].y1 + 1;
+ } else {
+ prect[i].y = pSeg[i].y2;
+ prect[i].height = pSeg[i].y1 - pSeg[i].y2 + 1;
+ }
+
+ /* don't paint last pixel */
+ if (pGC->capStyle == CapNotLast) {
+ if (prect[i].width == 1)
+ prect[i].height--;
+ else
+ prect[i].width--;
+ }
+ }
+ pGC->ops->PolyFillRect(pDrawable, pGC, nseg, prect);
+ free(prect);
+}
+
+static void
+glamor_poly_fill_rect(DrawablePtr pDrawable,
+ GCPtr pGC, int nrect, xRectangle * prect)
+{
+ int ok;
+
+ ok = glamor_prepare_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ if (ok) {
+ ok = glamor_poly_fill_rect_nf(pDrawable, pGC, nrect, prect);
+ glamor_finish_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ }
+
+ if (!ok)
+ glamor_check_poly_fill_rect(pDrawable, pGC, nrect, prect);
+}
+
+static void
+glamor_get_spans(DrawablePtr pDrawable,
+ int wMax,
+ DDXPointPtr ppt, int *pwidth, int nspans, char *pdstStart)
+{
+ int ok;
+
+ ok = glamor_prepare_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ if (ok) {
+ ok = glamor_get_spans_nf(pDrawable, wMax, ppt,
+ pwidth, nspans, pdstStart);
+ glamor_finish_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ }
+
+ if (!ok)
+ glamor_check_get_spans(pDrawable, wMax, ppt, pwidth, nspans, pdstStart);
+}
+
+static void
+glamor_set_spans(DrawablePtr pDrawable, GCPtr gc, char *src,
+ DDXPointPtr points, int *widths, int n, int sorted)
+{
+ int ok;
+
+ ok = glamor_prepare_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ if (ok) {
+ ok = glamor_set_spans_nf(pDrawable, gc, src,
+ points, widths, n, sorted);
+ glamor_finish_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ }
+
+ if (!ok)
+ glamor_check_set_spans(pDrawable, gc, src, points, widths, n, sorted);
+}
+
+static RegionPtr
+glamor_copy_plane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h, int dstx, int dsty,
+ unsigned long bitPlane)
+{
+ int ok;
+ RegionPtr region;
+
+ if (!glamor_prepare_access(pDst, GLAMOR_GPU_ACCESS_RW))
+ goto fallback;
+ ok = glamor_prepare_access(pSrc, GLAMOR_GPU_ACCESS_RO);
+ if (!ok)
+ goto finish_dst;
+ ok = glamor_copy_plane_nf(pSrc, pDst, pGC, srcx, srcy, w, h,
+ dstx, dsty, bitPlane, ®ion);
+ glamor_finish_access(pSrc, GLAMOR_GPU_ACCESS_RO);
+finish_dst:
+ glamor_finish_access(pDst, GLAMOR_GPU_ACCESS_RW);
+
+ if (ok)
+ return region;
+
+fallback:
+ return glamor_check_copy_plane(pSrc, pDst, pGC, srcx, srcy, w, h,
+ dstx, dsty, bitPlane);
+}
+
+static void
+glamor_image_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr * ppci, pointer pglyphBase)
+{
+ int ok;
+
+ ok = glamor_prepare_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ if (ok) {
+ ok = glamor_image_glyph_blt_nf(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ glamor_finish_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ }
+
+ if (!ok)
+ glamor_check_image_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+}
+
+static void
+glamor_poly_glyph_blt(DrawablePtr pDrawable, GCPtr pGC,
+ int x, int y, unsigned int nglyph,
+ CharInfoPtr * ppci, pointer pglyphBase)
+{
+ int ok;
+
+ ok = glamor_prepare_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ if (ok) {
+ ok = glamor_poly_glyph_blt_nf(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+ glamor_finish_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+ }
+
+ if (!ok)
+ glamor_check_poly_glyph_blt(pDrawable, pGC, x, y, nglyph, ppci, pglyphBase);
+}
+
+static void
+glamor_push_pixels(GCPtr pGC, PixmapPtr pBitmap,
+ DrawablePtr pDrawable, int w, int h, int x, int y)
+{
+ int ok;
+
+ if (!glamor_prepare_access(pDrawable, GLAMOR_GPU_ACCESS_RW))
+ goto fallback;
+ ok = glamor_prepare_access(&pBitmap->drawable, GLAMOR_GPU_ACCESS_RO);
+ if (!ok)
+ goto finish_drawable;
+ ok = glamor_push_pixels_nf(pGC, pBitmap, pDrawable, w, h, x, y);
+ glamor_finish_access(&pBitmap->drawable, GLAMOR_GPU_ACCESS_RO);
+finish_drawable:
+ glamor_prepare_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+
+ if (ok)
+ return;
+
+fallback:
+ glamor_check_push_pixels(pGC, pBitmap, pDrawable, w, h, x, y);
+}
+
+const GCOps glamor_ops = {
+ glamor_fill_spans,
+ glamor_set_spans,
+ glamor_put_image,
+ glamor_copy_area,
+ glamor_copy_plane,
+ glamor_poly_point,
+ glamor_poly_lines,
+ glamor_poly_segment,
+ miPolyRectangle,
+ glamor_check_poly_arc,
+ miFillPolygon,
+ glamor_poly_fill_rect,
+ miPolyFillArc,
+ miPolyText8,
+ miPolyText16,
+ miImageText8,
+ miImageText16,
+ glamor_image_glyph_blt,
+ glamor_poly_glyph_blt,
+ glamor_push_pixels,
+};
+
+/**
+ * glamor_validate_gc() sets the ops to GLAMOR's 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)
+{
+ glamor_validate_gc(pGC, changes, pDrawable);
+ pGC->ops = (GCOps *) & glamor_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)
+{
+ if (!fbCreateGC(pGC))
+ return FALSE;
+
+ pGC->funcs = &glamorGCFuncs;
+
+ return TRUE;
+}
+
+static void glamor_copy_window(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ RegionRec rgnDst;
+ int dx, dy;
+ PixmapPtr pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+
+ REGION_INIT(pWin->drawable.pScreen, &rgnDst, NullBox, 0);
+
+ REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst, &pWin->borderClip,
+ prgnSrc);
+#ifdef COMPOSITE
+ if (pPixmap->screen_x || pPixmap->screen_y)
+ REGION_TRANSLATE(pWin->drawable.pScreen, &rgnDst,
+ -pPixmap->screen_x, -pPixmap->screen_y);
+#endif
+
+ miCopyRegion(&pPixmap->drawable, &pPixmap->drawable,
+ NULL, &rgnDst, dx, dy, glamor_copy_n_to_n, 0, NULL);
+
+ REGION_UNINIT(pWin->drawable.pScreen, &rgnDst);
+}
+
+/**
+ * Accelerates GetImage for solid ZPixmap downloads from framebuffer memory.
+ *
+ * This is probably the only case we actually care about. The rest fall through
+ * to migration and fbGetImage, which hopefully will result in migration pushing
+ * the pixmap out of framebuffer.
+ */
+void
+static glamor_get_image(DrawablePtr pDrawable, int x, int y, int w, int h,
+ unsigned int format, unsigned long planeMask, char *d)
+{
+ ScreenPtr screen = pDrawable->pScreen;
+ BoxRec Box;
+ PixmapPtr pPix = glamor_get_drawable_pixmap(pDrawable);
+ int xoff, yoff;
+ Bool ok;
+
+ if (!glamor_prepare_access(pDrawable, GLAMOR_GPU_ACCESS_RW))
+ goto fallback;
+
+ glamor_get_drawable_deltas(pDrawable, pPix, &xoff, &yoff);
+
+ Box.x1 = pDrawable->y + x + xoff;
+ Box.y1 = pDrawable->y + y + yoff;
+ Box.x2 = Box.x1 + w;
+ Box.y2 = Box.y1 + h;
+
+ ok = glamor_get_image_nf(pDrawable, x, y, w, h,
+ format, planeMask, d);
+ glamor_finish_access(pDrawable, GLAMOR_GPU_ACCESS_RW);
+
+ if (ok)
+ return;
+
+fallback:
+ GLAMOR_FALLBACK(("from %p (%c)\n", pDrawable,
+ glamor_drawable_location(pDrawable)));
+
+ if (glamor_prepare_access(pDrawable, GLAMOR_CPU_ACCESS_RO)) {
+ fbGetImage(pDrawable, x, y, w, h, format, planeMask, d);
+ glamor_finish_access(pDrawable, GLAMOR_CPU_ACCESS_RO);
+ }
+
+ return;
+}
+
+
+/* Cut and paste from render/glyph.c - probably should export it instead */
+static void
+glamor_glyph_extents(int nlist,
+ GlyphListPtr list, GlyphPtr * glyphs, BoxPtr extents)
+{
+ int x1, x2, y1, y2;
+ int x, y, n;
+
+ x1 = y1 = MAXSHORT;
+ x2 = y2 = MINSHORT;
+ x = y = 0;
+ while (nlist--) {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ list++;
+ while (n--) {
+ GlyphPtr glyph = *glyphs++;
+ int v;
+
+ v = x - glyph->info.x;
+ if (v < x1)
+ x1 = v;
+ v += glyph->info.width;
+ if (v > x2)
+ x2 = v;
+
+ v = y - glyph->info.y;
+ if (v < y1)
+ y1 = v;
+ v += glyph->info.height;
+ if (v > y2)
+ y2 = v;
+
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ }
+
+ extents->x1 = x1 < MINSHORT ? MINSHORT : x1;
+ extents->x2 = x2 > MAXSHORT ? MAXSHORT : x2;
+ extents->y1 = y1 < MINSHORT ? MINSHORT : y1;
+ extents->y2 = y2 > MAXSHORT ? MAXSHORT : y2;
+}
+
+#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
+
+static void
+glamor_check_glyphs(CARD8 op,
+ PicturePtr src,
+ PicturePtr dst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc, int nlist, GlyphListPtr list, GlyphPtr * glyphs)
+{
+ pixman_image_t *image;
+ PixmapPtr scratch;
+ PicturePtr mask;
+ int width = 0, height = 0;
+ int x, y, n;
+ int xDst = list->xOff, yDst = list->yOff;
+ BoxRec extents = { 0, 0, 0, 0 };
+
+ if (maskFormat) {
+ pixman_format_code_t format;
+ CARD32 component_alpha;
+ int error;
+
+ glamor_glyph_extents(nlist, list, glyphs, &extents);
+ if (extents.x2 <= extents.x1 || extents.y2 <= extents.y1)
+ return;
+
+ width = extents.x2 - extents.x1;
+ height = extents.y2 - extents.y1;
+
+ format = maskFormat->format |
+ (BitsPerPixel(maskFormat->depth) << 24);
+ image =
+ pixman_image_create_bits(format, width, height, NULL, 0);
+ if (!image)
+ return;
+
+ scratch = GetScratchPixmapHeader(dst->pDrawable->pScreen, width, height,
+ PIXMAN_FORMAT_DEPTH(format),
+ PIXMAN_FORMAT_BPP(format),
+ pixman_image_get_stride(image),
+ pixman_image_get_data(image));
+
+ if (!scratch) {
+ pixman_image_unref(image);
+ return;
+ }
+
+ component_alpha = NeedsComponent(maskFormat->format);
+ mask = CreatePicture(0, &scratch->drawable,
+ maskFormat, CPComponentAlpha,
+ &component_alpha, serverClient, &error);
+ if (!mask) {
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
+ return;
+ }
+ ValidatePicture(mask);
+
+ x = -extents.x1;
+ y = -extents.y1;
+ } else {
+ mask = dst;
+ x = 0;
+ y = 0;
+ }
+
+ while (nlist--) {
+ x += list->xOff;
+ y += list->yOff;
+ n = list->len;
+ while (n--) {
+ GlyphPtr glyph = *glyphs++;
+ PicturePtr g = GetGlyphPicture(glyph, dst->pDrawable->pScreen);
+ if (g) {
+ if (maskFormat) {
+ CompositePicture(PictOpAdd, g, NULL, mask,
+ 0, 0,
+ 0, 0,
+ x - glyph->info.x,
+ y - glyph->info.y,
+ glyph->info.width,
+ glyph->info.height);
+ } else {
+ CompositePicture(op, src, g, dst,
+ xSrc + (x - glyph->info.x) - xDst,
+ ySrc + (y - glyph->info.y) - yDst,
+ 0, 0,
+ x - glyph->info.x,
+ y - glyph->info.y,
+ glyph->info.width,
+ glyph->info.height);
+ }
+ }
+
+ x += glyph->info.xOff;
+ y += glyph->info.yOff;
+ }
+ list++;
+ }
+
+ if (maskFormat) {
+ x = extents.x1;
+ y = extents.y1;
+ CompositePicture(op, src, mask, dst,
+ xSrc + x - xDst,
+ ySrc + y - yDst,
+ 0, 0,
+ x, y,
+ width, height);
+ FreePicture(mask, 0);
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
+ }
+}
+
+void
+glamor_glyphs(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ int nlist, GlyphListPtr list, GlyphPtr * glyphs)
+{
+ int ok;
+
+ if (!glamor_picture_prepare_access(pDst, GLAMOR_GPU_ACCESS_RW))
+ goto fallback;
+ ok = glamor_picture_prepare_access(pSrc, GLAMOR_GPU_ACCESS_RO);
+ if (!ok)
+ goto finish_dst;
+ ok = glamor_glyphs_nf(op,
+ pSrc, pDst, maskFormat,
+ xSrc, ySrc, nlist, list, glyphs);
+ glamor_picture_finish_access(pSrc, GLAMOR_GPU_ACCESS_RO);
+finish_dst:
+ glamor_picture_finish_access(pDst, GLAMOR_GPU_ACCESS_RW);
+
+ if (ok)
+ return;
+
+fallback:
+ glamor_check_glyphs(op, pSrc, pDst, maskFormat, xSrc, ySrc, nlist, list, glyphs);
+}
+
+
+#ifdef RENDER
+
+/* Note: when using glamor we can not fail through to the ordinary GLAMOR
+ * code paths, as glamor keeps an internal texture which will become
+ * inconsistent with the original bo. (The texture is replaced whenever
+ * the format changes, e.g. switching between xRGB and ARGB, for which mesa
+ * will allocate its own bo.)
+ *
+ * Ergo it is unsafe to fall through to the original backend operations if
+ * glamor is enabled.
+ *
+ * XXX This has some serious implications for mixing Render, DRI, scanout...
+ */
+
+static void glamor_composite_fallback_pict_desc(PicturePtr pict, char *string,
+ int n)
+{
+ char format[20];
+ char size[20];
+ char loc;
+
+ if (!pict) {
+ snprintf(string, n, "None");
+ return;
+ }
+
+ if (pict->pDrawable == NULL) {
+ snprintf(string, n, "source-only");
+ return;
+ }
+
+ switch (pict->format) {
+ case PICT_a8r8g8b8:
+ snprintf(format, 20, "ARGB8888");
+ break;
+ case PICT_x8r8g8b8:
+ snprintf(format, 20, "XRGB8888");
+ break;
+ case PICT_r5g6b5:
+ snprintf(format, 20, "RGB565 ");
+ break;
+ case PICT_x1r5g5b5:
+ snprintf(format, 20, "RGB555 ");
+ break;
+ case PICT_a8:
+ snprintf(format, 20, "A8 ");
+ break;
+ case PICT_a1:
+ snprintf(format, 20, "A1 ");
+ break;
+ default:
+ snprintf(format, 20, "0x%x", (int)pict->format);
+ break;
+ }
+
+ loc = glamor_drawable_is_offscreen(pict->pDrawable) ? 's' : 'm';
+
+ snprintf(size, 20, "%dx%d%s", pict->pDrawable->width,
+ pict->pDrawable->height, pict->repeat ? " R" : "");
+
+ snprintf(string, n, "%p:%c fmt %s (%s)%s",
+ pict->pDrawable, loc, format, size,
+ pict->alphaMap ? " with alpha map" :"");
+}
+
+static const char *
+op_to_string(CARD8 op)
+{
+ switch (op) {
+#define C(x) case PictOp##x: return #x
+ C(Clear);
+ C(Src);
+ C(Dst);
+ C(Over);
+ C(OverReverse);
+ C(In);
+ C(InReverse);
+ C(Out);
+ C(OutReverse);
+ C(Atop);
+ C(AtopReverse);
+ C(Xor);
+ C(Add);
+ C(Saturate);
+
+ /*
+ * Operators only available in version 0.2
+ */
+#if RENDER_MAJOR >= 1 || RENDER_MINOR >= 2
+ C(DisjointClear);
+ C(DisjointSrc);
+ C(DisjointDst);
+ C(DisjointOver);
+ C(DisjointOverReverse);
+ C(DisjointIn);
+ C(DisjointInReverse);
+ C(DisjointOut);
+ C(DisjointOutReverse);
+ C(DisjointAtop);
+ C(DisjointAtopReverse);
+ C(DisjointXor);
+
+ C(ConjointClear);
+ C(ConjointSrc);
+ C(ConjointDst);
+ C(ConjointOver);
+ C(ConjointOverReverse);
+ C(ConjointIn);
+ C(ConjointInReverse);
+ C(ConjointOut);
+ C(ConjointOutReverse);
+ C(ConjointAtop);
+ C(ConjointAtopReverse);
+ C(ConjointXor);
+#endif
+
+ /*
+ * Operators only available in version 0.11
+ */
+#if RENDER_MAJOR >= 1 || RENDER_MINOR >= 11
+ C(Multiply);
+ C(Screen);
+ C(Overlay);
+ C(Darken);
+ C(Lighten);
+ C(ColorDodge);
+ C(ColorBurn);
+ C(HardLight);
+ C(SoftLight);
+ C(Difference);
+ C(Exclusion);
+ C(HSLHue);
+ C(HSLSaturation);
+ C(HSLColor);
+ C(HSLLuminosity);
+#endif
+ default: return "garbage";
+#undef C
+ }
+}
+
+static void
+glamor_print_composite_fallback(const char *func, CARD8 op,
+ PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst)
+{
+ glamor_screen_t *glamor_screen = glamor_get_screen(pDst->pDrawable->pScreen);
+ char srcdesc[40], maskdesc[40], dstdesc[40];
+
+ if (! glamor_screen->fallback_debug)
+ return;
+
+ glamor_composite_fallback_pict_desc(pSrc, srcdesc, 40);
+ glamor_composite_fallback_pict_desc(pMask, maskdesc, 40);
+ glamor_composite_fallback_pict_desc(pDst, dstdesc, 40);
+
+ ErrorF("Composite fallback at %s:\n"
+ " op %s, \n"
+ " src %s, \n"
+ " mask %s, \n"
+ " dst %s, \n",
+ func, op_to_string (op), srcdesc, maskdesc, dstdesc);
+}
+
+
+static void
+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)
+{
+ int ok;
+
+ if (!glamor_picture_prepare_access(pDst, GLAMOR_GPU_ACCESS_RW))
+ goto fallback;
+ ok = glamor_picture_prepare_access(pSrc, GLAMOR_GPU_ACCESS_RO);
+ if (!ok)
+ goto finish_dst;
+ if (pMask) {
+ ok = glamor_picture_prepare_access(pMask, GLAMOR_GPU_ACCESS_RO);
+ if (!ok)
+ goto finish_src;
+ }
+
+ ok = glamor_composite_nf(op,
+ pSrc, pMask, pDst, xSrc, ySrc,
+ xMask, yMask, xDst, yDst,
+ width, height);
+
+ if (pMask)
+ glamor_picture_finish_access(pMask, GLAMOR_GPU_ACCESS_RO);
+finish_src:
+ glamor_picture_finish_access(pSrc, GLAMOR_GPU_ACCESS_RO);
+finish_dst:
+ glamor_picture_finish_access(pDst, GLAMOR_GPU_ACCESS_RW);
+
+ if (ok)
+ return;
+
+fallback:
+ glamor_print_composite_fallback("glamor_composite",
+ op, pSrc, pMask, pDst);
+
+ glamor_check_composite(op, pSrc, pMask, pDst, xSrc, ySrc,
+ xMask, yMask, xDst, yDst, width, height);
+}
+
+
+static void
+glamor_check_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid * traps)
+{
+ ScreenPtr screen = dst->pDrawable->pScreen;
+
+ if (maskFormat) {
+ PixmapPtr scratch = NULL;
+ PicturePtr mask;
+ INT16 xDst, yDst;
+ INT16 xRel, yRel;
+ BoxRec bounds;
+ int width, height;
+ pixman_image_t *image;
+ pixman_format_code_t format;
+ int error;
+
+ xDst = traps[0].left.p1.x >> 16;
+ yDst = traps[0].left.p1.y >> 16;
+
+ miTrapezoidBounds (ntrap, traps, &bounds);
+ if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
+ return;
+
+ width = bounds.x2 - bounds.x1;
+ height = bounds.y2 - bounds.y1;
+
+ format = maskFormat->format |
+ (BitsPerPixel(maskFormat->depth) << 24);
+ image =
+ pixman_image_create_bits(format, width, height, NULL, 0);
+ if (!image)
+ return;
+
+ for (; ntrap; ntrap--, traps++)
+ pixman_rasterize_trapezoid(image,
+ (pixman_trapezoid_t *) traps,
+ -bounds.x1, -bounds.y1);
+
+
+ scratch = GetScratchPixmapHeader(screen, width, height,
+ PIXMAN_FORMAT_DEPTH(format),
+ PIXMAN_FORMAT_BPP(format),
+ pixman_image_get_stride(image),
+ pixman_image_get_data(image));
+ if (!scratch) {
+ pixman_image_unref(image);
+ return;
+ }
+
+ mask = CreatePicture(0, &scratch->drawable,
+ PictureMatchFormat(screen,
+ PIXMAN_FORMAT_DEPTH(format),
+ format),
+ 0, 0, serverClient, &error);
+ if (!mask) {
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
+ return;
+ }
+
+ xRel = bounds.x1 + xSrc - xDst;
+ yRel = bounds.y1 + ySrc - yDst;
+ CompositePicture(op, src, mask, dst,
+ xRel, yRel,
+ 0, 0,
+ bounds.x1, bounds.y1,
+ width, height);
+ FreePicture(mask, 0);
+
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
+ } else {
+ if (dst->polyEdge == PolyEdgeSharp)
+ maskFormat = PictureMatchFormat(screen, 1, PICT_a1);
+ else
+ maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
+
+ for (; ntrap; ntrap--, traps++)
+ glamor_check_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, 1, traps);
+ }
+}
+
+/**
+ * glamor_trapezoids is essentially a copy of miTrapezoids that uses
+ * glamor_create_alpha_picture instead of miCreateAlphaPicture.
+ *
+ * The problem with miCreateAlphaPicture is that it calls PolyFillRect
+ * to initialize the contents after creating the pixmap, which
+ * causes the pixmap to be moved in for acceleration. The subsequent
+ * call to RasterizeTrapezoid won't be accelerated however, which
+ * forces the pixmap to be moved out again.
+ *
+ * glamor_create_alpha_picture avoids this roundtrip by using
+ * glamor_check_poly_fill_rect to initialize the contents.
+ */
+static void
+glamor_trapezoids(CARD8 op, PicturePtr src, PicturePtr dst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid * traps)
+{
+ int ok;
+
+ if (!glamor_picture_prepare_access(dst, GLAMOR_GPU_ACCESS_RW))
+ goto fallback;
+ ok = glamor_picture_prepare_access(src, GLAMOR_GPU_ACCESS_RO);
+ if (!ok)
+ goto finish_dst;
+ ok = glamor_trapezoids_nf(op,
+ src, dst, maskFormat, xSrc,
+ ySrc, ntrap, traps);
+ glamor_picture_finish_access(src, GLAMOR_GPU_ACCESS_RO);
+finish_dst:
+ glamor_picture_finish_access(dst, GLAMOR_GPU_ACCESS_RW);
+
+ if (ok)
+ return;
+
+fallback:
+ glamor_check_trapezoids(op, src, dst, maskFormat, xSrc, ySrc, ntrap, traps);
+}
+
+static void
+glamor_check_triangles(CARD8 op, PicturePtr src, PicturePtr dst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntri, xTriangle *tri)
+{
+ ScreenPtr screen = dst->pDrawable->pScreen;
+
+ if (maskFormat) {
+ PixmapPtr scratch = NULL;
+ PicturePtr mask;
+ INT16 xDst, yDst;
+ INT16 xRel, yRel;
+ BoxRec bounds;
+ int width, height;
+ pixman_image_t *image;
+ pixman_format_code_t format;
+ int error;
+
+ xDst = pixman_fixed_to_int(tri[0].p1.x);
+ yDst = pixman_fixed_to_int(tri[0].p1.y);
+
+ miTriangleBounds (ntri, tri, &bounds);
+ if (bounds.y1 >= bounds.y2 || bounds.x1 >= bounds.x2)
+ return;
+
+ width = bounds.x2 - bounds.x1;
+ height = bounds.y2 - bounds.y1;
+
+ format = maskFormat->format |
+ (BitsPerPixel(maskFormat->depth) << 24);
+ image =
+ pixman_image_create_bits(format, width, height, NULL, 0);
+ if (!image)
+ return;
+
+ pixman_add_triangles(image,
+ -bounds.x1, -bounds.y1,
+ ntri, (pixman_triangle_t *)tri);
+
+ scratch = GetScratchPixmapHeader(screen, width, height,
+ PIXMAN_FORMAT_DEPTH(format),
+ PIXMAN_FORMAT_BPP(format),
+ pixman_image_get_stride(image),
+ pixman_image_get_data(image));
+ if (!scratch) {
+ pixman_image_unref(image);
+ return;
+ }
+
+ mask = CreatePicture(0, &scratch->drawable,
+ PictureMatchFormat(screen,
+ PIXMAN_FORMAT_DEPTH(format),
+ format),
+ 0, 0, serverClient, &error);
+ if (!mask) {
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
+ return;
+ }
+
+ xRel = bounds.x1 + xSrc - xDst;
+ yRel = bounds.y1 + ySrc - yDst;
+ CompositePicture(op, src, mask, dst,
+ xRel, yRel,
+ 0, 0,
+ bounds.x1, bounds.y1,
+ width, height);
+ FreePicture(mask, 0);
+
+ FreeScratchPixmapHeader(scratch);
+ pixman_image_unref(image);
+ } else {
+ if (dst->polyEdge == PolyEdgeSharp)
+ maskFormat = PictureMatchFormat(screen, 1, PICT_a1);
+ else
+ maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
+
+ for (; ntri; ntri--, tri++)
+ glamor_check_triangles(op, src, dst, maskFormat, xSrc, ySrc, 1, tri);
+ }
+}
+
+/**
+ * glamor_triangles is essentially a copy of miTriangles that uses
+ * glamor_create_alpha_picture instead of miCreateAlphaPicture.
+ *
+ * The problem with miCreateAlphaPicture is that it calls PolyFillRect
+ * to initialize the contents after creating the pixmap, which
+ * causes the pixmap to be moved in for acceleration. The subsequent
+ * call to AddTriangles won't be accelerated however, which forces the pixmap
+ * to be moved out again.
+ *
+ * glamor_create_alpha_picture avoids this roundtrip by using
+ * glamor_check_poly_fill_rect to initialize the contents.
+ */
+static void
+glamor_triangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
+ int ntri, xTriangle * tris)
+{
+ int ok;
+
+ if (!glamor_picture_prepare_access(pDst, GLAMOR_GPU_ACCESS_RW))
+ goto fallback;
+ ok = glamor_picture_prepare_access(pSrc, GLAMOR_GPU_ACCESS_RO);
+ if (!ok)
+ goto finish_dst;
+ ok = glamor_triangles_nf(op,
+ pSrc, pDst, maskFormat, xSrc,
+ ySrc, ntri, tris);
+ glamor_picture_finish_access(pSrc, GLAMOR_GPU_ACCESS_RO);
+finish_dst:
+ glamor_picture_finish_access(pDst, GLAMOR_GPU_ACCESS_RW);
+
+ if (ok)
+ return;
+
+fallback:
+ glamor_check_triangles(op, pSrc, pDst, maskFormat,
+ xSrc, ySrc, ntri, tris);
+}
+
+void
+glamor_add_traps(PicturePtr pPicture,
+ INT16 x_off, INT16 y_off, int ntrap, xTrap * traps)
+{
+ int ok;
+
+ ok = glamor_picture_prepare_access(pPicture, GLAMOR_GPU_ACCESS_RW);
+ if (ok) {
+ ok = glamor_add_traps_nf(pPicture,
+ x_off, y_off, ntrap, traps);
+ glamor_picture_finish_access(pPicture, GLAMOR_GPU_ACCESS_RW);
+ }
+
+ if (!ok)
+ glamor_check_add_traps(pPicture, x_off, y_off, ntrap, traps);
+}
+
+#endif /* RENDER */
+
+
+/**
+ * radeon_glamor_close_screen() unwraps its wrapped screen functions and tears down GLAMOR's
+ * screen private, before calling down to the next CloseSccreen.
+ */
+static Bool radeon_glamor_close_screen(CLOSE_SCREEN_ARGS_DECL)
+{
+ glamor_screen_t *glamor_screen = glamor_get_screen(pScreen);
+#ifdef RENDER
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+#endif
+
+ pScreen->CreateGC = glamor_screen->SavedCreateGC;
+ pScreen->CloseScreen = glamor_screen->SavedCloseScreen;
+ pScreen->GetImage = glamor_screen->SavedGetImage;
+ pScreen->GetSpans = glamor_screen->SavedGetSpans;
+ pScreen->CreatePixmap = glamor_screen->SavedCreatePixmap;
+ pScreen->DestroyPixmap = glamor_screen->SavedDestroyPixmap;
+ pScreen->CopyWindow = glamor_screen->SavedCopyWindow;
+ pScreen->ChangeWindowAttributes =
+ glamor_screen->SavedChangeWindowAttributes;
+ pScreen->BitmapToRegion = glamor_screen->SavedBitmapToRegion;
+#ifdef RENDER
+ if (ps) {
+ ps->Composite = glamor_screen->SavedComposite;
+ ps->Glyphs = glamor_screen->SavedGlyphs;
+ ps->Trapezoids = glamor_screen->SavedTrapezoids;
+ ps->AddTraps = glamor_screen->SavedAddTraps;
+ ps->Triangles = glamor_screen->SavedTriangles;
+
+ ps->UnrealizeGlyph = glamor_screen->SavedUnrealizeGlyph;
+ }
+#endif
+
+ free(glamor_screen);
+
+ return (*pScreen->CloseScreen) (CLOSE_SCREEN_ARGS);
+}
+
+/**
+ * @param screen screen being initialized
+ */
+Bool glamor_screen_init(ScreenPtr screen)
+{
+ glamor_screen_t *glamor_screen;
+
+#if HAS_DIXREGISTERPRIVATEKEY
+ if (!dixRegisterPrivateKey(&glamor_screen_index, PRIVATE_SCREEN, 0))
+ return FALSE;
+#endif
+ glamor_screen = calloc(sizeof(glamor_screen_t), 1);
+
+ if (!glamor_screen) {
+ LogMessage(X_WARNING,
+ "GLAMOR(%d): Failed to allocate screen private\n",
+ screen->myNum);
+ return FALSE;
+ }
+
+ dixSetPrivate(&screen->devPrivates, &glamor_screen_index, glamor_screen);
+
+ /*
+ * Replace various fb screen functions
+ */
+ glamor_screen->SavedCloseScreen = screen->CloseScreen;
+ screen->CloseScreen = radeon_glamor_close_screen;
+
+ glamor_screen->SavedCreateGC = screen->CreateGC;
+ screen->CreateGC = radeon_glamor_create_gc;
+
+ glamor_screen->SavedGetImage = screen->GetImage;
+ screen->GetImage = glamor_get_image;
+
+ glamor_screen->SavedGetSpans = screen->GetSpans;
+ screen->GetSpans = glamor_get_spans;
+
+ glamor_screen->SavedCreatePixmap = screen->CreatePixmap;
+ glamor_screen->SavedDestroyPixmap = screen->DestroyPixmap;
+
+ glamor_screen->SavedCopyWindow = screen->CopyWindow;
+ screen->CopyWindow = glamor_copy_window;
+
+ glamor_screen->SavedChangeWindowAttributes =
+ screen->ChangeWindowAttributes;
+ screen->ChangeWindowAttributes = glamor_change_window_attributes;
+
+ glamor_screen->SavedBitmapToRegion = screen->BitmapToRegion;
+ screen->BitmapToRegion = glamor_bitmap_to_region;
+
+#ifdef RENDER
+ {
+ PictureScreenPtr ps = GetPictureScreenIfSet(screen);
+ if (ps) {
+ glamor_screen->SavedComposite = ps->Composite;
+ ps->Composite = glamor_composite;
+
+ glamor_screen->SavedGlyphs = ps->Glyphs;
+ ps->Glyphs = glamor_glyphs;
+
+ glamor_screen->SavedTriangles = ps->Triangles;
+ ps->Triangles = glamor_triangles;
+
+ glamor_screen->SavedTrapezoids = ps->Trapezoids;
+ ps->Trapezoids = glamor_trapezoids;
+
+ glamor_screen->SavedAddTraps = ps->AddTraps;
+ ps->AddTraps = glamor_add_traps;
+ }
+ }
+#endif
+
+ return TRUE;
+}
diff --git a/src/radeon_glamor_wrappers.h b/src/radeon_glamor_wrappers.h
new file mode 100644
index 0000000..9abbd22
--- /dev/null
+++ b/src/radeon_glamor_wrappers.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright © 2000,2008 Keith Packard
+ * 2004 Eric Anholt
+ * 2005 Zack Rusin, Trolltech
+ * 2012 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.
+ */
+
+#ifndef RADEON_GLAMOR_WRAPPERS_H
+#define RADEON_GLAMOR_WRAPPERS_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+#include <xorg-server.h>
+#include "xf86.h"
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "servermd.h"
+#include "mibstore.h"
+#include "colormapst.h"
+#include "gcstruct.h"
+#include "input.h"
+#include "mipointer.h"
+#include "mi.h"
+#include "dix.h"
+#include "fb.h"
+#include "fboverlay.h"
+#ifdef RENDER
+//#include "fbpict.h"
+#include "glyphstr.h"
+#include "picturestr.h"
+#endif
+#include "damage.h"
+
+#include "../src/compat-api.h"
+
+/* Provide substitutes for gcc's __FUNCTION__ on other compilers */
+#if !defined(__GNUC__) && !defined(__FUNCTION__)
+# if defined(__STDC__) && (__STDC_VERSION__>=199901L) /* C99 */
+# define __FUNCTION__ __func__
+# else
+# define __FUNCTION__ ""
+# endif
+#endif
+
+/* 1.6 and earlier server compat */
+#ifndef miGetCompositeClip
+#define miCopyRegion fbCopyRegion
+#define miDoCopy fbDoCopy
+#endif
+
+typedef enum {
+ GLAMOR_CPU_ACCESS_RO,
+ GLAMOR_CPU_ACCESS_RW,
+ GLAMOR_GPU_ACCESS_RO,
+ GLAMOR_GPU_ACCESS_RW
+} glamor_access_t;
+
+#include "radeon.h"
+#include "glamor.h"
+
+
+Bool glamor_screen_init(ScreenPtr screen);
+
+void glamor_set_fallback_debug(ScreenPtr screen, Bool enable);
+
+#define DEBUG_MIGRATE 0
+#define DEBUG_PIXMAP 0
+#define DEBUG_OFFSCREEN 0
+#define DEBUG_GLYPH_CACHE 0
+
+#define GLAMOR_FALLBACK(x) \
+if (glamor_get_screen(screen)->fallback_debug) { \
+ ErrorF("GLAMOR fallback at %s: ", __FUNCTION__); \
+ ErrorF x; \
+}
+
+#if DEBUG_PIXMAP
+#define DBG_PIXMAP(a) ErrorF a
+#else
+#define DBG_PIXMAP(a)
+#endif
+
+typedef void (*EnableDisableFBAccessProcPtr) (int, Bool);
+typedef struct {
+ CreateGCProcPtr SavedCreateGC;
+ 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
+
+ Bool fallback_debug;
+} glamor_screen_t;
+
+/*
+ * This is the only completely portable way to
+ * compute this info.
+ */
+#ifndef BitsPerPixel
+#define BitsPerPixel(d) (\
+ PixmapWidthPaddingInfo[d].notPower2 ? \
+ (PixmapWidthPaddingInfo[d].bytesPerPixel * 8) : \
+ ((1 << PixmapWidthPaddingInfo[d].padBytesLog2) * 8 / \
+ (PixmapWidthPaddingInfo[d].padRoundUp+1)))
+#endif
+
+#if HAS_DEVPRIVATEKEYREC
+extern DevPrivateKeyRec glamor_screen_index;
+#else
+extern int glamor_screen_index;
+#endif
+
+static inline glamor_screen_t *glamor_get_screen(ScreenPtr screen)
+{
+#if HAS_DEVPRIVATEKEYREC
+ return dixGetPrivate(&screen->devPrivates, &glamor_screen_index);
+#else
+ return dixLookupPrivate(&screen->devPrivates, &glamor_screen_index);
+#endif
+}
+
+#ifdef RENDER
+
+/* XXX these are in fbpict.h, which is not installed */
+void
+fbComposite(CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask, INT16 xDst, INT16 yDst, CARD16 width, CARD16 height);
+
+void
+fbAddTraps(PicturePtr pPicture,
+ INT16 xOff, INT16 yOff, int ntrap, xTrap * traps);
+
+#endif
+
+#endif /* RADEON_GLAMOR_WRAPPERS_H */
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 5d9ccff..5cc362f 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -418,6 +418,7 @@ static Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn)
(!RADEONIsAccelWorking(pScrn))) {
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"GPU accel disabled or not working, using shadowfb for KMS\n");
+shadowfb:
info->r600_shadow_fb = TRUE;
if (!xf86LoadSubModule(pScrn, "shadow"))
info->r600_shadow_fb = FALSE;
@@ -427,7 +428,9 @@ static Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn)
if (radeon_glamor_pre_init(pScrn))
return TRUE;
- if (info->ChipFamily == CHIP_FAMILY_PALM) {
+ if (info->ChipFamily >= CHIP_FAMILY_TAHITI) {
+ goto shadowfb;
+ } else if (info->ChipFamily == CHIP_FAMILY_PALM) {
info->accel_state->allowHWDFS = RADEONIsFusionGARTWorking(pScrn);
} else
info->accel_state->allowHWDFS = TRUE;
diff --git a/src/radeon_pci_chipset_gen.h b/src/radeon_pci_chipset_gen.h
index c9f9656..02c0a7e 100644
--- a/src/radeon_pci_chipset_gen.h
+++ b/src/radeon_pci_chipset_gen.h
@@ -537,5 +537,44 @@ static PciChipsets RADEONPciChipsets[] = {
{ PCI_CHIP_ARUBA_99A0, PCI_CHIP_ARUBA_99A0, RES_SHARED_VGA },
{ PCI_CHIP_ARUBA_99A2, PCI_CHIP_ARUBA_99A2, RES_SHARED_VGA },
{ PCI_CHIP_ARUBA_99A4, PCI_CHIP_ARUBA_99A4, RES_SHARED_VGA },
+ { PCI_CHIP_TAHITI_6780, PCI_CHIP_TAHITI_6780, RES_SHARED_VGA },
+ { PCI_CHIP_TAHITI_6784, PCI_CHIP_TAHITI_6784, RES_SHARED_VGA },
+ { PCI_CHIP_TAHITI_6788, PCI_CHIP_TAHITI_6788, RES_SHARED_VGA },
+ { PCI_CHIP_TAHITI_678A, PCI_CHIP_TAHITI_678A, RES_SHARED_VGA },
+ { PCI_CHIP_TAHITI_6790, PCI_CHIP_TAHITI_6790, RES_SHARED_VGA },
+ { PCI_CHIP_TAHITI_6798, PCI_CHIP_TAHITI_6798, RES_SHARED_VGA },
+ { PCI_CHIP_TAHITI_6799, PCI_CHIP_TAHITI_6799, RES_SHARED_VGA },
+ { PCI_CHIP_TAHITI_679A, PCI_CHIP_TAHITI_679A, RES_SHARED_VGA },
+ { PCI_CHIP_TAHITI_679E, PCI_CHIP_TAHITI_679E, RES_SHARED_VGA },
+ { PCI_CHIP_TAHITI_679F, PCI_CHIP_TAHITI_679F, RES_SHARED_VGA },
+ { PCI_CHIP_PITCAIRN_6800, PCI_CHIP_PITCAIRN_6800, RES_SHARED_VGA },
+ { PCI_CHIP_PITCAIRN_6801, PCI_CHIP_PITCAIRN_6801, RES_SHARED_VGA },
+ { PCI_CHIP_PITCAIRN_6802, PCI_CHIP_PITCAIRN_6802, RES_SHARED_VGA },
+ { PCI_CHIP_PITCAIRN_6808, PCI_CHIP_PITCAIRN_6808, RES_SHARED_VGA },
+ { PCI_CHIP_PITCAIRN_6809, PCI_CHIP_PITCAIRN_6809, RES_SHARED_VGA },
+ { PCI_CHIP_PITCAIRN_6810, PCI_CHIP_PITCAIRN_6810, RES_SHARED_VGA },
+ { PCI_CHIP_PITCAIRN_6818, PCI_CHIP_PITCAIRN_6818, RES_SHARED_VGA },
+ { PCI_CHIP_PITCAIRN_6819, PCI_CHIP_PITCAIRN_6819, RES_SHARED_VGA },
+ { PCI_CHIP_PITCAIRN_684C, PCI_CHIP_PITCAIRN_684C, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6820, PCI_CHIP_VERDE_6820, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6821, PCI_CHIP_VERDE_6821, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6823, PCI_CHIP_VERDE_6823, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6824, PCI_CHIP_VERDE_6824, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6825, PCI_CHIP_VERDE_6825, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6826, PCI_CHIP_VERDE_6826, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6827, PCI_CHIP_VERDE_6827, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6828, PCI_CHIP_VERDE_6828, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6829, PCI_CHIP_VERDE_6829, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_682B, PCI_CHIP_VERDE_682B, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_682D, PCI_CHIP_VERDE_682D, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_682F, PCI_CHIP_VERDE_682F, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6830, PCI_CHIP_VERDE_6830, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6831, PCI_CHIP_VERDE_6831, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6837, PCI_CHIP_VERDE_6837, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6838, PCI_CHIP_VERDE_6838, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_6839, PCI_CHIP_VERDE_6839, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_683B, PCI_CHIP_VERDE_683B, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_683D, PCI_CHIP_VERDE_683D, RES_SHARED_VGA },
+ { PCI_CHIP_VERDE_683F, PCI_CHIP_VERDE_683F, RES_SHARED_VGA },
{ -1, -1, RES_UNDEFINED }
};
diff --git a/src/radeon_pci_device_match_gen.h b/src/radeon_pci_device_match_gen.h
index a6663e0..f729914 100644
--- a/src/radeon_pci_device_match_gen.h
+++ b/src/radeon_pci_device_match_gen.h
@@ -537,5 +537,44 @@ static const struct pci_id_match radeon_device_match[] = {
ATI_DEVICE_MATCH( PCI_CHIP_ARUBA_99A0, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_ARUBA_99A2, 0 ),
ATI_DEVICE_MATCH( PCI_CHIP_ARUBA_99A4, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_TAHITI_6780, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_TAHITI_6784, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_TAHITI_6788, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_TAHITI_678A, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_TAHITI_6790, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_TAHITI_6798, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_TAHITI_6799, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_TAHITI_679A, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_TAHITI_679E, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_TAHITI_679F, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_PITCAIRN_6800, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_PITCAIRN_6801, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_PITCAIRN_6802, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_PITCAIRN_6808, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_PITCAIRN_6809, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_PITCAIRN_6810, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_PITCAIRN_6818, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_PITCAIRN_6819, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_PITCAIRN_684C, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6820, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6821, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6823, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6824, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6825, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6826, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6827, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6828, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6829, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_682B, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_682D, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_682F, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6830, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6831, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6837, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6838, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_6839, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_683B, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_683D, 0 ),
+ ATI_DEVICE_MATCH( PCI_CHIP_VERDE_683F, 0 ),
{ 0, 0, 0 }
};
diff --git a/src/radeon_probe.h b/src/radeon_probe.h
index 576f722..07bc080 100644
--- a/src/radeon_probe.h
+++ b/src/radeon_probe.h
@@ -102,6 +102,9 @@ typedef enum {
CHIP_FAMILY_CAICOS,
CHIP_FAMILY_CAYMAN,
CHIP_FAMILY_ARUBA,
+ CHIP_FAMILY_TAHITI,
+ CHIP_FAMILY_PITCAIRN,
+ CHIP_FAMILY_VERDE,
CHIP_FAMILY_LAST
} RADEONChipFamily;
diff --git a/src/radeon_version.h b/src/radeon_version.h
index 129046d..9a6fac1 100644
--- a/src/radeon_version.h
+++ b/src/radeon_version.h
@@ -39,6 +39,7 @@
#define R200_DRIVER_NAME "r200"
#define R300_DRIVER_NAME "r300"
#define R600_DRIVER_NAME "r600"
+#define SI_DRIVER_NAME "radeonsi"
#define RADEON_VERSION_MAJOR PACKAGE_VERSION_MAJOR
#define RADEON_VERSION_MINOR PACKAGE_VERSION_MINOR
commit e9edd2f5002c642b59f028b3ec076d604ae8ce9d
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Wed Jun 20 08:40:07 2012 +0200
Initial glamor support.
Enable at build time with --enable-glamor and runtime with
Option "AccelMethod" "glamor"
The most notable lack of functionality is XVideo. Use something like VDPAU for
now.
Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
diff --git a/configure.ac b/configure.ac
index a73dd4e..86199f2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -91,6 +91,20 @@ AM_CONDITIONAL(LIBUDEV, test x$LIBUDEV = xyes)
SAVE_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $XORG_CFLAGS"
+AC_MSG_CHECKING([whether to include GLAMOR support])
+AC_ARG_ENABLE(glamor,
+ AS_HELP_STRING([--enable-glamor],
+ [Enable glamor, a new GL-based acceleration [default=no]]),
+ [GLAMOR="$enableval"],
+ [GLAMOR=no])
+AC_MSG_RESULT([$GLAMOR])
+AM_CONDITIONAL(GLAMOR, test x$GLAMOR != xno)
+if test "x$GLAMOR" != "xno"; then
+ PKG_CHECK_MODULES(LIBGLAMOR, [glamor >= 0.3.1])
+ PKG_CHECK_MODULES(LIBGLAMOR_EGL, [glamor-egl])
+ AC_DEFINE(USE_GLAMOR, 1, [Enable glamor acceleration])
+fi
+
AC_CHECK_DECL(xf86ModeBandwidth,
[AC_DEFINE(HAVE_XF86MODEBANDWIDTH, 1, [Have xf86ModeBandwidth prototype])],
[],
diff --git a/man/radeon.man b/man/radeon.man
index da0c1cc..be50314 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -211,13 +211,6 @@ For example:
Option \*qZaphodHeads\*q \*qLVDS,VGA-0\*q
will assign xrandr outputs LVDS and VGA-0 to this instance of the driver.
.TP
-.BI "Option \*qEXAVSync\*q \*q" boolean \*q
-This option attempts to avoid tearing by stalling the engine until the display
-controller has passed the destination region. It reduces tearing at the cost
-of performance and has been known to cause instability on some chips.
-The default is
-.B off.
-.TP
.BI "Option \*qColorTiling\*q \*q" "boolean" \*q
The framebuffer can be addressed either in linear or tiled mode. Tiled mode can provide
significant performance benefits with 3D applications. Tiling will be disabled if the drm
@@ -241,6 +234,33 @@ The default value is
.B off
for R/RV6XX, R/RV7XX, RS780, RS880, EVERGREEN, and CAYMAN.
.TP
+.BI "Option \*qEnablePageFlip\*q \*q" boolean \*q
+Enable DRI2 page flipping. The default is
+.B on.
+Pageflipping is supported on all radeon hardware.
+.TP
+.BI "Option \*qAccelMethod\*q \*q" "string" \*q
+Chooses between available acceleration architectures. Valid values are
+.B EXA
+and
+.B glamor.
+The default is
+.B EXA.
+
+.PP
+The following driver
+.B Options
+are supported for
+.B EXA
+:
+.TP
+.BI "Option \*qEXAVSync\*q \*q" boolean \*q
+This option attempts to avoid tearing by stalling the engine until the display
+controller has passed the destination region. It reduces tearing at the cost
+of performance and has been known to cause instability on some chips.
+The default is
+.B off.
+.TP
.BI "Option \*qEXAPixmaps\*q \*q" boolean \*q
Under KMS, to avoid thrashing pixmaps in/out of VRAM on low memory cards,
we use a heuristic based on VRAM amount to determine whether to allow EXA
@@ -259,11 +279,6 @@ the framerate of applications that render frames at less than refresh rate.
.IP
The default value is
.B on.
-.TP
-.BI "Option \*qEnablePageFlip\*q \*q" boolean \*q
-Enable DRI2 page flipping. The default is
-.B on.
-Pageflipping is supported on all radeon hardware.
.SH TEXTURED VIDEO ATTRIBUTES
The driver supports the following X11 Xv attributes for Textured Video.
diff --git a/src/Makefile.am b/src/Makefile.am
index e857f21..da94927 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -64,6 +64,13 @@ radeon_drv_la_SOURCES = \
$(RADEON_EXA_SOURCES) \
$(RADEON_KMS_SRCS)
+if GLAMOR
+AM_CFLAGS += @LIBGLAMOR_CFLAGS@
+radeon_drv_la_LIBADD += @LIBGLAMOR_LIBS@
+radeon_drv_la_SOURCES += \
+ radeon_glamor.c
+endif
+
EXTRA_DIST = \
radeon_textured_videofuncs.c \
r600_reg.h \
@@ -88,6 +95,7 @@ EXTRA_DIST = \
radeon_exa_render.c \
radeon_exa_funcs.c \
radeon_exa_shared.h \
+ radeon_glamor.h \
radeon.h \
radeon_probe.h \
radeon_reg.h \
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 27569e5..6a35728 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -101,7 +101,8 @@ static PixmapPtr drmmode_create_bo_pixmap(ScrnInfoPtr pScrn,
return NULL;
}
- exaMoveInPixmap(pixmap);
+ if (!info->use_glamor)
+ exaMoveInPixmap(pixmap);
radeon_set_pixmap_bo(pixmap, bo);
if (info->ChipFamily >= CHIP_FAMILY_R600) {
surface = radeon_get_pixmap_surface(pixmap);
@@ -278,7 +279,7 @@ void drmmode_copy_fb(ScrnInfoPtr pScrn, drmmode_ptr drmmode)
uint32_t tiling_flags = 0;
Bool ret;
- if (info->accelOn == FALSE)
+ if (info->accelOn == FALSE || info->use_glamor)
goto fallback;
for (i = 0; i < xf86_config->num_crtc; i++) {
@@ -1442,6 +1443,9 @@ 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)
diff --git a/src/radeon.h b/src/radeon.h
index d357dc1..2f05249 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -51,6 +51,7 @@
#include "exa.h"
+#include "radeon_glamor.h"
/* Exa and Cursor Support */
#include "xf86Cursor.h"
@@ -429,6 +430,7 @@ typedef struct {
Bool allowColorTiling2D;
struct radeon_accel_state *accel_state;
Bool accelOn;
+ Bool use_glamor;
Bool exa_pixmaps;
Bool exa_force_create;
XF86ModReqInfo exaReq;
@@ -522,11 +524,107 @@ extern void radeon_ddx_cs_start(ScrnInfoPtr pScrn,
int num, const char *file,
const char *func, int line);
void radeon_kms_update_vram_limit(ScrnInfoPtr pScrn, int new_fb_size);
-struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix);
-struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix);
-void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo);
+
+static inline struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix)
+{
+#ifdef USE_GLAMOR
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen));
+
+ if (info->use_glamor) {
+ struct radeon_pixmap *priv;
+ priv = radeon_get_pixmap_private(pPix);
+ return priv ? &priv->surface : NULL;
+ } else
+#endif
+ {
+ struct radeon_exa_pixmap_priv *driver_priv;
+ driver_priv = exaGetPixmapDriverPrivate(pPix);
+ return &driver_priv->surface;
+ }
+
+ return NULL;
+}
+
uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix);
+static inline void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
+{
+#ifdef USE_GLAMOR
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen));
+
+ if (info->use_glamor) {
+ struct radeon_pixmap *priv;
+
+ priv = radeon_get_pixmap_private(pPix);
+ if (priv == NULL && bo == NULL)
+ return;
+
+ if (priv) {
+ if (priv->bo == bo)
+ return;
+
+ if (priv->bo)
+ radeon_bo_unref(priv->bo);
+
+ free(priv);
+ priv = NULL;
+ }
+
+ if (bo) {
+ uint32_t pitch;
+
+ priv = calloc(1, sizeof (struct radeon_pixmap));
+ if (priv == NULL)
+ goto out;
+
+ radeon_bo_ref(bo);
+ priv->bo = bo;
+
+ radeon_bo_get_tiling(bo, &priv->tiling_flags, &pitch);
+ }
+out:
+ radeon_set_pixmap_private(pPix, priv);
+ } else
+#endif /* USE_GLAMOR */
+ {
+ struct radeon_exa_pixmap_priv *driver_priv;
+
+ driver_priv = exaGetPixmapDriverPrivate(pPix);
+ if (driver_priv) {
+ uint32_t pitch;
+
+ if (driver_priv->bo)
+ radeon_bo_unref(driver_priv->bo);
+
+ radeon_bo_ref(bo);
+ driver_priv->bo = bo;
+
+ radeon_bo_get_tiling(bo, &driver_priv->tiling_flags, &pitch);
+ }
+ }
+}
+
+static inline struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
+{
+#ifdef USE_GLAMOR
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(pPix->drawable.pScreen));
+
+ if (info->use_glamor) {
+ struct radeon_pixmap *priv;
+ priv = radeon_get_pixmap_private(pPix);
+ return priv ? priv->bo : NULL;
+ } else
+#endif
+ {
+ struct radeon_exa_pixmap_priv *driver_priv;
+ driver_priv = exaGetPixmapDriverPrivate(pPix);
+ return driver_priv->bo;
+ }
+
+ return NULL;
+}
+
+
#define CP_PACKET0(reg, n) \
(RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2))
#define CP_PACKET1(reg0, reg1) \
@@ -659,6 +757,7 @@ static __inline__ void RADEON_SYNC(RADEONInfoPtr info, ScrnInfoPtr pScrn)
}
enum {
+ RADEON_CREATE_PIXMAP_DRI2 = 0x08000000,
RADEON_CREATE_PIXMAP_TILING_MACRO = 0x10000000,
RADEON_CREATE_PIXMAP_TILING_MICRO = 0x20000000,
RADEON_CREATE_PIXMAP_DEPTH = 0x40000000, /* for r200 */
diff --git a/src/radeon_accel.c b/src/radeon_accel.c
index 15cf2bd..8eff5c5 100644
--- a/src/radeon_accel.c
+++ b/src/radeon_accel.c
@@ -182,7 +182,12 @@ Bool RADEONAccelInit(ScreenPtr pScreen)
RADEONInfoPtr info = RADEONPTR(pScrn);
if (info->directRenderingEnabled) {
- if (info->ChipFamily >= CHIP_FAMILY_CEDAR) {
+ if (info->use_glamor) {
+ if (!radeon_glamor_init(pScreen)) {
+ info->use_glamor = FALSE;
+ return FALSE;
+ }
+ } else if (info->ChipFamily >= CHIP_FAMILY_CEDAR) {
if (!EVERGREENDrawInit(pScreen))
return FALSE;
} else
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index 8c24de9..12b198c 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -73,6 +73,77 @@ struct dri2_buffer_priv {
};
+static PixmapPtr get_drawable_pixmap(DrawablePtr drawable)
+{
+ if (drawable->type == DRAWABLE_PIXMAP)
+ return (PixmapPtr)drawable;
+ else
+ return (*drawable->pScreen->GetWindowPixmap)((WindowPtr)drawable);
+}
+
+
+static PixmapPtr fixup_glamor(DrawablePtr drawable, PixmapPtr pixmap)
+{
+ PixmapPtr old = get_drawable_pixmap(drawable);
+#ifdef USE_GLAMOR
+ ScreenPtr screen = drawable->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ struct radeon_pixmap *priv = radeon_get_pixmap_private(pixmap);
+ GCPtr gc;
+
+ /* With a glamor pixmap, 2D pixmaps are created in texture
+ * and without a static BO attached to it. To support DRI,
+ * we need to create a new textured-drm pixmap and
+ * need to copy the original content to this new textured-drm
+ * pixmap, and then convert the old pixmap to a coherent
+ * textured-drm pixmap which has a valid BO attached to it
+ * and also has a valid texture, thus both glamor and DRI2
+ * can access it.
+ *
+ */
+
+ /* Copy the current contents of the pixmap to the bo. */
+ gc = GetScratchGC(drawable->depth, screen);
+ if (gc) {
+ ValidateGC(&pixmap->drawable, gc);
+ gc->ops->CopyArea(&old->drawable, &pixmap->drawable,
+ gc,
+ 0, 0,
+ old->drawable.width,
+ old->drawable.height,
+ 0, 0);
+ FreeScratchGC(gc);
+ }
+
+ radeon_set_pixmap_private(pixmap, NULL);
+ screen->DestroyPixmap(pixmap);
+
+ /* And redirect the pixmap to the new bo (for 3D). */
+ radeon_set_pixmap_private(old, priv);
+ old->refcnt++;
+
+ /* This creating should not fail, as we already created its
+ * successfully. But if it happens, we put a warning indicator
+ * here, and the old pixmap will still be a glamor pixmap, and
+ * latter the pixmap_flink will get a 0 name, then the X server
+ * will pass a BadAlloc to the client.*/
+ if (!radeon_glamor_create_textured_pixmap(old))
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Failed to get DRI drawable for glamor pixmap.\n");
+
+ screen->ModifyPixmapHeader(old,
+ old->drawable.width,
+ old->drawable.height,
+ 0, 0,
+ priv->stride,
+ NULL);
+
+#endif /* USE_GLAMOR*/
+
+ return old;
+}
+
+
#ifndef USE_DRI2_1_1_0
static BufferPtr
radeon_dri2_create_buffers(DrawablePtr drawable,
@@ -85,13 +156,13 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
BufferPtr buffers;
struct dri2_buffer_priv *privates;
PixmapPtr pixmap, depth_pixmap;
- struct radeon_exa_pixmap_priv *driver_priv;
+ struct radeon_bo *bo;
int i, r, need_enlarge = 0;
int flags = 0;
unsigned front_width;
uint32_t tiling = 0;
- pixmap = screen->GetScreenPixmap(screen);
+ pixmap = pScreen->GetScreenPixmap(pScreen);
front_width = pixmap->drawable.width;
buffers = calloc(count, sizeof *buffers);
@@ -106,17 +177,25 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
depth_pixmap = NULL;
for (i = 0; i < count; i++) {
+ Bool is_glamor_pixmap = FALSE;
+ unsigned aligned_width = drawable->width;
+ unsigned aligned_height = drawable->height;
+
if (attachments[i] == DRI2BufferFrontLeft) {
- if (drawable->type == DRAWABLE_PIXMAP) {
- pixmap = (Pixmap*)drawable;
- } else {
- pixmap = (*pScreen->GetWindowPixmap)((WindowPtr)drawable);
- }
- pixmap->refcnt++;
+ pixmap = get_drawable_pixmap(drawable);
+ if (info->use_glamor && !radeon_get_pixmap_bo(pixmap)) {
+ is_glamor_pixmap = TRUE;
+ aligned_width = pixmap->drawable.width;
+ aligned_height = pixmap->drawable.height;
+ pixmap = NULL;
+ } else
+ pixmap->refcnt++;
} else if (attachments[i] == DRI2BufferStencil && depth_pixmap) {
pixmap = depth_pixmap;
pixmap->refcnt++;
- } else {
+ }
+
+ if (!pixmap) {
/* tile the back buffer */
switch(attachments[i]) {
case DRI2BufferDepth:
@@ -145,6 +224,8 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
break;
case DRI2BufferBackLeft:
case DRI2BufferBackRight:
+ case DRI2BufferFrontLeft:
+ case DRI2BufferFrontRight:
case DRI2BufferFakeFrontLeft:
case DRI2BufferFakeFrontRight:
if (info->ChipFamily >= CHIP_FAMILY_R600)
@@ -164,14 +245,15 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
if (flags & RADEON_CREATE_PIXMAP_TILING_MACRO)
tiling |= RADEON_TILING_MACRO;
+ if (aligned_width == front_width)
+ aligned_width = pScrn->virtualX;
+
if (need_enlarge) {
/* evergreen uses separate allocations for depth and stencil
* so we make an extra large depth buffer to cover stencil
* as well.
*/
- unsigned aligned_width = drawable->width;
unsigned width_align = drmmode_get_pitch_align(pScrn, drawable->depth / 8, tiling);
- unsigned aligned_height;
unsigned height_align = drmmode_get_height_align(pScrn, tiling);
unsigned base_align = drmmode_get_base_align(pScrn, drawable->depth / 8, tiling);
unsigned pitch_bytes;
@@ -181,42 +263,33 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
aligned_width = pScrn->virtualX;
aligned_width = RADEON_ALIGN(aligned_width, width_align);
pitch_bytes = aligned_width * (drawable->depth / 8);
- aligned_height = RADEON_ALIGN(drawable->height, height_align);
+ aligned_height = RADEON_ALIGN(aligned_height, height_align);
size = pitch_bytes * aligned_height;
size = RADEON_ALIGN(size, base_align);
/* add additional size for stencil */
size += aligned_width * aligned_height;
aligned_height = RADEON_ALIGN(size / pitch_bytes, height_align);
-
- pixmap = (*pScreen->CreatePixmap)(pScreen,
- aligned_width,
- aligned_height,
- drawable->depth,
- flags);
-
- } else {
- unsigned aligned_width = drawable->width;
-
- if (aligned_width == front_width)
- aligned_width = pScrn->virtualX;
-
- pixmap = (*pScreen->CreatePixmap)(pScreen,
- aligned_width,
- drawable->height,
- drawable->depth,
- flags);
}
+
+ pixmap = (*pScreen->CreatePixmap)(pScreen,
+ aligned_width,
+ aligned_height,
+ drawable->depth,
+ flags | RADEON_CREATE_PIXMAP_DRI2);
}
if (attachments[i] == DRI2BufferDepth) {
depth_pixmap = pixmap;
}
- info->exa_force_create = TRUE;
- exaMoveInPixmap(pixmap);
- info->exa_force_create = FALSE;
- driver_priv = exaGetPixmapDriverPrivate(pixmap);
- if (!driver_priv ||
- radeon_gem_get_kernel_name(driver_priv->bo, &buffers[i].name) != 0) {
+ if (!info->use_glamor) {
+ info->exa_force_create = TRUE;
+ exaMoveInPixmap(pixmap);
+ info->exa_force_create = FALSE;
+ }
+ if (is_glamor_pixmap)
+ pixmap = fixup_glamor(drawable, pixmap);
+ bo = radeon_get_pixmap_bo(pixmap);
+ if (!bo || radeon_gem_get_kernel_name(bo, &buffers[i].name) != 0) {
int j;
for (j = 0; j < i; j++)
@@ -249,11 +322,13 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
BufferPtr buffers;
struct dri2_buffer_priv *privates;
PixmapPtr pixmap, depth_pixmap;
- struct radeon_exa_pixmap_priv *driver_priv;
+ struct radeon_bo *bo;
int flags;
unsigned front_width;
uint32_t tiling = 0;
unsigned aligned_width = drawable->width;
+ unsigned height = drawable->height;
+ Bool is_glamor_pixmap = FALSE;
pixmap = pScreen->GetScreenPixmap(pScreen);
front_width = pixmap->drawable.width;
@@ -261,16 +336,20 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
pixmap = depth_pixmap = NULL;
if (attachment == DRI2BufferFrontLeft) {
- if (drawable->type == DRAWABLE_PIXMAP) {
- pixmap = (PixmapPtr)drawable;
- } else {
- pixmap = (*pScreen->GetWindowPixmap)((WindowPtr)drawable);
- }
- pixmap->refcnt++;
+ pixmap = get_drawable_pixmap(drawable);
+ if (info->use_glamor && !radeon_get_pixmap_bo(pixmap)) {
+ 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++;
- } else {
+ }
+
+ if (!pixmap) {
/* tile the back buffer */
switch(attachment) {
case DRI2BufferDepth:
@@ -310,6 +389,8 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
break;
case DRI2BufferBackLeft:
case DRI2BufferBackRight:
+ case DRI2BufferFrontLeft:
+ case DRI2BufferFrontRight:
case DRI2BufferFakeFrontLeft:
case DRI2BufferFakeFrontRight:
if (info->ChipFamily >= CHIP_FAMILY_R600) {
@@ -336,9 +417,9 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
pixmap = (*pScreen->CreatePixmap)(pScreen,
aligned_width,
- drawable->height,
+ height,
(format != 0)?format:drawable->depth,
- flags);
+ flags | RADEON_CREATE_PIXMAP_DRI2);
}
if (!pixmap)
@@ -351,12 +432,15 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
if (attachment == DRI2BufferDepth) {
depth_pixmap = pixmap;
}
- info->exa_force_create = TRUE;
- exaMoveInPixmap(pixmap);
- info->exa_force_create = FALSE;
- driver_priv = exaGetPixmapDriverPrivate(pixmap);
- if (!driver_priv ||
- (radeon_gem_get_kernel_name(driver_priv->bo, &buffers->name) != 0))
+ if (!info->use_glamor) {
+ info->exa_force_create = TRUE;
+ exaMoveInPixmap(pixmap);
+ info->exa_force_create = FALSE;
+ }
+ 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)
goto error;
privates = calloc(1, sizeof(struct dri2_buffer_priv));
@@ -476,11 +560,10 @@ radeon_dri2_copy_region(DrawablePtr drawable,
if (extents->x1 == 0 && extents->y1 == 0 &&
extents->x2 == drawable->width &&
extents->y2 == drawable->height) {
- struct radeon_exa_pixmap_priv *exa_priv =
- exaGetPixmapDriverPrivate(dst_private->pixmap);
+ struct radeon_bo *bo = radeon_get_pixmap_bo(dst_private->pixmap);
- if (exa_priv && exa_priv->bo)
- radeon_bo_wait(exa_priv->bo);
+ if (bo)
+ radeon_bo_wait(bo);
}
}
}
@@ -643,7 +726,7 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
void *data, unsigned int target_msc)
{
struct dri2_buffer_priv *back_priv;
- struct radeon_exa_pixmap_priv *exa_priv;
+ struct radeon_bo *bo;
DRI2FrameEventPtr flip_info;
/* Main crtc for this drawable shall finally deliver pageflip event. */
@@ -665,9 +748,9 @@ radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
/* Page flip the full screen buffer */
back_priv = back->driverPrivate;
- exa_priv = exaGetPixmapDriverPrivate(back_priv->pixmap);
+ bo = radeon_get_pixmap_bo(back_priv->pixmap);
- return radeon_do_pageflip(scrn, exa_priv->bo, flip_info, ref_crtc_hw_id);
+ return radeon_do_pageflip(scrn, bo, flip_info, ref_crtc_hw_id);
}
static Bool
@@ -675,19 +758,17 @@ 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_exa_pixmap_priv *driver_priv;
-
- if (draw->type == DRAWABLE_PIXMAP)
- pixmap = (PixmapPtr)draw;
- else
- pixmap = (*draw->pScreen->GetWindowPixmap)((WindowPtr)draw);
+ struct radeon_bo *bo;
+ pixmap = get_drawable_pixmap(draw);
pixmap->refcnt++;
- exaMoveInPixmap(pixmap);
- driver_priv = exaGetPixmapDriverPrivate(pixmap);
- r = radeon_gem_get_kernel_name(driver_priv->bo, &front->name);
+ if (!info->use_glamor)
+ exaMoveInPixmap(pixmap);
+ bo = radeon_get_pixmap_bo(pixmap);
+ r = radeon_gem_get_kernel_name(bo, &front->name);
if (r) {
(*draw->pScreen->DestroyPixmap)(pixmap);
return FALSE;
@@ -753,10 +834,9 @@ radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPt
{
struct dri2_buffer_priv *front_priv = front->driverPrivate;
struct dri2_buffer_priv *back_priv = back->driverPrivate;
- struct radeon_exa_pixmap_priv *front_radeon, *back_radeon;
+ struct radeon_bo *front_bo, *back_bo;
ScreenPtr screen;
RADEONInfoPtr info;
- struct radeon_bo *bo;
int tmp;
/* Swap BO names so DRI works */
@@ -765,22 +845,22 @@ radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPt
back->name = tmp;
/* Swap pixmap bos */
- front_radeon = exaGetPixmapDriverPrivate(front_priv->pixmap);
- back_radeon = exaGetPixmapDriverPrivate(back_priv->pixmap);
- bo = back_radeon->bo;
- back_radeon->bo = front_radeon->bo;
- front_radeon->bo = bo;
+ front_bo = radeon_get_pixmap_bo(front_priv->pixmap);
+ back_bo = radeon_get_pixmap_bo(back_priv->pixmap);
+ radeon_set_pixmap_bo(front_priv->pixmap, back_bo);
+ radeon_set_pixmap_bo(back_priv->pixmap, front_bo);
/* Do we need to update the Screen? */
screen = draw->pScreen;
info = RADEONPTR(xf86ScreenToScrn(screen));
- if (front_radeon->bo == info->front_bo) {
+ if (front_bo == info->front_bo) {
+ radeon_bo_ref(back_bo);
radeon_bo_unref(info->front_bo);
- info->front_bo = back_radeon->bo;
- radeon_bo_ref(info->front_bo);
- front_radeon = exaGetPixmapDriverPrivate(screen->GetScreenPixmap(screen));
- front_radeon->bo = bo;
+ info->front_bo = back_bo;
+ radeon_set_pixmap_bo(screen->GetScreenPixmap(screen), back_bo);
}
+
+ radeon_glamor_exchange_buffers(front_priv->pixmap, back_priv->pixmap);
}
void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index d80c7e4..5c5d997 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -325,20 +325,6 @@ void RADEONEXADestroyPixmap(ScreenPtr pScreen, void *driverPriv)
free(driverPriv);
}
-struct radeon_bo *radeon_get_pixmap_bo(PixmapPtr pPix)
-{
- struct radeon_exa_pixmap_priv *driver_priv;
- driver_priv = exaGetPixmapDriverPrivate(pPix);
- return driver_priv->bo;
-}
-
-struct radeon_surface *radeon_get_pixmap_surface(PixmapPtr pPix)
-{
- struct radeon_exa_pixmap_priv *driver_priv;
- driver_priv = exaGetPixmapDriverPrivate(pPix);
- return &driver_priv->surface;
-}
-
uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix)
{
struct radeon_exa_pixmap_priv *driver_priv;
@@ -346,24 +332,6 @@ uint32_t radeon_get_pixmap_tiling(PixmapPtr pPix)
return driver_priv->tiling_flags;
}
-void radeon_set_pixmap_bo(PixmapPtr pPix, struct radeon_bo *bo)
-{
- struct radeon_exa_pixmap_priv *driver_priv;
-
- driver_priv = exaGetPixmapDriverPrivate(pPix);
- if (driver_priv) {
- uint32_t pitch;
-
- if (driver_priv->bo)
- radeon_bo_unref(driver_priv->bo);
-
- radeon_bo_ref(bo);
- driver_priv->bo = bo;
-
- radeon_bo_get_tiling(bo, &driver_priv->tiling_flags, &pitch);
- }
-}
-
Bool RADEONEXAPixmapIsOffscreen(PixmapPtr pPix)
{
struct radeon_exa_pixmap_priv *driver_priv;
diff --git a/src/radeon_glamor.c b/src/radeon_glamor.c
new file mode 100644
index 0000000..232332e
--- /dev/null
+++ b/src/radeon_glamor.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright © 2011 Intel Corporation.
+ * 2012 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <xf86.h>
+#define GLAMOR_FOR_XORG 1
+#include <glamor.h>
+
+#include "radeon.h"
+#include "radeon_bo_helper.h"
+
+#if HAS_DEVPRIVATEKEYREC
+DevPrivateKeyRec glamor_pixmap_index;
+#else
+int glamor_pixmap_index;
+#endif
+
+void
+radeon_glamor_exchange_buffers(PixmapPtr src,
+ PixmapPtr dst)
+{
+ RADEONInfoPtr info = RADEONPTR(xf86ScreenToScrn(dst->drawable.pScreen));
+
+ if (!info->use_glamor)
+ return;
+ glamor_egl_exchange_buffers(src, dst);
+}
+
+Bool
+radeon_glamor_create_screen_resources(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ RADEONInfoPtr info = RADEONPTR(scrn);
+
+ if (!info->use_glamor)
+ return TRUE;
+
+ if (!glamor_glyphs_init(screen))
+ return FALSE;
+
+ if (!glamor_egl_create_textured_screen_ext(screen,
+ info->front_bo->handle,
+ scrn->displayWidth *
+ info->pixel_bytes,
+ NULL))
+ return FALSE;
+
+ return TRUE;
+}
+
+
+Bool
+radeon_glamor_pre_init(ScrnInfoPtr scrn)
+{
+ RADEONInfoPtr info = RADEONPTR(scrn);
+ pointer glamor_module;
+ CARD32 version;
+ const char *s;
+
+ s = xf86GetOptValString(info->Options, OPTION_ACCELMETHOD);
+ if (s == NULL)
+ return FALSE;
+
+ if (strcasecmp(s, "glamor") != 0)
+ return FALSE;
+
+ /* Load glamor module */
+ if ((glamor_module = xf86LoadSubModule(scrn, GLAMOR_EGL_MODULE_NAME))) {
+ version = xf86GetModuleVersion(glamor_module);
+ if (version < MODULE_VERSION_NUMERIC(0,3,1)) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "Incompatible glamor version, required >= 0.3.0.\n");
+ return FALSE;
+ } else {
+ if (glamor_egl_init(scrn, info->dri2.drm_fd)) {
+ xf86DrvMsg(scrn->scrnIndex, X_INFO,
+ "glamor detected, initialising EGL layer.\n");
+ } else {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "glamor detected, failed to initialize EGL.\n");
+ return FALSE;
+ }
+ }
+ } else {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR, "glamor not available\n");
+ return FALSE;
+ }
+
+ info->use_glamor = TRUE;
+
+ return TRUE;
+}
+
+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 (glamor_egl_create_textured_pixmap(pixmap, priv->bo->handle,
+ priv->stride))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static PixmapPtr
+radeon_glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
+ unsigned usage)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ struct radeon_pixmap *priv;
+ PixmapPtr pixmap, new_pixmap = NULL;
+
+ if (!(usage & RADEON_CREATE_PIXMAP_DRI2)) {
+ pixmap = glamor_create_pixmap(screen, w, h, depth, usage);
+ if (pixmap)
+ return pixmap;
+ }
+
+ if (w > 32767 || h > 32767)
+ return NullPixmap;
+
+ if (depth == 1)
+ return fbCreatePixmap(screen, w, h, depth, usage);
+
+ if (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && w <= 32 && h <= 32)
+ return fbCreatePixmap(screen, w, h, depth, usage);
+
+ pixmap = fbCreatePixmap(screen, 0, 0, depth, usage);
+ if (pixmap == NullPixmap)
+ return pixmap;
+
+ if (w && h) {
+ 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,
+ &priv->surface,
+ &priv->tiling_flags);
+ if (!priv->bo)
+ goto fallback_priv;
+
+ radeon_set_pixmap_private(pixmap, priv);
+
+ screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, priv->stride, NULL);
+
+ if (!radeon_glamor_create_textured_pixmap(pixmap))
+ goto fallback_glamor;
+ }
+
+ return pixmap;
+
+fallback_glamor:
+ if (usage & RADEON_CREATE_PIXMAP_DRI2) {
+ /* XXX need further work to handle the DRI2 failure case.
+ * Glamor don't know how to handle a BO only pixmap. Put
+ * a warning indicator here.
+ */
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "Failed to create textured DRI2 pixmap.");
+ return pixmap;
+ }
+ /* Create textured pixmap failed means glamor failed to
+ * create a texture from current BO for some reasons. We turn
+ * to create a new glamor pixmap and clean up current one.
+ * One thing need to be noted, this new pixmap doesn't
+ * has a priv and bo attached to it. It's glamor's responsbility
+ * to take care of it. Glamor will mark this new pixmap as a
+ * texture only pixmap and will never fallback to DDX layer
+ * afterwards.
+ */
+ new_pixmap = glamor_create_pixmap(screen, w, h, depth, usage);
+ radeon_bo_unref(priv->bo);
+fallback_priv:
+ free(priv);
+fallback_pixmap:
+ fbDestroyPixmap(pixmap);
+ if (new_pixmap)
+ return new_pixmap;
+ else
+ return fbCreatePixmap(screen, w, h, depth, usage);
+}
+
+static Bool radeon_glamor_destroy_pixmap(PixmapPtr pixmap)
+{
+ if (pixmap->refcnt == 1) {
+ glamor_egl_destroy_textured_pixmap(pixmap);
+ radeon_set_pixmap_bo(pixmap, NULL);
+ }
+ fbDestroyPixmap(pixmap);
+ return TRUE;
+}
+
+Bool
+radeon_glamor_init(ScreenPtr screen)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+
+ if (!glamor_init(screen, GLAMOR_INVERTED_Y_AXIS | GLAMOR_USE_EGL_SCREEN |
+ GLAMOR_USE_SCREEN | GLAMOR_USE_PICTURE_SCREEN)) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "Failed to initialize glamor.\n");
+ return FALSE;
+ }
+
+ if (!glamor_egl_init_textured_pixmap(screen)) {
+ xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+ "Failed to initialize textured pixmap of screen for glamor.\n");
+ return FALSE;
+ }
+
+#if HAS_DIXREGISTERPRIVATEKEY
+ if (!dixRegisterPrivateKey(&glamor_pixmap_index, PRIVATE_PIXMAP, 0))
+#else
+ if (!dixRequestPrivate(&glamor_pixmap_index, 0))
+#endif
+ return FALSE;
+
+ screen->CreatePixmap = radeon_glamor_create_pixmap;
+ screen->DestroyPixmap = radeon_glamor_destroy_pixmap;
+
+ xf86DrvMsg(scrn->scrnIndex, X_INFO,
+ "Use GLAMOR acceleration.\n");
+ return TRUE;
+}
+
+void
+radeon_glamor_flush(ScrnInfoPtr pScrn)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+
+ if (info->use_glamor)
+ glamor_block_handler(pScrn->pScreen);
+}
diff --git a/src/radeon_glamor.h b/src/radeon_glamor.h
new file mode 100644
index 0000000..40c9092
--- /dev/null
+++ b/src/radeon_glamor.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright © 2011 Intel Corporation.
+ * 2012 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_GLAMOR_H
+#define RADEON_GLAMOR_H
+
+#ifdef USE_GLAMOR
+
+#include "radeon_surface.h"
+
+Bool radeon_glamor_pre_init(ScrnInfoPtr scrn);
+Bool radeon_glamor_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);
+void radeon_glamor_exchange_buffers(PixmapPtr src, PixmapPtr dst);
+
+Bool radeon_glamor_pixmap_is_offscreen(PixmapPtr pixmap);
+
+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; }
+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 FALSE; }
+
+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; }
+
+#endif
+
+#endif /* RADEON_GLAMOR_H */
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index 61d6419..5d9ccff 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -224,7 +224,7 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
return FALSE;
}
- if (info->dri2.enabled) {
+ if (info->dri2.enabled || info->use_glamor) {
if (info->front_bo) {
PixmapPtr pPix = pScreen->GetScreenPixmap(pScreen);
radeon_set_pixmap_bo(pPix, info->front_bo);
@@ -234,6 +234,10 @@ static Bool RADEONCreateScreenResources_KMS(ScreenPtr pScreen)
}
}
}
+
+ if (info->use_glamor)
+ radeon_glamor_create_screen_resources(pScreen);
+
return TRUE;
}
@@ -247,6 +251,9 @@ static void RADEONBlockHandler_KMS(BLOCKHANDLER_ARGS_DECL)
(*pScreen->BlockHandler) (BLOCKHANDLER_ARGS);
pScreen->BlockHandler = RADEONBlockHandler_KMS;
+ if (info->use_glamor)
+ radeon_glamor_flush(pScrn);
+
radeon_cs_flush_indirect(pScrn);
}
@@ -258,6 +265,7 @@ radeon_flush_callback(CallbackListPtr *list,
if (pScrn->vtSema) {
radeon_cs_flush_indirect(pScrn);
+ radeon_glamor_flush(pScrn);
}
}
@@ -416,6 +424,9 @@ static Bool RADEONPreInitAccel_KMS(ScrnInfoPtr pScrn)
return TRUE;
}
+ if (radeon_glamor_pre_init(pScrn))
+ return TRUE;
+
if (info->ChipFamily == CHIP_FAMILY_PALM) {
info->accel_state->allowHWDFS = RADEONIsFusionGARTWorking(pScrn);
} else
@@ -838,16 +849,18 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
}
}
- info->exa_pixmaps = xf86ReturnOptValBool(info->Options,
- OPTION_EXA_PIXMAPS,
- ((info->vram_size > (32 * 1024 * 1024) &&
- info->RenderAccel)));
- if (info->exa_pixmaps)
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "EXA: Driver will allow EXA pixmaps in VRAM\n");
- else
- xf86DrvMsg(pScrn->scrnIndex, X_INFO,
- "EXA: Driver will not allow EXA pixmaps in VRAM\n");
+ if (!info->use_glamor) {
+ info->exa_pixmaps = xf86ReturnOptValBool(info->Options,
+ OPTION_EXA_PIXMAPS,
+ ((info->vram_size > (32 * 1024 * 1024) &&
+ info->RenderAccel)));
+ if (info->exa_pixmaps)
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "EXA: Driver will allow EXA pixmaps in VRAM\n");
+ else
+ xf86DrvMsg(pScrn->scrnIndex, X_INFO,
+ "EXA: Driver will not allow EXA pixmaps in VRAM\n");
+ }
/* no tiled scanout on r6xx+ yet */
if (info->allowColorTiling) {
@@ -1186,7 +1199,7 @@ Bool RADEONScreenInit_KMS(SCREEN_INIT_ARGS_DECL)
*/
/* xf86DiDGAInit(pScreen, info->LinearAddr + pScrn->fbOffset); */
#endif
- if (info->r600_shadow_fb == FALSE) {
+ if (!info->use_glamor && info->r600_shadow_fb == FALSE) {
/* Init Xv */
xf86DrvMsgVerb(pScrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
"Initializing Xv\n");
@@ -1322,7 +1335,7 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
xf86DrvMsg(pScreen->myNum, X_ERROR, "Memory map already initialized\n");
return FALSE;
}
- if (info->r600_shadow_fb == FALSE) {
+ if (!info->use_glamor && info->r600_shadow_fb == FALSE) {
info->accel_state->exa = exaDriverAlloc();
if (info->accel_state->exa == NULL) {
xf86DrvMsg(pScreen->myNum, X_ERROR, "exaDriverAlloc failed\n");
commit 9eac8021f3d33a63156f9f5d43a220e88bb3f8db
Author: Michel Dänzer <michel.daenzer at amd.com>
Date: Wed Jun 27 14:48:47 2012 +0200
EXA: Factor out pixmap BO allocation into a helper function.
Signed-off-by: Michel Dänzer <michel.daenzer at amd.com>
diff --git a/src/Makefile.am b/src/Makefile.am
index 5c09554..e857f21 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,7 +28,8 @@
radeon_drv_la_LIBADD = $(LIBDRM_RADEON_LIBS)
-RADEON_KMS_SRCS=radeon_dri2.c radeon_kms.c drmmode_display.c radeon_vbo.c
+RADEON_KMS_SRCS=radeon_dri2.c radeon_kms.c drmmode_display.c radeon_vbo.c \
+ radeon_bo_helper.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
@@ -82,6 +83,7 @@ EXTRA_DIST = \
ati.h \
ativersion.h \
bicubic_table.h \
+ radeon_bo_helper.h \
radeon_drm.h \
radeon_exa_render.c \
radeon_exa_funcs.c \
diff --git a/src/radeon.h b/src/radeon.h
index 742a6f8..d357dc1 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -665,4 +665,24 @@ enum {
RADEON_CREATE_PIXMAP_SZBUFFER = 0x80000000, /* for eg */
};
+
+/* Compute log base 2 of val. */
+static __inline__ int
+RADEONLog2(int val)
+{
+ int bits;
+#if (defined __i386__ || defined __x86_64__) && (defined __GNUC__)
+ __asm volatile("bsrl %1, %0"
+ : "=r" (bits)
+ : "c" (val)
+ );
+ return bits;
+#else
+ for (bits = 0; val != 0; val >>= 1, ++bits)
+ ;
+ return bits - 1;
+#endif
+}
+
+
#endif /* _RADEON_H_ */
diff --git a/src/radeon_bo_helper.c b/src/radeon_bo_helper.c
new file mode 100644
index 0000000..ccdf7eb
--- /dev/null
+++ b/src/radeon_bo_helper.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2012 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "radeon.h"
+
+
+static const unsigned MicroBlockTable[5][3][2] = {
+ /*linear tiled square-tiled */
+ {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */
+ {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */
+ {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */
+ {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */
+ {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */
+};
+
+/* Return true if macrotiling can be enabled */
+static Bool RADEONMacroSwitch(int width, int height, int bpp,
+ uint32_t flags, Bool rv350_mode)
+{
+ unsigned tilew, tileh, microtiled, logbpp;
+
+ logbpp = RADEONLog2(bpp / 8);
+ if (logbpp > 4)
+ return 0;
+
+ microtiled = !!(flags & RADEON_TILING_MICRO);
+ tilew = MicroBlockTable[logbpp][microtiled][0] * 8;
+ tileh = MicroBlockTable[logbpp][microtiled][1] * 8;
+
+ /* See TX_FILTER1_n.MACRO_SWITCH. */
+ if (rv350_mode) {
+ return width >= tilew && height >= tileh;
+ } else {
+ return width > tilew && height > tileh;
+ }
+}
+
+/* Calculate appropriate tiling and pitch for a pixmap and allocate a BO that
+ * can hold it.
+ */
+struct radeon_bo*
+radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
+ int usage_hint, int bitsPerPixel, int *new_pitch,
+ struct radeon_surface *new_surface, uint32_t *new_tiling)
+{
+ RADEONInfoPtr info = RADEONPTR(pScrn);
+ int pitch, base_align;
+ uint32_t size, heighta;
+ int cpp = bitsPerPixel / 8;
+ uint32_t tiling = 0;
+ struct radeon_surface surface;
+ struct radeon_bo *bo;
+
+ if (usage_hint) {
+ if (info->allowColorTiling) {
+ if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
+ tiling |= RADEON_TILING_MACRO;
+ if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO)
+ tiling |= RADEON_TILING_MICRO;
+ }
+ if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH)
+ tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO;
+
+ }
+
+ /* Small pixmaps must not be macrotiled on R300, hw cannot sample them
+ * correctly because samplers automatically switch to macrolinear. */
+ if (info->ChipFamily >= CHIP_FAMILY_R300 &&
+ info->ChipFamily <= CHIP_FAMILY_RS740 &&
+ (tiling & RADEON_TILING_MACRO) &&
+ !RADEONMacroSwitch(width, height, bitsPerPixel, tiling,
+ info->ChipFamily >= CHIP_FAMILY_RV350)) {
+ tiling &= ~RADEON_TILING_MACRO;
+ }
+
+ heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling));
+ pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp;
+ base_align = drmmode_get_base_align(pScrn, cpp, tiling);
+ size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE);
+ memset(&surface, 0, sizeof(struct radeon_surface));
+
+ if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
+ if (width) {
+ surface.npix_x = width;
+ /* need to align height to 8 for old kernel */
+ surface.npix_y = RADEON_ALIGN(height, 8);
+ surface.npix_z = 1;
+ surface.blk_w = 1;
+ surface.blk_h = 1;
+ surface.blk_d = 1;
+ surface.array_size = 1;
+ surface.last_level = 0;
+ surface.bpe = cpp;
+ surface.nsamples = 1;
+ if (height < 64) {
+ /* disable 2d tiling for small surface to work around
+ * the fact that ddx align height to 8 pixel for old
+ * obscure reason i can't remember
+ */
+ tiling &= ~RADEON_TILING_MACRO;
+ }
+ surface.flags = RADEON_SURF_SCANOUT;
+ surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
+ surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
+ if ((tiling & RADEON_TILING_MICRO)) {
+ surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
+ surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+ }
+ if ((tiling & RADEON_TILING_MACRO)) {
+ surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
+ surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+ }
+ if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) {
+ surface.flags |= RADEON_SURF_ZBUFFER;
+ surface.flags |= RADEON_SURF_SBUFFER;
+ }
+ if (radeon_surface_best(info->surf_man, &surface)) {
+ return NULL;
+ }
+ if (radeon_surface_init(info->surf_man, &surface)) {
+ return NULL;
+ }
+ size = surface.bo_size;
+ base_align = surface.bo_alignment;
+ pitch = surface.level[0].pitch_bytes;
+ tiling = 0;
+ switch (surface.level[0].mode) {
+ case RADEON_SURF_MODE_2D:
+ tiling |= RADEON_TILING_MACRO;
+ tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
+ tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
+ tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
+ tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
+ tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT;
+ break;
+ case RADEON_SURF_MODE_1D:
+ tiling |= RADEON_TILING_MICRO;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ bo = radeon_bo_open(info->bufmgr, 0, size, base_align,
+ RADEON_GEM_DOMAIN_VRAM, 0);
+
+ if (bo && tiling && radeon_bo_set_tiling(bo, tiling, pitch) == 0)
+ *new_tiling = tiling;
+
+ *new_surface = surface;
+ *new_pitch = pitch;
+ return bo;
+}
diff --git a/src/radeon_bo_helper.h b/src/radeon_bo_helper.h
new file mode 100644
index 0000000..0f6fffb
--- /dev/null
+++ b/src/radeon_bo_helper.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2012 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 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 COPYRIGHT HOLDER(S) OR AUTHOR(S) 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_BO_HELPER_H
+#define RADEON_BO_HELPER_H 1
+
+extern struct radeon_bo*
+radeon_alloc_pixmap_bo(ScrnInfoPtr pScrn, int width, int height, int depth,
+ int usage_hint, int bitsPerPixel, int *new_pitch,
+ struct radeon_surface *new_surface, uint32_t *new_tiling);
+
+#endif /* RADEON_BO_HELPER_H */
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 99dc453..d80c7e4 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -37,6 +37,7 @@
#include "radeon_reg.h"
#include "r600_reg.h"
#include "radeon_drm.h"
+#include "radeon_bo_helper.h"
#include "radeon_probe.h"
#include "radeon_version.h"
#include "radeon_exa_shared.h"
@@ -70,24 +71,6 @@ static struct {
{ RADEON_ROP3_ONE, RADEON_ROP3_ONE } /* GXset */
};
-/* Compute log base 2 of val. */
-static __inline__ int
-RADEONLog2(int val)
-{
- int bits;
-#if (defined __i386__ || defined __x86_64__) && (defined __GNUC__)
- __asm volatile("bsrl %1, %0"
- : "=r" (bits)
- : "c" (val)
- );
- return bits;
-#else
- for (bits = 0; val != 0; val >>= 1, ++bits)
- ;
- return bits - 1;
-#endif
-}
-
static __inline__ uint32_t F_TO_DW(float val)
{
union {
@@ -292,37 +275,6 @@ void *RADEONEXACreatePixmap(ScreenPtr pScreen, int size, int align)
}
-static const unsigned MicroBlockTable[5][3][2] = {
- /*linear tiled square-tiled */
- {{32, 1}, {8, 4}, {0, 0}}, /* 8 bits per pixel */
- {{16, 1}, {8, 2}, {4, 4}}, /* 16 bits per pixel */
- {{ 8, 1}, {4, 2}, {0, 0}}, /* 32 bits per pixel */
- {{ 4, 1}, {0, 0}, {2, 2}}, /* 64 bits per pixel */
- {{ 2, 1}, {0, 0}, {0, 0}} /* 128 bits per pixel */
-};
-
-/* Return true if macrotiling can be enabled */
-static Bool RADEONMacroSwitch(int width, int height, int bpp,
- uint32_t flags, Bool rv350_mode)
-{
- unsigned tilew, tileh, microtiled, logbpp;
-
- logbpp = RADEONLog2(bpp / 8);
- if (logbpp > 4)
- return 0;
-
- microtiled = !!(flags & RADEON_TILING_MICRO);
- tilew = MicroBlockTable[logbpp][microtiled][0] * 8;
- tileh = MicroBlockTable[logbpp][microtiled][1] * 8;
-
- /* See TX_FILTER1_n.MACRO_SWITCH. */
- if (rv350_mode) {
- return width >= tilew && height >= tileh;
- } else {
- return width > tilew && height > tileh;
- }
-}
-
void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
int depth, int usage_hint, int bitsPerPixel,
int *new_pitch)
@@ -330,11 +282,6 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
RADEONInfoPtr info = RADEONPTR(pScrn);
struct radeon_exa_pixmap_priv *new_priv;
- int pitch, base_align;
- uint32_t size, heighta;
- uint32_t tiling = 0;
- int cpp = bitsPerPixel / 8;
- struct radeon_surface surface;
#ifdef EXA_MIXED_PIXMAPS
if (info->accel_state->exa->flags & EXA_MIXED_PIXMAPS) {
@@ -344,120 +291,25 @@ void *RADEONEXACreatePixmap2(ScreenPtr pScreen, int width, int height,
}
#endif
- if (usage_hint) {
- if (info->allowColorTiling) {
- if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MACRO)
- tiling |= RADEON_TILING_MACRO;
- if (usage_hint & RADEON_CREATE_PIXMAP_TILING_MICRO)
- tiling |= RADEON_TILING_MICRO;
- }
- if (usage_hint & RADEON_CREATE_PIXMAP_DEPTH)
- tiling |= RADEON_TILING_MACRO | RADEON_TILING_MICRO;
-
- }
-
- /* Small pixmaps must not be macrotiled on R300, hw cannot sample them
- * correctly because samplers automatically switch to macrolinear. */
- if (info->ChipFamily >= CHIP_FAMILY_R300 &&
- info->ChipFamily <= CHIP_FAMILY_RS740 &&
- (tiling & RADEON_TILING_MACRO) &&
- !RADEONMacroSwitch(width, height, bitsPerPixel, tiling,
- info->ChipFamily >= CHIP_FAMILY_RV350)) {
- tiling &= ~RADEON_TILING_MACRO;
- }
-
- heighta = RADEON_ALIGN(height, drmmode_get_height_align(pScrn, tiling));
- pitch = RADEON_ALIGN(width, drmmode_get_pitch_align(pScrn, cpp, tiling)) * cpp;
- base_align = drmmode_get_base_align(pScrn, cpp, tiling);
- size = RADEON_ALIGN(heighta * pitch, RADEON_GPU_PAGE_SIZE);
- memset(&surface, 0, sizeof(struct radeon_surface));
-
- if (info->ChipFamily >= CHIP_FAMILY_R600 && info->surf_man) {
- if (width) {
- surface.npix_x = width;
- /* need to align height to 8 for old kernel */
- surface.npix_y = RADEON_ALIGN(height, 8);
- surface.npix_z = 1;
- surface.blk_w = 1;
- surface.blk_h = 1;
- surface.blk_d = 1;
- surface.array_size = 1;
- surface.last_level = 0;
- surface.bpe = cpp;
- surface.nsamples = 1;
- if (height < 64) {
- /* disable 2d tiling for small surface to work around
- * the fact that ddx align height to 8 pixel for old
- * obscure reason i can't remember
- */
- tiling &= ~RADEON_TILING_MACRO;
- }
- surface.flags = RADEON_SURF_SCANOUT;
- surface.flags |= RADEON_SURF_SET(RADEON_SURF_TYPE_2D, TYPE);
- surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR, MODE);
- if ((tiling & RADEON_TILING_MICRO)) {
- surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
- surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
- }
- if ((tiling & RADEON_TILING_MACRO)) {
- surface.flags = RADEON_SURF_CLR(surface.flags, MODE);
- surface.flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
- }
- if (usage_hint & RADEON_CREATE_PIXMAP_SZBUFFER) {
- surface.flags |= RADEON_SURF_ZBUFFER;
- surface.flags |= RADEON_SURF_SBUFFER;
- }
- if (radeon_surface_best(info->surf_man, &surface)) {
- return NULL;
- }
- if (radeon_surface_init(info->surf_man, &surface)) {
- return NULL;
- }
- size = surface.bo_size;
- base_align = surface.bo_alignment;
- pitch = surface.level[0].pitch_bytes;
- tiling = 0;
- switch (surface.level[0].mode) {
- case RADEON_SURF_MODE_2D:
- tiling |= RADEON_TILING_MACRO;
- tiling |= surface.bankw << RADEON_TILING_EG_BANKW_SHIFT;
- tiling |= surface.bankh << RADEON_TILING_EG_BANKH_SHIFT;
- tiling |= surface.mtilea << RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT;
- tiling |= eg_tile_split(surface.tile_split) << RADEON_TILING_EG_TILE_SPLIT_SHIFT;
- tiling |= eg_tile_split(surface.stencil_tile_split) << RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT;
- break;
- case RADEON_SURF_MODE_1D:
- tiling |= RADEON_TILING_MICRO;
- break;
- default:
- break;
- }
- }
- }
-
new_priv = calloc(1, sizeof(struct radeon_exa_pixmap_priv));
if (!new_priv) {
return NULL;
}
- if (size == 0) {
+ if (width == 0 || height == 0) {
return new_priv;
}
- *new_pitch = pitch;
-
- new_priv->bo = radeon_bo_open(info->bufmgr, 0, size, base_align,
- RADEON_GEM_DOMAIN_VRAM, 0);
+ new_priv->bo = radeon_alloc_pixmap_bo(pScrn, width, height, depth,
+ usage_hint, bitsPerPixel, new_pitch,
+ &new_priv->surface,
+ &new_priv->tiling_flags);
if (!new_priv->bo) {
free(new_priv);
ErrorF("Failed to alloc memory\n");
return NULL;
}
- if (tiling && !radeon_bo_set_tiling(new_priv->bo, tiling, *new_pitch))
- new_priv->tiling_flags = tiling;
-
- new_priv->surface = surface;
return new_priv;
}
More information about the xorg-commit
mailing list