diff options
author | Keith Packard <keithp@keithp.com> | 2013-01-23 11:51:31 -0800 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2013-01-23 11:51:31 -0800 |
commit | 8e52b3336fe5268d9cd34875b7a90a72dc21e9c8 (patch) | |
tree | 42e48b146b32c7ed0a57148e97f2a3e243b00d6f | |
parent | 63b7e9bb263905c780d5e689d829ffb0bc6e28c9 (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.c | 108 |
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, ®ion, &box, 0); + + I830DRI2CopyRegion(drawable, + ®ion, 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, ®ion, &box, 0); - - I830DRI2CopyRegion(drawable, - ®ion, 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); } |