summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2013-01-23 11:51:31 -0800
committerKeith Packard <keithp@keithp.com>2013-01-23 11:51:31 -0800
commit8e52b3336fe5268d9cd34875b7a90a72dc21e9c8 (patch)
tree42e48b146b32c7ed0a57148e97f2a3e243b00d6f
parent63b7e9bb263905c780d5e689d829ffb0bc6e28c9 (diff)
Add SwapPages support for SwapBuffersswap-pages
This uses the new kernel ioctl to swap pages between objects rather than copying pixels Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--src/intel_dri.c108
1 files changed, 94 insertions, 14 deletions
diff --git a/src/intel_dri.c b/src/intel_dri.c
index d027a643..30c73630 100644
--- a/src/intel_dri.c
+++ b/src/intel_dri.c
@@ -967,12 +967,99 @@ can_exchange(DrawablePtr drawable, DRI2BufferPtr front, DRI2BufferPtr back)
return TRUE;
}
+/* Only a few hacks remaining */
+
+static Bool
+I830DRI2SwapDrawable(DrawablePtr drawable, DRI2BufferPtr front, DRI2BufferPtr back)
+{
+ int ret;
+ DRI2BufferPtr dst_buffer = front;
+ DRI2BufferPtr src_buffer = back;
+ ScreenPtr screen = drawable->pScreen;
+ ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+ intel_screen_private *intel = intel_get_screen_private(scrn);
+
+ I830DRI2BufferPrivatePtr dst_priv = dst_buffer->driverPrivate;
+ I830DRI2BufferPrivatePtr src_priv = src_buffer->driverPrivate;
+ DrawablePtr src = (src_buffer->attachment == DRI2BufferFrontLeft)
+ ? drawable : &src_priv->pixmap->drawable;
+ DrawablePtr dst = (dst_buffer->attachment == DRI2BufferFrontLeft)
+ ? drawable : &dst_priv->pixmap->drawable;
+
+ int src_off_x, src_off_y;
+ PixmapPtr src_pixmap = uxa_get_offscreen_pixmap(src, &src_off_x, &src_off_y);
+ int dst_off_x, dst_off_y;
+ PixmapPtr dst_pixmap = uxa_get_offscreen_pixmap(dst, &dst_off_x, &dst_off_y);
+ dri_bo *src_bo, *dst_bo;
+ struct intel_pixmap *src_intel_pixmap, *dst_intel_pixmap;
+ int width = drawable->width;
+ int height = drawable->height;
+ int bpp = 4; /* XXX assume 32bpp */
+
+ int page_width = width * bpp / 512; /* XXX assumes X tiled */
+ int page_height = height / 8; /* XXX assumes X tiled */
+ int page_start_src, page_start_dst;
+ int page_stride_src, page_stride_dst;
+
+ if (!src_pixmap)
+ return FALSE;
+ if (!dst_pixmap)
+ return FALSE;
+
+ src_intel_pixmap = intel_get_pixmap_private(src_pixmap);
+ dst_intel_pixmap = intel_get_pixmap_private(dst_pixmap);
+ if (src_intel_pixmap->tiling != dst_intel_pixmap->tiling)
+ return FALSE;
+
+ page_stride_src = intel_pixmap_pitch(src_pixmap) / 512;
+ page_stride_dst = intel_pixmap_pitch(dst_pixmap) / 512;
+
+ page_start_src = ((src->y + src_off_y) / 8) * page_stride_src + (src->x + src_off_x) * bpp / 512;
+ page_start_dst = ((dst->y + dst_off_y) / 8) * page_stride_dst + (dst->x + dst_off_x) * bpp / 512;
+
+ src_bo = src_intel_pixmap->bo;
+ dst_bo = dst_intel_pixmap->bo;
+
+ ret = drm_intel_gem_swap_pages(src_bo, page_start_src, page_stride_src,
+ dst_bo, page_start_dst, page_stride_dst,
+ page_width, page_height);
+
+ if (!ret)
+ return TRUE;
+
+ return FALSE;
+}
+
+
+int I830DRI2SwapImmediate(DrawablePtr drawable,
+ DRI2BufferPtr front,
+ DRI2BufferPtr back)
+{
+ if (I830DRI2SwapDrawable(drawable, front, back))
+ return DRI2_BLIT_COMPLETE;
+ else {
+ BoxRec box;
+ RegionRec region;
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = drawable->width;
+ box.y2 = drawable->height;
+ REGION_INIT(pScreen, &region, &box, 0);
+
+ I830DRI2CopyRegion(drawable,
+ &region, front, back);
+ return DRI2_BLIT_COMPLETE;
+ }
+}
+
void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
unsigned int tv_usec, DRI2FrameEventPtr swap_info)
{
intel_screen_private *intel = swap_info->intel;
DrawablePtr drawable;
int status;
+ int type;
if (!swap_info->drawable_id)
status = BadDrawable;
@@ -993,24 +1080,13 @@ void I830DRI2FrameEventHandler(unsigned int frame, unsigned int tv_sec,
return;
/* else fall through to exchange/blit */
- case DRI2_SWAP: {
- BoxRec box;
- RegionRec region;
-
- box.x1 = 0;
- box.y1 = 0;
- box.x2 = drawable->width;
- box.y2 = drawable->height;
- REGION_INIT(pScreen, &region, &box, 0);
-
- I830DRI2CopyRegion(drawable,
- &region, swap_info->front, swap_info->back);
+ case DRI2_SWAP:
+ type = I830DRI2SwapImmediate(drawable, swap_info->front, swap_info->back);
DRI2SwapComplete(swap_info->client, drawable, frame, tv_sec, tv_usec,
- DRI2_BLIT_COMPLETE,
+ type,
swap_info->client ? swap_info->event_complete : NULL,
swap_info->event_data);
break;
- }
case DRI2_WAITMSC:
if (swap_info->client)
DRI2WaitMSCComplete(swap_info->client, drawable,
@@ -1592,6 +1668,10 @@ Bool I830DRI2ScreenInit(ScreenPtr screen)
info.driverNames = driverNames;
driverNames[0] = info.driverName;
#endif
+#if DRI2INFOREC_VERSION >= 10
+ info.version = 10;
+ info.SwapImmediate = I830DRI2SwapImmediate;
+#endif
return DRI2ScreenInit(screen, &info);
}