summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2013-11-21 09:34:00 +1000
committerBen Skeggs <bskeggs@redhat.com>2013-11-22 14:45:55 +1000
commit0c8529ce05e5f6bb812a04754ca139c691dd6305 (patch)
tree485bef58f4f651e22114f5102793a147e70dcb13
parentc08c3fd534700ec9aa0f6b8c854d0c932f503dba (diff)
downloadxorg-driver-xf86-video-nouveau-0c8529ce05e5f6bb812a04754ca139c691dd6305.tar.gz
dri2: pull in flip handling bits from drmmode_display locally
To avoid busting DRI2 while trying some different things for DRI3. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--src/drmmode_display.c135
-rw-r--r--src/nouveau_dri2.c379
-rw-r--r--src/nv_proto.h10
3 files changed, 261 insertions, 263 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 3e8ccec..df3e43b 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -85,21 +85,6 @@ typedef struct {
drmmode_prop_ptr props;
} drmmode_output_private_rec, *drmmode_output_private_ptr;
-typedef struct {
- drmmode_ptr drmmode;
- 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
@@ -1377,90 +1362,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);
- drmmode_crtc_private_ptr crtc = config->crtc[0]->driver_private;
- drmmode_ptr mode = crtc->drmmode;
- int ret, i, old_fb_id;
- int emitted = 0;
- drmmode_flipdata_ptr flipdata;
- drmmode_flipevtcarrier_ptr flipcarrier;
-
- old_fb_id = mode->fb_id;
- ret = drmModeAddFB(mode->fd, scrn->virtualX, scrn->virtualY,
- scrn->depth, scrn->bitsPerPixel,
- scrn->displayWidth * scrn->bitsPerPixel / 8,
- nouveau_pixmap_bo(back)->handle, &mode->fb_id);
- 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->drmmode = mode;
-
- for (i = 0; i < config->num_crtc; i++) {
- crtc = config->crtc[i]->driver_private;
-
- 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(mode->fd, crtc->mode_crtc->crtc_id,
- mode->fb_id, 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. */
- flipdata->old_fb_id = old_fb_id;
-
- return TRUE;
-
-error_undo:
- drmModeRmFB(mode->fd, mode->fb_id);
- mode->fb_id = old_fb_id;
- return FALSE;
-}
-
#ifdef HAVE_LIBUDEV
static void
drmmode_handle_uevents(ScrnInfoPtr scrn)
@@ -1525,42 +1426,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;
- drmmode_ptr drmmode = flipdata->drmmode;
-
- /* 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(drmmode->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;
diff --git a/src/nouveau_dri2.c b/src/nouveau_dri2.c
index 3785956..3e6defb 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;
@@ -295,6 +297,262 @@ can_sync_to_vblank(DrawablePtr draw)
draw->width, draw->height);
}
+#if DRI2INFOREC_VERSION >= 6
+static Bool
+nouveau_dri2_swap_limit_validate(DrawablePtr draw, int swap_limit)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
+ NVPtr pNv = NVPTR(scrn);
+
+ if ((swap_limit < 1 ) || (swap_limit > pNv->max_swap_limit))
+ return FALSE;
+
+ return TRUE;
+}
+#endif
+
+/* Shall we intentionally violate the OML_sync_control spec to
+ * get some sort of triple-buffering behaviour on a pre 1.12.0
+ * x-server?
+ */
+static Bool violate_oml(DrawablePtr draw)
+{
+ ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
+ NVPtr pNv = NVPTR(scrn);
+
+ 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;
+} drmmode_flipdata_rec, *drmmode_flipdata_ptr;
+
+typedef struct {
+ drmmode_flipdata_ptr flipdata;
+ Bool dispatch_me;
+} drmmode_flipevtcarrier_rec, *drmmode_flipevtcarrier_ptr;
+
+static void
+nouveau_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
+ unsigned int tv_usec, void *event_data)
+{
+ struct nouveau_dri2_vblank_state *flip = event_data;
+ DrawablePtr draw;
+ ScreenPtr screen;
+ ScrnInfoPtr scrn;
+ int status;
+
+ status = dixLookupDrawable(&draw, flip->draw, serverClient,
+ M_ANY, DixWriteAccess);
+ if (status != Success) {
+ free(flip);
+ return;
+ }
+
+ screen = draw->pScreen;
+ scrn = xf86ScreenToScrn(screen);
+
+ /* We assume our flips arrive in order, so we don't check the frame */
+ switch (flip->action) {
+ case SWAP:
+ /* Check for too small vblank count of pageflip completion,
+ * taking wraparound into account. This usually means some
+ * defective kms pageflip completion, causing wrong (msc, ust)
+ * return values and possible visual corruption.
+ * Skip test for frame == 0, as this is a valid constant value
+ * reported by all Linux kernels at least up to Linux 3.0.
+ */
+ if ((frame != 0) &&
+ (frame < flip->frame) && (flip->frame - frame < 5)) {
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "%s: Pageflip has impossible msc %d < target_msc %d\n",
+ __func__, frame, flip->frame);
+ /* All-Zero values signal failure of (msc, ust)
+ * timestamping to client.
+ */
+ frame = tv_sec = tv_usec = 0;
+ }
+
+ DRI2SwapComplete(flip->client, draw, frame, tv_sec, tv_usec,
+ DRI2_FLIP_COMPLETE, flip->func,
+ flip->data);
+ break;
+ default:
+ xf86DrvMsg(scrn->scrnIndex, X_WARNING,
+ "%s: unknown vblank event received\n", __func__);
+ /* Unknown type */
+ break;
+ }
+
+ free(flip);
+}
+
+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 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_bo(back)->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;
+}
+
+static void
+nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame,
+ unsigned int tv_sec, unsigned int tv_usec,
+ struct nouveau_dri2_vblank_state *s);
+
+void
+nouveau_dri2_vblank_handler(int fd, unsigned int frame,
+ unsigned int tv_sec, unsigned int tv_usec,
+ void *event_data)
+{
+ struct nouveau_dri2_vblank_state *s = event_data;
+ DrawablePtr draw;
+ int ret;
+
+ ret = dixLookupDrawable(&draw, s->draw, serverClient,
+ M_ANY, DixWriteAccess);
+ if (ret) {
+ free(s);
+ return;
+ }
+
+ switch (s->action) {
+ case SWAP:
+ nouveau_dri2_finish_swap(draw, frame, tv_sec, tv_usec, s);
+#if DRI2INFOREC_VERSION >= 6
+ /* Restore real swap limit on drawable, now that it is safe. */
+ ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
+ DRI2SwapLimit(draw, NVPTR(scrn)->swap_limit);
+#endif
+
+ break;
+
+ case WAIT:
+ DRI2WaitMSCComplete(s->client, draw, frame, tv_sec, tv_usec);
+ free(s);
+ break;
+
+ case BLIT:
+ DRI2SwapComplete(s->client, draw, frame, tv_sec, tv_usec,
+ DRI2_BLIT_COMPLETE, s->func, s->data);
+ free(s);
+ break;
+ }
+}
+
static int
nouveau_wait_vblank(DrawablePtr draw, int type, CARD64 msc,
CARD64 *pmsc, CARD64 *pust, void *data)
@@ -325,32 +583,6 @@ nouveau_wait_vblank(DrawablePtr draw, int type, CARD64 msc,
return 0;
}
-#if DRI2INFOREC_VERSION >= 6
-static Bool
-nouveau_dri2_swap_limit_validate(DrawablePtr draw, int swap_limit)
-{
- ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
- NVPtr pNv = NVPTR(scrn);
-
- if ((swap_limit < 1 ) || (swap_limit > pNv->max_swap_limit))
- return FALSE;
-
- return TRUE;
-}
-#endif
-
-/* Shall we intentionally violate the OML_sync_control spec to
- * get some sort of triple-buffering behaviour on a pre 1.12.0
- * x-server?
- */
-static Bool violate_oml(DrawablePtr draw)
-{
- ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
- NVPtr pNv = NVPTR(scrn);
-
- return (DRI2INFOREC_VERSION < 6) && (pNv->swap_limit > 1);
-}
-
static void
nouveau_dri2_finish_swap(DrawablePtr draw, unsigned int frame,
unsigned int tv_sec, unsigned int tv_usec,
@@ -671,101 +903,6 @@ nouveau_dri2_get_msc(DrawablePtr draw, CARD64 *ust, CARD64 *msc)
return TRUE;
}
-void
-nouveau_dri2_vblank_handler(int fd, unsigned int frame,
- unsigned int tv_sec, unsigned int tv_usec,
- void *event_data)
-{
- struct nouveau_dri2_vblank_state *s = event_data;
- DrawablePtr draw;
- int ret;
-
- ret = dixLookupDrawable(&draw, s->draw, serverClient,
- M_ANY, DixWriteAccess);
- if (ret) {
- free(s);
- return;
- }
-
- switch (s->action) {
- case SWAP:
- nouveau_dri2_finish_swap(draw, frame, tv_sec, tv_usec, s);
-#if DRI2INFOREC_VERSION >= 6
- /* Restore real swap limit on drawable, now that it is safe. */
- ScrnInfoPtr scrn = xf86ScreenToScrn(draw->pScreen);
- DRI2SwapLimit(draw, NVPTR(scrn)->swap_limit);
-#endif
-
- break;
-
- case WAIT:
- DRI2WaitMSCComplete(s->client, draw, frame, tv_sec, tv_usec);
- free(s);
- break;
-
- case BLIT:
- DRI2SwapComplete(s->client, draw, frame, tv_sec, tv_usec,
- DRI2_BLIT_COMPLETE, s->func, s->data);
- free(s);
- break;
- }
-}
-
-void
-nouveau_dri2_flip_event_handler(unsigned int frame, unsigned int tv_sec,
- unsigned int tv_usec, void *event_data)
-{
- struct nouveau_dri2_vblank_state *flip = event_data;
- DrawablePtr draw;
- ScreenPtr screen;
- ScrnInfoPtr scrn;
- int status;
-
- status = dixLookupDrawable(&draw, flip->draw, serverClient,
- M_ANY, DixWriteAccess);
- if (status != Success) {
- free(flip);
- return;
- }
-
- screen = draw->pScreen;
- scrn = xf86ScreenToScrn(screen);
-
- /* We assume our flips arrive in order, so we don't check the frame */
- switch (flip->action) {
- case SWAP:
- /* Check for too small vblank count of pageflip completion,
- * taking wraparound into account. This usually means some
- * defective kms pageflip completion, causing wrong (msc, ust)
- * return values and possible visual corruption.
- * Skip test for frame == 0, as this is a valid constant value
- * reported by all Linux kernels at least up to Linux 3.0.
- */
- if ((frame != 0) &&
- (frame < flip->frame) && (flip->frame - frame < 5)) {
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "%s: Pageflip has impossible msc %d < target_msc %d\n",
- __func__, frame, flip->frame);
- /* All-Zero values signal failure of (msc, ust)
- * timestamping to client.
- */
- frame = tv_sec = tv_usec = 0;
- }
-
- DRI2SwapComplete(flip->client, draw, frame, tv_sec, tv_usec,
- DRI2_FLIP_COMPLETE, flip->func,
- flip->data);
- break;
- default:
- xf86DrvMsg(scrn->scrnIndex, X_WARNING,
- "%s: unknown vblank event received\n", __func__);
- /* Unknown type */
- break;
- }
-
- free(flip);
-}
-
Bool
nouveau_dri2_init(ScreenPtr pScreen)
{
diff --git a/src/nv_proto.h b/src/nv_proto.h
index f45c0d6..09f7ede 100644
--- a/src/nv_proto.h
+++ b/src/nv_proto.h
@@ -7,14 +7,15 @@ void drmmode_adjust_frame(ScrnInfoPtr pScrn, int x, int y);
void drmmode_remove_fb(ScrnInfoPtr pScrn);
Bool drmmode_cursor_init(ScreenPtr pScreen);
void drmmode_fbcon_copy(ScreenPtr pScreen);
-Bool drmmode_page_flip(DrawablePtr draw, PixmapPtr back, void *priv,
- unsigned int ref_crtc_hw_id);
void drmmode_screen_init(ScreenPtr pScreen);
void drmmode_screen_fini(ScreenPtr pScreen);
int drmmode_head(xf86CrtcPtr crtc);
void drmmode_swap(ScrnInfoPtr, uint32_t, uint32_t *);
+void drmmode_flip_handler(int fd, unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, void *event_data);
+void nouveau_dri2_vblank_handler(int fd, unsigned int frame, unsigned int tv_sec, unsigned int tv_usec, void *event_data);
+
/* in nv_accel_common.c */
Bool NVAccelCommonInit(ScrnInfoPtr pScrn);
Bool NVAccelGetCtxSurf2DFormatFromPixmap(PixmapPtr pPix, int *fmt_ret);
@@ -27,11 +28,6 @@ Bool nouveau_allocate_surface(ScrnInfoPtr scrn, int width, int height,
struct nouveau_bo **bo);
/* in nouveau_dri2.c */
-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);
Bool nouveau_dri2_init(ScreenPtr pScreen);
void nouveau_dri2_fini(ScreenPtr pScreen);