summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am2
-rw-r--r--src/ati_pciids_gen.h39
-rw-r--r--src/pcidb/ati_pciids.csv39
-rw-r--r--src/radeon_chipinfo_gen.h39
-rw-r--r--src/radeon_chipset_gen.h39
-rw-r--r--src/radeon_dri2.c4
-rw-r--r--src/radeon_glamor.c88
-rw-r--r--src/radeon_glamor.h5
-rw-r--r--src/radeon_glamor_wrappers.c1870
-rw-r--r--src/radeon_glamor_wrappers.h179
-rw-r--r--src/radeon_kms.c5
-rw-r--r--src/radeon_pci_chipset_gen.h39
-rw-r--r--src/radeon_pci_device_match_gen.h39
-rw-r--r--src/radeon_probe.h3
-rw-r--r--src/radeon_version.h1
15 files changed, 2384 insertions, 7 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index da94927f..3ee292a6 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 b08ad88f..5509120d 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 501a0f61..29ff26b0 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 c64c9212..295a824a 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 31b31ab3..8e887acc 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 12b198c5..e16d5517 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 232332e3..714dde9e 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 40c9092b..f814e469 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 00000000..d0eb383b
--- /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, &region);
+ 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 00000000..9abbd223
--- /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 5d9ccff6..5cc362f9 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 c9f9656f..02c0a7ee 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 a6663e00..f7299140 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 576f7222..07bc0808 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 129046d7..9a6fac17 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