diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2014-06-20 09:29:08 +1000 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2014-06-20 14:28:39 +1000 |
commit | 97feb3b2104287eb385ffba8329f304e2808d808 (patch) | |
tree | a3816bcab93be104254af66af383cc6f756c7427 | |
parent | 60b876eab3708f1c277027addb5514974452644c (diff) |
dri2: move page flip handling out of drmmode
Nothing to see here... This is to (hopefully) avoid busting DRI2 while
implementing Present support.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | src/drmmode_display.c | 132 | ||||
-rw-r--r-- | src/nouveau_dri2.c | 137 | ||||
-rw-r--r-- | src/nv_proto.h | 5 |
3 files changed, 138 insertions, 136 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index cae7355..a46aad5 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -87,21 +87,6 @@ typedef struct { drmmode_prop_ptr props; } drmmode_output_private_rec, *drmmode_output_private_ptr; -typedef struct { - int fd; - unsigned old_fb_id; - int flip_count; - void *event_data; - unsigned int fe_frame; - unsigned int fe_tv_sec; - unsigned int fe_tv_usec; -} drmmode_flipdata_rec, *drmmode_flipdata_ptr; - -typedef struct { - drmmode_flipdata_ptr flipdata; - Bool dispatch_me; -} drmmode_flipevtcarrier_rec, *drmmode_flipevtcarrier_ptr; - static void drmmode_output_dpms(xf86OutputPtr output, int mode); static drmmode_ptr @@ -1391,86 +1376,6 @@ drmmode_cursor_init(ScreenPtr pScreen) return xf86_cursors_init(pScreen, size, size, flags); } -Bool -drmmode_page_flip(DrawablePtr draw, PixmapPtr back, void *priv, - unsigned int ref_crtc_hw_id) -{ - ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); - xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); - NVPtr pNv = NVPTR(scrn); - uint32_t next_fb; - int emitted = 0; - int ret, i; - drmmode_flipdata_ptr flipdata; - drmmode_flipevtcarrier_ptr flipcarrier; - - ret = drmModeAddFB(pNv->dev->fd, scrn->virtualX, scrn->virtualY, - scrn->depth, scrn->bitsPerPixel, - scrn->displayWidth * scrn->bitsPerPixel / 8, - nouveau_pixmap(back)->bo->handle, &next_fb); - if (ret) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "add fb failed: %s\n", strerror(errno)); - return FALSE; - } - - flipdata = calloc(1, sizeof(drmmode_flipdata_rec)); - if (!flipdata) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "flip queue: data alloc failed.\n"); - goto error_undo; - } - - flipdata->event_data = priv; - flipdata->fd = pNv->dev->fd; - - for (i = 0; i < config->num_crtc; i++) { - int head = drmmode_head(config->crtc[i]); - - if (!config->crtc[i]->enabled) - continue; - - flipdata->flip_count++; - - flipcarrier = calloc(1, sizeof(drmmode_flipevtcarrier_rec)); - if (!flipcarrier) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "flip queue: carrier alloc failed.\n"); - if (emitted == 0) - free(flipdata); - goto error_undo; - } - - /* Only the reference crtc will finally deliver its page flip - * completion event. All other crtc's events will be discarded. - */ - flipcarrier->dispatch_me = ((1 << i) == ref_crtc_hw_id); - flipcarrier->flipdata = flipdata; - - ret = drmModePageFlip(pNv->dev->fd, head, next_fb, - DRM_MODE_PAGE_FLIP_EVENT, flipcarrier); - if (ret) { - xf86DrvMsg(scrn->scrnIndex, X_WARNING, - "flip queue failed: %s\n", strerror(errno)); - - free(flipcarrier); - if (emitted == 0) - free(flipdata); - goto error_undo; - } - - emitted++; - } - - /* Will release old fb after all crtc's completed flip. */ - drmmode_swap(scrn, next_fb, &flipdata->old_fb_id); - return TRUE; - -error_undo: - drmModeRmFB(pNv->dev->fd, next_fb); - return FALSE; -} - #ifdef HAVE_LIBUDEV static void drmmode_handle_uevents(ScrnInfoPtr scrn) @@ -1535,41 +1440,6 @@ drmmode_uevent_fini(ScrnInfoPtr scrn) } static void -drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data) -{ - drmmode_flipevtcarrier_ptr flipcarrier = event_data; - drmmode_flipdata_ptr flipdata = flipcarrier->flipdata; - - /* Is this the event whose info shall be delivered to higher level? */ - if (flipcarrier->dispatch_me) { - /* Yes: Cache msc, ust for later delivery. */ - flipdata->fe_frame = frame; - flipdata->fe_tv_sec = tv_sec; - flipdata->fe_tv_usec = tv_usec; - } - free(flipcarrier); - - /* Last crtc completed flip? */ - flipdata->flip_count--; - if (flipdata->flip_count > 0) - return; - - /* Release framebuffer */ - drmModeRmFB(flipdata->fd, flipdata->old_fb_id); - - if (flipdata->event_data == NULL) { - free(flipdata); - return; - } - - /* Deliver cached msc, ust from reference crtc to flip event handler */ - nouveau_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec, - flipdata->fe_tv_usec, flipdata->event_data); - free(flipdata); -} - -static void drmmode_wakeup_handler(pointer data, int err, pointer p) { ScrnInfoPtr scrn = data; @@ -1601,7 +1471,7 @@ drmmode_screen_init(ScreenPtr pScreen) drmmode->event_context.vblank_handler = nouveau_dri2_vblank_handler; /* Plug in a pageflip completion event handler */ - drmmode->event_context.page_flip_handler = drmmode_flip_handler; + drmmode->event_context.page_flip_handler = nouveau_dri2_flip_handler; AddGeneralSocket(drmmode->fd); diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c index b4294b9..8a0cddd 100644 --- a/src/nouveau_dri2.c +++ b/src/nouveau_dri2.c @@ -11,6 +11,8 @@ #error "This driver requires a DRI2-enabled X server" #endif +#include "xf86drmMode.h" + struct nouveau_dri2_buffer { DRI2BufferRec base; PixmapPtr ppix; @@ -321,6 +323,21 @@ static Bool violate_oml(DrawablePtr draw) return (DRI2INFOREC_VERSION < 6) && (pNv->swap_limit > 1); } +typedef struct { + int fd; + unsigned old_fb_id; + int flip_count; + void *event_data; + unsigned int fe_frame; + unsigned int fe_tv_sec; + unsigned int fe_tv_usec; +} dri2_flipdata_rec, *dri2_flipdata_ptr; + +typedef struct { + dri2_flipdata_ptr flipdata; + Bool dispatch_me; +} dri2_flipevtcarrier_rec, *dri2_flipevtcarrier_ptr; + void nouveau_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, void *event_data) @@ -376,6 +393,121 @@ nouveau_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec, free(flip); } +void +nouveau_dri2_flip_handler(int fd, unsigned int frame, unsigned int tv_sec, + unsigned int tv_usec, void *event_data) +{ + dri2_flipevtcarrier_ptr flipcarrier = event_data; + dri2_flipdata_ptr flipdata = flipcarrier->flipdata; + + /* Is this the event whose info shall be delivered to higher level? */ + if (flipcarrier->dispatch_me) { + /* Yes: Cache msc, ust for later delivery. */ + flipdata->fe_frame = frame; + flipdata->fe_tv_sec = tv_sec; + flipdata->fe_tv_usec = tv_usec; + } + free(flipcarrier); + + /* Last crtc completed flip? */ + flipdata->flip_count--; + if (flipdata->flip_count > 0) + return; + + /* Release framebuffer */ + drmModeRmFB(flipdata->fd, flipdata->old_fb_id); + + if (flipdata->event_data == NULL) { + free(flipdata); + return; + } + + /* Deliver cached msc, ust from reference crtc to flip event handler */ + nouveau_dri2_flip_event_handler(flipdata->fe_frame, flipdata->fe_tv_sec, + flipdata->fe_tv_usec, flipdata->event_data); + free(flipdata); +} + +static Bool +dri2_page_flip(DrawablePtr draw, PixmapPtr back, void *priv, + unsigned int ref_crtc_hw_id) +{ + ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen); + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn); + NVPtr pNv = NVPTR(scrn); + uint32_t next_fb; + int emitted = 0; + int ret, i; + dri2_flipdata_ptr flipdata; + dri2_flipevtcarrier_ptr flipcarrier; + + ret = drmModeAddFB(pNv->dev->fd, scrn->virtualX, scrn->virtualY, + scrn->depth, scrn->bitsPerPixel, + scrn->displayWidth * scrn->bitsPerPixel / 8, + nouveau_pixmap(back)->bo->handle, &next_fb); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "add fb failed: %s\n", strerror(errno)); + return FALSE; + } + + flipdata = calloc(1, sizeof(dri2_flipdata_rec)); + if (!flipdata) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "flip queue: data alloc failed.\n"); + goto error_undo; + } + + flipdata->event_data = priv; + flipdata->fd = pNv->dev->fd; + + for (i = 0; i < config->num_crtc; i++) { + int head = drmmode_head(config->crtc[i]); + + if (!config->crtc[i]->enabled) + continue; + + flipdata->flip_count++; + + flipcarrier = calloc(1, sizeof(dri2_flipevtcarrier_rec)); + if (!flipcarrier) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "flip queue: carrier alloc failed.\n"); + if (emitted == 0) + free(flipdata); + goto error_undo; + } + + /* Only the reference crtc will finally deliver its page flip + * completion event. All other crtc's events will be discarded. + */ + flipcarrier->dispatch_me = ((1 << i) == ref_crtc_hw_id); + flipcarrier->flipdata = flipdata; + + ret = drmModePageFlip(pNv->dev->fd, head, next_fb, + DRM_MODE_PAGE_FLIP_EVENT, flipcarrier); + if (ret) { + xf86DrvMsg(scrn->scrnIndex, X_WARNING, + "flip queue failed: %s\n", strerror(errno)); + + free(flipcarrier); + if (emitted == 0) + free(flipdata); + goto error_undo; + } + + emitted++; + } + + /* Will release old fb after all crtc's completed flip. */ + drmmode_swap(scrn, next_fb, &flipdata->old_fb_id); + return TRUE; + +error_undo: + drmModeRmFB(pNv->dev->fd, next_fb); + return FALSE; +} + static void nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, @@ -517,9 +649,8 @@ nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame, if (nouveau_exa_pixmap_is_onscreen(dst_pix)) { type = DRI2_FLIP_COMPLETE; - ret = drmmode_page_flip(draw, src_pix, - violate_oml(draw) ? NULL : s, - ref_crtc_hw_id); + ret = dri2_page_flip(draw, src_pix, violate_oml(draw) ? + NULL : s, ref_crtc_hw_id); if (!ret) goto out; } diff --git a/src/nv_proto.h b/src/nv_proto.h index c2c66c7..134fba4 100644 --- a/src/nv_proto.h +++ b/src/nv_proto.h @@ -30,8 +30,9 @@ Bool nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int height, void nouveau_dri2_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, void *event_data); -void nouveau_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec, - unsigned int tv_usec, void *event_data); +void nouveau_dri2_flip_handler(int fd, unsigned int frame, + unsigned int tv_sec, unsigned int tv_usec, + void *event_data); Bool nouveau_dri2_init(ScreenPtr pScreen); void nouveau_dri2_fini(ScreenPtr pScreen); |