summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Deucher <alexdeucher@gmail.com>2011-01-10 18:16:49 -0500
committerAlex Deucher <alexdeucher@gmail.com>2011-01-10 18:16:49 -0500
commite5d0a400d08da2358fac9c2ad12042f125525736 (patch)
treea869dd4be87331d24076cc46c60ef4dffbb5b9f2
parent0e432dff9e06a183acaeb20db29cbd03ff0f4b82 (diff)
parente27e9b4e50ad42885ad2e25be897cdf29aa59712 (diff)
Merge branch 'kms-pflip' of git+ssh://git.freedesktop.org/git/xorg/driver/xf86-video-ati
-rw-r--r--man/radeon.man17
-rw-r--r--src/drmmode_display.c134
-rw-r--r--src/drmmode_display.h12
-rw-r--r--src/evergreen_exa.c21
-rw-r--r--src/r600_exa.c21
-rw-r--r--src/radeon.h8
-rw-r--r--src/radeon_dri2.c278
-rw-r--r--src/radeon_dri2.h2
-rw-r--r--src/radeon_exa.c11
-rw-r--r--src/radeon_kms.c23
10 files changed, 461 insertions, 66 deletions
diff --git a/man/radeon.man b/man/radeon.man
index 609f7672..285cb397 100644
--- a/man/radeon.man
+++ b/man/radeon.man
@@ -266,7 +266,22 @@ to use VRAM for non-essential pixmaps. This option allows us to override the
266heuristic. The default is 266heuristic. The default is
267.B on 267.B on
268with > 32MB VRAM, off with < 32MB. 268with > 32MB VRAM, off with < 32MB.
269 269.TP
270.BI "Option \*qSwapbuffersWait\*q \*q" boolean \*q
271This option controls the behavior of glXSwapBuffers and glXCopySubBufferMESA
272calls by GL applications. If enabled, the calls will avoid tearing by making
273sure the display scanline is outside of the area to be copied before the copy
274occurs. If disabled, no scanline synchronization is performed, meaning tearing
275will likely occur. Note that when enabled, this option can adversely affect
276the framerate of applications that render frames at less than refresh rate.
277.IP
278The default value is
279.B on.
280.TP
281.BI "Option \*qEnablePageFlip\*q \*q" boolean \*q
282Enable DRI2 page flipping. The default is
283.B on.
284Pageflipping is supported on all radeon hardware.
270.PP 285.PP
271The following driver 286The following driver
272.B Options 287.B Options
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 0a6e338e..9248cb0e 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -29,6 +29,7 @@
29#include "config.h" 29#include "config.h"
30#endif 30#endif
31 31
32#include <errno.h>
32#ifdef XF86DRM_MODE 33#ifdef XF86DRM_MODE
33#include <sys/ioctl.h> 34#include <sys/ioctl.h>
34#include "micmap.h" 35#include "micmap.h"
@@ -266,9 +267,10 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
266 uint32_t tiling_flags = 0; 267 uint32_t tiling_flags = 0;
267 int height; 268 int height;
268 269
269 /* no tiled scanout on r6xx+ yet */
270 if (info->allowColorTiling) { 270 if (info->allowColorTiling) {
271 if (info->ChipFamily < CHIP_FAMILY_R600) 271 if (info->ChipFamily >= CHIP_FAMILY_R600)
272 tiling_flags |= RADEON_TILING_MICRO;
273 else
272 tiling_flags |= RADEON_TILING_MACRO; 274 tiling_flags |= RADEON_TILING_MACRO;
273 } 275 }
274 276
@@ -1167,9 +1169,10 @@ drmmode_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
1167 if (front_bo) 1169 if (front_bo)
1168 radeon_bo_wait(front_bo); 1170 radeon_bo_wait(front_bo);
1169 1171
1170 /* no tiled scanout on r6xx+ yet */
1171 if (info->allowColorTiling) { 1172 if (info->allowColorTiling) {
1172 if (info->ChipFamily < CHIP_FAMILY_R600) 1173 if (info->ChipFamily >= CHIP_FAMILY_R600)
1174 tiling_flags |= RADEON_TILING_MICRO;
1175 else
1173 tiling_flags |= RADEON_TILING_MACRO; 1176 tiling_flags |= RADEON_TILING_MACRO;
1174 } 1177 }
1175 1178
@@ -1278,6 +1281,39 @@ drmmode_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec,
1278} 1281}
1279 1282
1280static void 1283static void
1284drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec,
1285 unsigned int tv_usec, void *event_data)
1286{
1287 drmmode_flipevtcarrier_ptr flipcarrier = event_data;
1288 drmmode_ptr drmmode = flipcarrier->drmmode;
1289
1290 /* Is this the event whose info shall be delivered to higher level? */
1291 if (flipcarrier->dispatch_me) {
1292 /* Yes: Cache msc, ust for later delivery. */
1293 drmmode->fe_frame = frame;
1294 drmmode->fe_tv_sec = tv_sec;
1295 drmmode->fe_tv_usec = tv_usec;
1296 }
1297 free(flipcarrier);
1298
1299 /* Last crtc completed flip? */
1300 drmmode->flip_count--;
1301 if (drmmode->flip_count > 0)
1302 return;
1303
1304 /* Release framebuffer */
1305 drmModeRmFB(drmmode->fd, drmmode->old_fb_id);
1306
1307 if (drmmode->event_data == NULL)
1308 return;
1309
1310 /* Deliver cached msc, ust from reference crtc to flip event handler */
1311 radeon_dri2_flip_event_handler(drmmode->fe_frame, drmmode->fe_tv_sec,
1312 drmmode->fe_tv_usec, drmmode->event_data);
1313}
1314
1315
1316static void
1281drm_wakeup_handler(pointer data, int err, pointer p) 1317drm_wakeup_handler(pointer data, int err, pointer p)
1282{ 1318{
1283 drmmode_ptr drmmode = data; 1319 drmmode_ptr drmmode = data;
@@ -1320,8 +1356,9 @@ Bool drmmode_pre_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int cpp)
1320 drmmode->flip_count = 0; 1356 drmmode->flip_count = 0;
1321 drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION; 1357 drmmode->event_context.version = DRM_EVENT_CONTEXT_VERSION;
1322 drmmode->event_context.vblank_handler = drmmode_vblank_handler; 1358 drmmode->event_context.vblank_handler = drmmode_vblank_handler;
1323 drmmode->event_context.page_flip_handler = NULL; 1359 drmmode->event_context.page_flip_handler = drmmode_flip_handler;
1324 if (!pRADEONEnt->fd_wakeup_registered && info->dri->pKernelDRMVersion->version_minor >= 4) { 1360 if (!pRADEONEnt->fd_wakeup_registered && info->dri->pKernelDRMVersion->version_minor >= 4) {
1361 drmmode->flip_count = 0;
1325 AddGeneralSocket(drmmode->fd); 1362 AddGeneralSocket(drmmode->fd);
1326 RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA, 1363 RegisterBlockAndWakeupHandlers((BlockHandlerProcPtr)NoopDDA,
1327 drm_wakeup_handler, drmmode); 1364 drm_wakeup_handler, drmmode);
@@ -1561,4 +1598,91 @@ void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode)
1561#endif 1598#endif
1562} 1599}
1563 1600
1601Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id)
1602{
1603 RADEONInfoPtr info = RADEONPTR(scrn);
1604 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
1605 drmmode_crtc_private_ptr drmmode_crtc = config->crtc[0]->driver_private;
1606 drmmode_ptr drmmode = drmmode_crtc->drmmode;
1607 unsigned int pitch = scrn->displayWidth * info->CurrentLayout.pixel_bytes;
1608 int i, old_fb_id;
1609 uint32_t tiling_flags = 0;
1610 int height;
1611 drmmode_flipevtcarrier_ptr flipcarrier;
1612
1613 if (info->allowColorTiling) {
1614 if (info->ChipFamily >= CHIP_FAMILY_R600)
1615 tiling_flags |= RADEON_TILING_MICRO;
1616 else
1617 tiling_flags |= RADEON_TILING_MACRO;
1618 }
1619
1620 pitch = RADEON_ALIGN(pitch, drmmode_get_pitch_align(scrn, info->CurrentLayout.pixel_bytes, tiling_flags));
1621 height = RADEON_ALIGN(scrn->virtualY, drmmode_get_height_align(scrn, tiling_flags));
1622
1623 /*
1624 * Create a new handle for the back buffer
1625 */
1626 old_fb_id = drmmode->fb_id;
1627 if (drmModeAddFB(drmmode->fd, scrn->virtualX, height,
1628 scrn->depth, scrn->bitsPerPixel, pitch,
1629 new_front->handle, &drmmode->fb_id))
1630 goto error_out;
1631
1632 /*
1633 * Queue flips on all enabled CRTCs
1634 * Note that if/when we get per-CRTC buffers, we'll have to update this.
1635 * Right now it assumes a single shared fb across all CRTCs, with the
1636 * kernel fixing up the offset of each CRTC as necessary.
1637 *
1638 * Also, flips queued on disabled or incorrectly configured displays
1639 * may never complete; this is a configuration error.
1640 */
1641 drmmode->fe_frame = 0;
1642 drmmode->fe_tv_sec = 0;
1643 drmmode->fe_tv_usec = 0;
1644
1645 for (i = 0; i < config->num_crtc; i++) {
1646 if (!config->crtc[i]->enabled)
1647 continue;
1648
1649 drmmode->event_data = data;
1650 drmmode->flip_count++;
1651 drmmode_crtc = config->crtc[i]->driver_private;
1652
1653 flipcarrier = calloc(1, sizeof(drmmode_flipevtcarrier_rec));
1654 if (!flipcarrier) {
1655 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1656 "flip queue: carrier alloc failed.\n");
1657 goto error_undo;
1658 }
1659
1660 /* Only the reference crtc will finally deliver its page flip
1661 * completion event. All other crtc's events will be discarded.
1662 */
1663 flipcarrier->dispatch_me = (drmmode_crtc->hw_id == ref_crtc_hw_id);
1664 flipcarrier->drmmode = drmmode;
1665
1666 if (drmModePageFlip(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
1667 drmmode->fb_id, DRM_MODE_PAGE_FLIP_EVENT, flipcarrier)) {
1668 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
1669 "flip queue failed: %s\n", strerror(errno));
1670 free(flipcarrier);
1671 goto error_undo;
1672 }
1673 }
1674
1675 drmmode->old_fb_id = old_fb_id;
1676 return TRUE;
1677
1678error_undo:
1679 drmModeRmFB(drmmode->fd, drmmode->fb_id);
1680 drmmode->fb_id = old_fb_id;
1681
1682error_out:
1683 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "Page flip failed: %s\n",
1684 strerror(errno));
1685 return FALSE;
1686}
1687
1564#endif 1688#endif
diff --git a/src/drmmode_display.h b/src/drmmode_display.h
index e6bfd50a..548907bb 100644
--- a/src/drmmode_display.h
+++ b/src/drmmode_display.h
@@ -39,6 +39,7 @@
39typedef struct { 39typedef struct {
40 int fd; 40 int fd;
41 unsigned fb_id; 41 unsigned fb_id;
42 unsigned old_fb_id;
42 drmModeResPtr mode_res; 43 drmModeResPtr mode_res;
43 drmModeFBPtr mode_fb; 44 drmModeFBPtr mode_fb;
44 int cpp; 45 int cpp;
@@ -50,9 +51,18 @@ typedef struct {
50#endif 51#endif
51 drmEventContext event_context; 52 drmEventContext event_context;
52 int flip_count; 53 int flip_count;
54 void *event_data;
55 unsigned int fe_frame;
56 unsigned int fe_tv_sec;
57 unsigned int fe_tv_usec;
53} drmmode_rec, *drmmode_ptr; 58} drmmode_rec, *drmmode_ptr;
54 59
55typedef struct { 60typedef struct {
61 drmmode_ptr drmmode;
62 Bool dispatch_me;
63} drmmode_flipevtcarrier_rec, *drmmode_flipevtcarrier_ptr;
64
65typedef struct {
56 drmmode_ptr drmmode; 66 drmmode_ptr drmmode;
57 drmModeCrtcPtr mode_crtc; 67 drmModeCrtcPtr mode_crtc;
58 int hw_id; 68 int hw_id;
@@ -99,6 +109,8 @@ extern int drmmode_get_height_align(ScrnInfoPtr scrn, uint32_t tiling);
99extern int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling); 109extern int drmmode_get_pitch_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling);
100extern int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling); 110extern int drmmode_get_base_align(ScrnInfoPtr scrn, int bpe, uint32_t tiling);
101 111
112Bool radeon_do_pageflip(ScrnInfoPtr scrn, struct radeon_bo *new_front, void *data, int ref_crtc_hw_id);
113
102#endif 114#endif
103 115
104#endif 116#endif
diff --git a/src/evergreen_exa.c b/src/evergreen_exa.c
index c6ef33d4..0fe00d80 100644
--- a/src/evergreen_exa.c
+++ b/src/evergreen_exa.c
@@ -1647,22 +1647,29 @@ EVERGREENDownloadFromScreen(PixmapPtr pSrc, int x, int y, int w,
1647 Bool flush = FALSE; 1647 Bool flush = FALSE;
1648 Bool r; 1648 Bool r;
1649 struct r600_accel_object src_obj, dst_obj; 1649 struct r600_accel_object src_obj, dst_obj;
1650 uint32_t tiling_flags = 0, pitch = 0;
1650 1651
1651 if (bpp < 8) 1652 if (bpp < 8)
1652 return FALSE; 1653 return FALSE;
1653 1654
1654 driver_priv = exaGetPixmapDriverPrivate(pSrc); 1655 driver_priv = exaGetPixmapDriverPrivate(pSrc);
1655 1656
1657 ret = radeon_bo_get_tiling(driver_priv->bo, &tiling_flags, &pitch);
1658 if (ret)
1659 ErrorF("radeon_bo_get_tiling failed\n");
1660
1656 /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */ 1661 /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */
1657 copy_src = driver_priv->bo; 1662 copy_src = driver_priv->bo;
1658 copy_pitch = pSrc->devKind; 1663 copy_pitch = pSrc->devKind;
1659 if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { 1664 if (!(tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) {
1660 src_domain = radeon_bo_get_src_domain(driver_priv->bo); 1665 if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) {
1661 if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) == 1666 src_domain = radeon_bo_get_src_domain(driver_priv->bo);
1662 (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) 1667 if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) ==
1663 src_domain = 0; 1668 (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM))
1664 else /* A write may be scheduled */ 1669 src_domain = 0;
1665 flush = TRUE; 1670 else /* A write may be scheduled */
1671 flush = TRUE;
1672 }
1666 } 1673 }
1667 1674
1668 if (!src_domain) 1675 if (!src_domain)
diff --git a/src/r600_exa.c b/src/r600_exa.c
index 15db42ac..5dfc770e 100644
--- a/src/r600_exa.c
+++ b/src/r600_exa.c
@@ -1895,22 +1895,29 @@ R600DownloadFromScreenCS(PixmapPtr pSrc, int x, int y, int w,
1895 Bool flush = FALSE; 1895 Bool flush = FALSE;
1896 Bool r; 1896 Bool r;
1897 struct r600_accel_object src_obj, dst_obj; 1897 struct r600_accel_object src_obj, dst_obj;
1898 uint32_t tiling_flags = 0, pitch = 0;
1898 1899
1899 if (bpp < 8) 1900 if (bpp < 8)
1900 return FALSE; 1901 return FALSE;
1901 1902
1902 driver_priv = exaGetPixmapDriverPrivate(pSrc); 1903 driver_priv = exaGetPixmapDriverPrivate(pSrc);
1903 1904
1905 ret = radeon_bo_get_tiling(driver_priv->bo, &tiling_flags, &pitch);
1906 if (ret)
1907 ErrorF("radeon_bo_get_tiling failed\n");
1908
1904 /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */ 1909 /* If we know the BO won't end up in VRAM anyway, don't bother with a scratch */
1905 copy_src = driver_priv->bo; 1910 copy_src = driver_priv->bo;
1906 copy_pitch = pSrc->devKind; 1911 copy_pitch = pSrc->devKind;
1907 if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { 1912 if (!(tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))) {
1908 src_domain = radeon_bo_get_src_domain(driver_priv->bo); 1913 if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) {
1909 if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) == 1914 src_domain = radeon_bo_get_src_domain(driver_priv->bo);
1910 (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) 1915 if ((src_domain & (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM)) ==
1911 src_domain = 0; 1916 (RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM))
1912 else /* A write may be scheduled */ 1917 src_domain = 0;
1913 flush = TRUE; 1918 else /* A write may be scheduled */
1919 flush = TRUE;
1920 }
1914 } 1921 }
1915 1922
1916 if (!src_domain) 1923 if (!src_domain)
diff --git a/src/radeon.h b/src/radeon.h
index 7f55feec..4da9bf76 100644
--- a/src/radeon.h
+++ b/src/radeon.h
@@ -224,7 +224,8 @@ typedef enum {
224 OPTION_FORCE_LOW_POWER, 224 OPTION_FORCE_LOW_POWER,
225 OPTION_DYNAMIC_PM, 225 OPTION_DYNAMIC_PM,
226 OPTION_NEW_PLL, 226 OPTION_NEW_PLL,
227 OPTION_ZAPHOD_HEADS 227 OPTION_ZAPHOD_HEADS,
228 OPTION_SWAPBUFFERS_WAIT
228} RADEONOpts; 229} RADEONOpts;
229 230
230 231
@@ -1079,6 +1080,11 @@ typedef struct {
1079 struct radeon_bo *bicubic_bo; 1080 struct radeon_bo *bicubic_bo;
1080 void *bicubic_memory; 1081 void *bicubic_memory;
1081 int bicubic_offset; 1082 int bicubic_offset;
1083 /* kms pageflipping */
1084 Bool allowPageFlip;
1085
1086 /* Perform vsync'ed SwapBuffers? */
1087 Bool swapBuffersWait;
1082} RADEONInfoRec, *RADEONInfoPtr; 1088} RADEONInfoRec, *RADEONInfoPtr;
1083 1089
1084#define RADEONWaitForFifo(pScrn, entries) \ 1090#define RADEONWaitForFifo(pScrn, entries) \
diff --git a/src/radeon_dri2.c b/src/radeon_dri2.c
index f2ea0bb4..e8e16ff9 100644
--- a/src/radeon_dri2.c
+++ b/src/radeon_dri2.c
@@ -82,6 +82,10 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
82 struct radeon_exa_pixmap_priv *driver_priv; 82 struct radeon_exa_pixmap_priv *driver_priv;
83 int i, r, need_enlarge = 0; 83 int i, r, need_enlarge = 0;
84 int flags = 0; 84 int flags = 0;
85 unsigned front_width;
86
87 pixmap = screen->GetScreenPixmap(screen);
88 front_width = pixmap->drawable.width;
85 89
86 buffers = calloc(count, sizeof *buffers); 90 buffers = calloc(count, sizeof *buffers);
87 if (buffers == NULL) { 91 if (buffers == NULL) {
@@ -162,12 +166,18 @@ radeon_dri2_create_buffers(DrawablePtr drawable,
162 drawable->depth, 166 drawable->depth,
163 flags); 167 flags);
164 168
165 } else 169 } else {
170 unsigned aligned_width = drawable->width;
171
172 if (aligned_width == front_width)
173 aligned_width = pScrn->virtualX;
174
166 pixmap = (*pScreen->CreatePixmap)(pScreen, 175 pixmap = (*pScreen->CreatePixmap)(pScreen,
167 drawable->width, 176 aligned_width,
168 drawable->height, 177 drawable->height,
169 drawable->depth, 178 drawable->depth,
170 flags); 179 flags);
180 }
171 } 181 }
172 182
173 if (attachments[i] == DRI2BufferDepth) { 183 if (attachments[i] == DRI2BufferDepth) {
@@ -206,6 +216,10 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
206 struct radeon_exa_pixmap_priv *driver_priv; 216 struct radeon_exa_pixmap_priv *driver_priv;
207 int r, need_enlarge = 0; 217 int r, need_enlarge = 0;
208 int flags; 218 int flags;
219 unsigned front_width;
220
221 pixmap = pScreen->GetScreenPixmap(pScreen);
222 front_width = pixmap->drawable.width;
209 223
210 buffers = calloc(1, sizeof *buffers); 224 buffers = calloc(1, sizeof *buffers);
211 if (buffers == NULL) { 225 if (buffers == NULL) {
@@ -287,12 +301,18 @@ radeon_dri2_create_buffer(DrawablePtr drawable,
287 (format != 0)?format:drawable->depth, 301 (format != 0)?format:drawable->depth,
288 flags); 302 flags);
289 303
290 } else 304 } else {
305 unsigned aligned_width = drawable->width;
306
307 if (aligned_width == front_width)
308 aligned_width = pScrn->virtualX;
309
291 pixmap = (*pScreen->CreatePixmap)(pScreen, 310 pixmap = (*pScreen->CreatePixmap)(pScreen,
292 drawable->width, 311 aligned_width,
293 drawable->height, 312 drawable->height,
294 (format != 0)?format:drawable->depth, 313 (format != 0)?format:drawable->depth,
295 flags); 314 flags);
315 }
296 } 316 }
297 317
298 if (attachment == DRI2BufferDepth) { 318 if (attachment == DRI2BufferDepth) {
@@ -423,7 +443,9 @@ radeon_dri2_copy_region(DrawablePtr drawable,
423 } 443 }
424 444
425 vsync = info->accel_state->vsync; 445 vsync = info->accel_state->vsync;
426 info->accel_state->vsync = TRUE; 446
447 /* Driver option "SwapbuffersWait" defines if we vsync DRI2 copy-swaps. */
448 info->accel_state->vsync = info->swapBuffersWait;
427 449
428 (*gc->ops->CopyArea)(src_drawable, dst_drawable, gc, 450 (*gc->ops->CopyArea)(src_drawable, dst_drawable, gc,
429 0, 0, drawable->width, drawable->height, 0, 0); 451 0, 0, drawable->width, drawable->height, 0, 0);
@@ -549,12 +571,124 @@ radeon_dri2_unref_buffer(BufferPtr buffer)
549 } 571 }
550} 572}
551 573
574static int radeon_dri2_drawable_crtc(DrawablePtr pDraw)
575{
576 ScreenPtr pScreen = pDraw->pScreen;
577 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
578 xf86CrtcPtr crtc;
579 int crtc_id = -1;
580
581 crtc = radeon_pick_best_crtc(pScrn,
582 pDraw->x,
583 pDraw->x + pDraw->width,
584 pDraw->y,
585 pDraw->y + pDraw->height);
586
587 /* Make sure the CRTC is valid and this is the real front buffer */
588 if (crtc != NULL && !crtc->rotatedData) {
589 crtc_id = drmmode_get_crtc_id(crtc);
590 }
591 return crtc_id;
592}
593
594static Bool
595radeon_dri2_schedule_flip(ScrnInfoPtr scrn, ClientPtr client,
596 DrawablePtr draw, DRI2BufferPtr front,
597 DRI2BufferPtr back, DRI2SwapEventPtr func,
598 void *data, unsigned int target_msc)
599{
600 struct dri2_buffer_priv *back_priv;
601 struct radeon_exa_pixmap_priv *exa_priv;
602 DRI2FrameEventPtr flip_info;
603
604 /* Main crtc for this drawable shall finally deliver pageflip event. */
605 int ref_crtc_hw_id = radeon_dri2_drawable_crtc(draw);
606
607 flip_info = calloc(1, sizeof(DRI2FrameEventRec));
608 if (!flip_info)
609 return FALSE;
610
611 flip_info->drawable_id = draw->id;
612 flip_info->client = client;
613 flip_info->type = DRI2_SWAP;
614 flip_info->event_complete = func;
615 flip_info->event_data = data;
616 flip_info->frame = target_msc;
617
618 xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
619 "%s:%d fevent[%p]\n", __func__, __LINE__, flip_info);
620
621 /* Page flip the full screen buffer */
622 back_priv = back->driverPrivate;
623 exa_priv = exaGetPixmapDriverPrivate(back_priv->pixmap);
624
625 return radeon_do_pageflip(scrn, exa_priv->bo, flip_info, ref_crtc_hw_id);
626}
627
628static Bool
629can_exchange(DRI2BufferPtr front, DRI2BufferPtr back)
630{
631 struct dri2_buffer_priv *front_priv = front->driverPrivate;
632 struct dri2_buffer_priv *back_priv = back->driverPrivate;
633 PixmapPtr front_pixmap = front_priv->pixmap;
634 PixmapPtr back_pixmap = back_priv->pixmap;
635
636 if (front_pixmap->drawable.width != back_pixmap->drawable.width)
637 return FALSE;
638
639 if (front_pixmap->drawable.height != back_pixmap->drawable.height)
640 return FALSE;
641
642 if (front_pixmap->drawable.bitsPerPixel != back_pixmap->drawable.bitsPerPixel)
643 return FALSE;
644
645 if (front_pixmap->devKind != back_pixmap->devKind)
646 return FALSE;
647
648 return TRUE;
649}
650
651static void
652radeon_dri2_exchange_buffers(DrawablePtr draw, DRI2BufferPtr front, DRI2BufferPtr back)
653{
654 struct dri2_buffer_priv *front_priv = front->driverPrivate;
655 struct dri2_buffer_priv *back_priv = back->driverPrivate;
656 struct radeon_exa_pixmap_priv *front_radeon, *back_radeon;
657 ScreenPtr screen;
658 RADEONInfoPtr info;
659 struct radeon_bo *bo;
660 int tmp;
661
662 /* Swap BO names so DRI works */
663 tmp = front->name;
664 front->name = back->name;
665 back->name = tmp;
666
667 /* Swap pixmap bos */
668 front_radeon = exaGetPixmapDriverPrivate(front_priv->pixmap);
669 back_radeon = exaGetPixmapDriverPrivate(back_priv->pixmap);
670 bo = back_radeon->bo;
671 back_radeon->bo = front_radeon->bo;
672 front_radeon->bo = bo;
673
674 /* Do we need to update the Screen? */
675 screen = draw->pScreen;
676 info = RADEONPTR(xf86Screens[screen->myNum]);
677 if (front_radeon->bo == info->front_bo) {
678 radeon_bo_unref(info->front_bo);
679 info->front_bo = back_radeon->bo;
680 radeon_bo_ref(info->front_bo);
681 front_radeon = exaGetPixmapDriverPrivate(screen->GetScreenPixmap(screen));
682 front_radeon->bo = bo;
683 }
684}
685
552void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec, 686void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
553 unsigned int tv_usec, void *event_data) 687 unsigned int tv_usec, void *event_data)
554{ 688{
555 DRI2FrameEventPtr event = event_data; 689 DRI2FrameEventPtr event = event_data;
690 RADEONInfoPtr info;
556 DrawablePtr drawable; 691 DrawablePtr drawable;
557 ClientPtr client;
558 ScreenPtr screen; 692 ScreenPtr screen;
559 ScrnInfoPtr scrn; 693 ScrnInfoPtr scrn;
560 int status; 694 int status;
@@ -563,7 +697,7 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
563 RegionRec region; 697 RegionRec region;
564 698
565 if (!event->valid) 699 if (!event->valid)
566 goto cleanup; 700 goto cleanup;
567 701
568 status = dixLookupDrawable(&drawable, event->drawable_id, serverClient, 702 status = dixLookupDrawable(&drawable, event->drawable_id, serverClient,
569 M_ANY, DixWriteAccess); 703 M_ANY, DixWriteAccess);
@@ -572,25 +706,46 @@ void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
572 706
573 screen = drawable->pScreen; 707 screen = drawable->pScreen;
574 scrn = xf86Screens[screen->myNum]; 708 scrn = xf86Screens[screen->myNum];
575 client = event->client; 709 info = RADEONPTR(scrn);
576 710
577 switch (event->type) { 711 switch (event->type) {
578 case DRI2_FLIP: 712 case DRI2_FLIP:
713 if (info->allowPageFlip &&
714 DRI2CanFlip(drawable) &&
715 can_exchange(event->front, event->back) &&
716 radeon_dri2_schedule_flip(scrn,
717 event->client,
718 drawable,
719 event->front,
720 event->back,
721 event->event_complete,
722 event->event_data,
723 event->frame)) {
724 radeon_dri2_exchange_buffers(drawable, event->front, event->back);
725 break;
726 }
727 /* else fall through to exchange/blit */
579 case DRI2_SWAP: 728 case DRI2_SWAP:
580 box.x1 = 0; 729 if (DRI2CanExchange(drawable) &&
581 box.y1 = 0; 730 can_exchange(event->front, event->back)) {
582 box.x2 = drawable->width; 731 radeon_dri2_exchange_buffers(drawable, event->front, event->back);
583 box.y2 = drawable->height; 732 swap_type = DRI2_EXCHANGE_COMPLETE;
584 REGION_INIT(pScreen, &region, &box, 0); 733 } else {
585 radeon_dri2_copy_region(drawable, &region, event->front, event->back); 734 box.x1 = 0;
586 swap_type = DRI2_BLIT_COMPLETE; 735 box.y1 = 0;
587 736 box.x2 = drawable->width;
588 DRI2SwapComplete(client, drawable, frame, tv_sec, tv_usec, 737 box.y2 = drawable->height;
738 REGION_INIT(pScreen, &region, &box, 0);
739 radeon_dri2_copy_region(drawable, &region, event->front, event->back);
740 swap_type = DRI2_BLIT_COMPLETE;
741 }
742
743 DRI2SwapComplete(event->client, drawable, frame, tv_sec, tv_usec,
589 swap_type, event->event_complete, event->event_data); 744 swap_type, event->event_complete, event->event_data);
590 745
591 break; 746 break;
592 case DRI2_WAITMSC: 747 case DRI2_WAITMSC:
593 DRI2WaitMSCComplete(client, drawable, frame, tv_sec, tv_usec); 748 DRI2WaitMSCComplete(event->client, drawable, frame, tv_sec, tv_usec);
594 break; 749 break;
595 default: 750 default:
596 /* Unknown type */ 751 /* Unknown type */
@@ -607,26 +762,6 @@ cleanup:
607 free(event); 762 free(event);
608} 763}
609 764
610static int radeon_dri2_drawable_crtc(DrawablePtr pDraw)
611{
612 ScreenPtr pScreen = pDraw->pScreen;
613 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
614 xf86CrtcPtr crtc;
615 int crtc_id = -1;
616
617 crtc = radeon_pick_best_crtc(pScrn,
618 pDraw->x,
619 pDraw->x + pDraw->width,
620 pDraw->y,
621 pDraw->y + pDraw->height);
622
623 /* Make sure the CRTC is valid and this is the real front buffer */
624 if (crtc != NULL && !crtc->rotatedData) {
625 crtc_id = drmmode_get_crtc_id(crtc);
626 }
627 return crtc_id;
628}
629
630/* 765/*
631 * Get current frame count and frame count timestamp, based on drawable's 766 * Get current frame count and frame count timestamp, based on drawable's
632 * crtc. 767 * crtc.
@@ -638,7 +773,7 @@ static int radeon_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
638 RADEONInfoPtr info = RADEONPTR(scrn); 773 RADEONInfoPtr info = RADEONPTR(scrn);
639 drmVBlank vbl; 774 drmVBlank vbl;
640 int ret; 775 int ret;
641 int crtc= radeon_dri2_drawable_crtc(draw); 776 int crtc = radeon_dri2_drawable_crtc(draw);
642 777
643 /* Drawable not displayed, make up a value */ 778 /* Drawable not displayed, make up a value */
644 if (crtc == -1) { 779 if (crtc == -1) {
@@ -796,6 +931,59 @@ out_complete:
796 return TRUE; 931 return TRUE;
797} 932}
798 933
934void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
935 unsigned int tv_usec, void *event_data)
936{
937 DRI2FrameEventPtr flip = event_data;
938 DrawablePtr drawable;
939 ScreenPtr screen;
940 ScrnInfoPtr scrn;
941 int status;
942 PixmapPtr pixmap;
943
944 status = dixLookupDrawable(&drawable, flip->drawable_id, serverClient,
945 M_ANY, DixWriteAccess);
946 if (status != Success) {
947 free(flip);
948 return;
949 }
950
951 screen = drawable->pScreen;
952 scrn = xf86Screens[screen->myNum];
953
954 pixmap = screen->GetScreenPixmap(screen);
955 xf86DrvMsgVerb(scrn->scrnIndex, X_INFO, RADEON_LOGLEVEL_DEBUG,
956 "%s:%d fevent[%p] width %d pitch %d (/4 %d)\n",
957 __func__, __LINE__, flip, pixmap->drawable.width, pixmap->devKind, pixmap->devKind/4);
958
959 /* We assume our flips arrive in order, so we don't check the frame */
960 switch (flip->type) {
961 case DRI2_SWAP:
962 /* Check for too small vblank count of pageflip completion, taking wraparound
963 * into account. This usually means some defective kms pageflip completion,
964 * causing wrong (msc, ust) return values and possible visual corruption.
965 */
966 if ((frame < flip->frame) && (flip->frame - frame < 5)) {
967 xf86DrvMsg(scrn->scrnIndex, X_WARNING,
968 "%s: Pageflip completion event has impossible msc %d < target_msc %d\n",
969 __func__, frame, flip->frame);
970 /* All-Zero values signal failure of (msc, ust) timestamping to client. */
971 frame = tv_sec = tv_usec = 0;
972 }
973
974 DRI2SwapComplete(flip->client, drawable, frame, tv_sec, tv_usec,
975 DRI2_FLIP_COMPLETE, flip->event_complete,
976 flip->event_data);
977 break;
978 default:
979 xf86DrvMsg(scrn->scrnIndex, X_WARNING, "%s: unknown vblank event received\n", __func__);
980 /* Unknown type */
981 break;
982 }
983
984 free(flip);
985}
986
799/* 987/*
800 * ScheduleSwap is responsible for requesting a DRM vblank event for the 988 * ScheduleSwap is responsible for requesting a DRM vblank event for the
801 * appropriate frame. 989 * appropriate frame.
@@ -883,6 +1071,15 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
883 } 1071 }
884 1072
885 current_msc = vbl.reply.sequence; 1073 current_msc = vbl.reply.sequence;
1074
1075 /* Flips need to be submitted one frame before */
1076 if (info->allowPageFlip &&
1077 DRI2CanFlip(draw) &&
1078 can_exchange(front, back)) {
1079 swap_type = DRI2_FLIP;
1080 flip = 1;
1081 }
1082
886 swap_info->type = swap_type; 1083 swap_info->type = swap_type;
887 1084
888 /* Correct target_msc by 'flip' if swap_type == DRI2_FLIP. 1085 /* Correct target_msc by 'flip' if swap_type == DRI2_FLIP.
@@ -899,9 +1096,6 @@ static int radeon_dri2_schedule_swap(ClientPtr client, DrawablePtr draw,
899 */ 1096 */
900 if (divisor == 0 || current_msc < *target_msc) { 1097 if (divisor == 0 || current_msc < *target_msc) {
901 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT; 1098 vbl.request.type = DRM_VBLANK_ABSOLUTE | DRM_VBLANK_EVENT;
902 if (crtc > 0)
903 vbl.request.type |= DRM_VBLANK_SECONDARY;
904
905 /* If non-pageflipping, but blitting/exchanging, we need to use 1099 /* If non-pageflipping, but blitting/exchanging, we need to use
906 * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later 1100 * DRM_VBLANK_NEXTONMISS to avoid unreliable timestamping later
907 * on. 1101 * on.
diff --git a/src/radeon_dri2.h b/src/radeon_dri2.h
index 688530f2..79952862 100644
--- a/src/radeon_dri2.h
+++ b/src/radeon_dri2.h
@@ -44,5 +44,7 @@ xf86CrtcPtr radeon_covering_crtc(ScrnInfoPtr pScrn, BoxPtr box,
44 xf86CrtcPtr desired, BoxPtr crtc_box_ret); 44 xf86CrtcPtr desired, BoxPtr crtc_box_ret);
45void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec, 45void radeon_dri2_frame_event_handler(unsigned int frame, unsigned int tv_sec,
46 unsigned int tv_usec, void *event_data); 46 unsigned int tv_usec, void *event_data);
47void radeon_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
48 unsigned int tv_usec, void *event_data);
47 49
48#endif 50#endif
diff --git a/src/radeon_exa.c b/src/radeon_exa.c
index 9c40da79..9df7251e 100644
--- a/src/radeon_exa.c
+++ b/src/radeon_exa.c
@@ -318,6 +318,17 @@ Bool RADEONPrepareAccess_CS(PixmapPtr pPix, int index)
318 if (!driver_priv) 318 if (!driver_priv)
319 return FALSE; 319 return FALSE;
320 320
321 if (info->ChipFamily >= CHIP_FAMILY_R600) {
322 uint32_t tiling_flags = 0, pitch = 0;
323
324 ret = radeon_bo_get_tiling(driver_priv->bo, &tiling_flags, &pitch);
325 if (ret)
326 return FALSE;
327 /* untile in DFS/UTS */
328 if (tiling_flags & (RADEON_TILING_MACRO | RADEON_TILING_MICRO))
329 return FALSE;
330 }
331
321 /* if we have more refs than just the BO then flush */ 332 /* if we have more refs than just the BO then flush */
322 if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) { 333 if (radeon_bo_is_referenced_by_cs(driver_priv->bo, info->cs)) {
323 flush = TRUE; 334 flush = TRUE;
diff --git a/src/radeon_kms.c b/src/radeon_kms.c
index f4c54b30..59f82818 100644
--- a/src/radeon_kms.c
+++ b/src/radeon_kms.c
@@ -70,6 +70,8 @@ const OptionInfoRec RADEONOptions_KMS[] = {
70 { OPTION_EXA_VSYNC, "EXAVSync", OPTV_BOOLEAN, {0}, FALSE }, 70 { OPTION_EXA_VSYNC, "EXAVSync", OPTV_BOOLEAN, {0}, FALSE },
71 { OPTION_EXA_PIXMAPS, "EXAPixmaps", OPTV_BOOLEAN, {0}, FALSE }, 71 { OPTION_EXA_PIXMAPS, "EXAPixmaps", OPTV_BOOLEAN, {0}, FALSE },
72 { OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE }, 72 { OPTION_ZAPHOD_HEADS, "ZaphodHeads", OPTV_STRING, {0}, FALSE },
73 { OPTION_PAGE_FLIP, "EnablePageFlip", OPTV_BOOLEAN, {0}, FALSE },
74 { OPTION_SWAPBUFFERS_WAIT,"SwapbuffersWait", OPTV_BOOLEAN, {0}, FALSE },
73 { -1, NULL, OPTV_NONE, {0}, FALSE } 75 { -1, NULL, OPTV_NONE, {0}, FALSE }
74}; 76};
75 77
@@ -620,6 +622,18 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
620 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 622 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
621 "KMS Color Tiling: %sabled\n", info->allowColorTiling ? "en" : "dis"); 623 "KMS Color Tiling: %sabled\n", info->allowColorTiling ? "en" : "dis");
622 624
625 if (info->dri->pKernelDRMVersion->version_minor >= 8) {
626 info->allowPageFlip = xf86ReturnOptValBool(info->Options,
627 OPTION_PAGE_FLIP, TRUE);
628 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
629 "KMS Pageflipping: %sabled\n", info->allowPageFlip ? "en" : "dis");
630 }
631
632 info->swapBuffersWait = xf86ReturnOptValBool(info->Options,
633 OPTION_SWAPBUFFERS_WAIT, TRUE);
634 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
635 "SwapBuffers wait for vsync: %sabled\n", info->swapBuffersWait ? "en" : "dis");
636
623 if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) == FALSE) { 637 if (drmmode_pre_init(pScrn, &info->drmmode, pScrn->bitsPerPixel / 8) == FALSE) {
624 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n"); 638 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Kernel modesetting setup failed\n");
625 goto fail; 639 goto fail;
@@ -678,7 +692,9 @@ Bool RADEONPreInit_KMS(ScrnInfoPtr pScrn, int flags)
678 692
679 /* no tiled scanout on r6xx+ yet */ 693 /* no tiled scanout on r6xx+ yet */
680 if (info->allowColorTiling) { 694 if (info->allowColorTiling) {
681 if (info->ChipFamily < CHIP_FAMILY_R600) 695 if (info->ChipFamily >= CHIP_FAMILY_R600)
696 tiling |= RADEON_TILING_MICRO;
697 else
682 tiling |= RADEON_TILING_MACRO; 698 tiling |= RADEON_TILING_MACRO;
683 } 699 }
684 cpp = pScrn->bitsPerPixel / 8; 700 cpp = pScrn->bitsPerPixel / 8;
@@ -1115,9 +1131,10 @@ static Bool radeon_setup_kernel_mem(ScreenPtr pScreen)
1115 return FALSE; 1131 return FALSE;
1116 } 1132 }
1117 1133
1118 /* no tiled scanout on r6xx+ yet */
1119 if (info->allowColorTiling) { 1134 if (info->allowColorTiling) {
1120 if (info->ChipFamily < CHIP_FAMILY_R600) 1135 if (info->ChipFamily >= CHIP_FAMILY_R600)
1136 tiling_flags |= RADEON_TILING_MICRO;
1137 else
1121 tiling_flags |= RADEON_TILING_MACRO; 1138 tiling_flags |= RADEON_TILING_MACRO;
1122 } 1139 }
1123 pitch = RADEON_ALIGN(pScrn->displayWidth, drmmode_get_pitch_align(pScrn, cpp, tiling_flags)) * cpp; 1140 pitch = RADEON_ALIGN(pScrn->displayWidth, drmmode_get_pitch_align(pScrn, cpp, tiling_flags)) * cpp;