blob: 681c0acefb5bc5972e99ae61207224017eb47ec6 [file] [log] [blame]
Rob Clark4b8f30a2011-08-28 12:51:26 -05001/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
2
3/*
4 * Copyright © 2011 Texas Instruments, Inc
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
15 * Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Authors:
26 * Rob Clark <rob@ti.com>
27 */
28
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include "omap_driver.h"
Rob Clark0fdd91f2011-10-20 09:56:11 -050034#include "omap_exa.h"
Rob Clark4b8f30a2011-08-28 12:51:26 -050035
36#include "xf86drmMode.h"
37#include "dri2.h"
38
39/* any point to support earlier? */
40#if DRI2INFOREC_VERSION < 4
41# error "Requires newer DRI2"
42#endif
43
Rob Clark4b8f30a2011-08-28 12:51:26 -050044typedef struct {
45 DRI2BufferRec base;
46
Rob Clark99ab80d2012-04-12 17:38:07 -050047 /**
48 * Pixmap that is backing the buffer
49 *
50 * NOTE: don't track the pixmap ptr for the front buffer if it is
51 * a window.. this could get reallocated from beneath us, so we should
52 * always use draw2pix to be sure to have the correct one
53 */
Rob Clark4b8f30a2011-08-28 12:51:26 -050054 PixmapPtr pPixmap;
55
56 /**
Rob Clark0bdd3702012-04-20 14:47:51 -050057 * The DRI2 buffers are reference counted to avoid crashyness when the
58 * client detaches a dri2 drawable while we are still waiting for a
59 * page_flip event.
60 */
61 int refcnt;
62
Raymond Smith4a0c0aa2012-06-20 10:50:39 +010063 /**
64 * The value of canflip() for the previous frame. Used so that we can tell
65 * whether the buffer should be re-allocated, e.g into scanout-able
66 * memory if the buffer can now be flipped.
67 *
68 * We don't want to re-allocate every frame because it is unnecessary
69 * overhead most of the time apart from when we switch from flipping
70 * to blitting or vice versa.
71 *
72 * We should bump the serial number of the drawable if canflip() returns
73 * something different to what is stored here, so that the DRI2 buffers
74 * will get re-allocated.
75 */
76 int previous_canflip;
77
Rob Clark4b8f30a2011-08-28 12:51:26 -050078} OMAPDRI2BufferRec, *OMAPDRI2BufferPtr;
79
80#define OMAPBUF(p) ((OMAPDRI2BufferPtr)(p))
81#define DRIBUF(p) ((DRI2BufferPtr)(&(p)->base))
82
83
Rob Clark4b8f30a2011-08-28 12:51:26 -050084static inline DrawablePtr
85dri2draw(DrawablePtr pDraw, DRI2BufferPtr buf)
86{
87 if (buf->attachment == DRI2BufferFrontLeft) {
88 return pDraw;
89 } else {
90 return &(OMAPBUF(buf)->pPixmap->drawable);
91 }
92}
93
Rob Clark4b8f30a2011-08-28 12:51:26 -050094static Bool
95canflip(DrawablePtr pDraw)
96{
97 return (pDraw->type == DRAWABLE_WINDOW) &&
Rob Clark99ab80d2012-04-12 17:38:07 -050098 DRI2CanFlip(pDraw);
Rob Clark4b8f30a2011-08-28 12:51:26 -050099}
100
101static inline Bool
102exchangebufs(DrawablePtr pDraw, DRI2BufferPtr a, DRI2BufferPtr b)
103{
David Garbett8028b102012-09-24 09:26:47 +0100104 OMAPPixmapExchange(draw2pix(dri2draw(pDraw, a)),
105 draw2pix(dri2draw(pDraw, b)));
Rob Clark4b8f30a2011-08-28 12:51:26 -0500106 exchange(a->name, b->name);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500107 return TRUE;
108}
109
110static PixmapPtr
111createpix(DrawablePtr pDraw)
112{
113 ScreenPtr pScreen = pDraw->pScreen;
114 int flags = canflip(pDraw) ? OMAP_CREATE_PIXMAP_SCANOUT : 0;
115 return pScreen->CreatePixmap(pScreen,
116 pDraw->width, pDraw->height, pDraw->depth, flags);
117}
118
119/**
120 * Create Buffer.
121 *
122 * Note that 'format' is used from the client side to specify the DRI buffer
123 * format, which could differ from the drawable format. For example, the
124 * drawable could be 32b RGB, but the DRI buffer some YUV format (video) or
125 * perhaps lower bit depth RGB (GL). The color conversion is handled when
126 * blitting to front buffer, and page-flipping (overlay or flipchain) can
127 * only be used if the display supports.
128 */
129static DRI2BufferPtr
130OMAPDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment,
131 unsigned int format)
132{
133 ScreenPtr pScreen = pDraw->pScreen;
134 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
135 OMAPPtr pOMAP = OMAPPTR(pScrn);
136 OMAPDRI2BufferPtr buf = calloc(1, sizeof(*buf));
137 PixmapPtr pPixmap;
138 struct omap_bo *bo;
139 int ret;
140
141 DEBUG_MSG("pDraw=%p, attachment=%d, format=%08x",
142 pDraw, attachment, format);
143
144 if (!buf) {
145 return NULL;
146 }
147
148 if (attachment == DRI2BufferFrontLeft) {
149 pPixmap = draw2pix(pDraw);
150
Rob Clark834f6462012-04-20 15:40:51 -0500151 /* to do flipping, if we don't have DMM, then we need a scanout
152 * capable (physically contiguous) buffer.. this bit of gymnastics
153 * ensures that.
Rob Clark4b8f30a2011-08-28 12:51:26 -0500154 *
Rob Clark834f6462012-04-20 15:40:51 -0500155 * TODO we may want to re-allocate and switch back to non-scanout
Rob Clark4b8f30a2011-08-28 12:51:26 -0500156 * buffer when client disconnects from drawable..
157 */
Raymond Smith2b4620b2012-05-01 12:00:41 +0100158
159/* TODO: We don't have enough memory to allocate three physically contiguous buffers at the same time! Because all our
160 * buffers are scanout-able we'll not bother allocating *another* scanout buffer and just use the one we already have
161 * and save that extra buffer size */
162#if 0
Rob Clark834f6462012-04-20 15:40:51 -0500163 if (canflip(pDraw) && !has_dmm(pOMAP) &&
164 (OMAPPixmapBo(pPixmap) != pOMAP->scanout)) {
165
Rob Clark4b8f30a2011-08-28 12:51:26 -0500166 /* need to re-allocate pixmap to get a scanout capable buffer */
167 PixmapPtr pNewPix = createpix(pDraw);
168
169 // TODO copy contents..
170
171 OMAPPixmapExchange(pPixmap, pNewPix);
172
173 pScreen->DestroyPixmap(pNewPix);
174 }
Raymond Smith2b4620b2012-05-01 12:00:41 +0100175#endif
Rob Clark0bdd3702012-04-20 14:47:51 -0500176
177 pPixmap->refcnt++;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500178 } else {
179 pPixmap = createpix(pDraw);
180 }
181
182 bo = OMAPPixmapBo(pPixmap);
Raymond Smithd15a7342012-05-01 12:01:52 +0100183 if (!bo)
184 {
185 ERROR_MSG("Attempting to DRI2 wrap a pixmap with no DRM buffer object backing");
186 /* TODO: Returning NULL here ends up in a segfault all the way in pixman which has no backtrace. We get
187 * a more friendly segfault if we just let it be dereferenced in a few lines */
188 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500189
190 DRIBUF(buf)->attachment = attachment;
191 DRIBUF(buf)->pitch = exaGetPixmapPitch(pPixmap);
192 DRIBUF(buf)->cpp = pPixmap->drawable.bitsPerPixel / 8;
193 DRIBUF(buf)->format = format;
Raymond Smith2f93cb12012-05-10 07:41:34 +0100194 DRIBUF(buf)->flags = 0;
Rob Clark0bdd3702012-04-20 14:47:51 -0500195 buf->refcnt = 1;
196 buf->pPixmap = pPixmap;
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100197 buf->previous_canflip = -1;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500198
199 ret = omap_bo_get_name(bo, &DRIBUF(buf)->name);
200 if (ret) {
201 ERROR_MSG("could not get buffer name: %d", ret);
202 /* TODO cleanup */
203 return NULL;
204 }
205
Rob Clark4b8f30a2011-08-28 12:51:26 -0500206 /* Q: how to know across OMAP generations what formats that the display
207 * can support directly?
208 * A: attempt to create a drm_framebuffer, and if that fails then the
David Garbett7d6a6e72012-05-11 11:52:45 +0100209 * hw must not support.. then fall back to blitting
Rob Clark4b8f30a2011-08-28 12:51:26 -0500210 */
David Garbett7d6a6e72012-05-11 11:52:45 +0100211 if (canflip(pDraw) && attachment != DRI2BufferFrontLeft) {
212 uint32_t new_fb_id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500213 int ret = drmModeAddFB(pOMAP->drmFD, pDraw->width, pDraw->height,
214 pDraw->depth, pDraw->bitsPerPixel, DRIBUF(buf)->pitch,
David Garbett7d6a6e72012-05-11 11:52:45 +0100215 omap_bo_handle(bo), &new_fb_id);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500216 if (ret) {
217 /* to-bad, so-sad, we can't flip */
218 WARNING_MSG("could not create fb: %d", ret);
David Garbett7d6a6e72012-05-11 11:52:45 +0100219 } else {
220 omap_bo_set_fb(bo, new_fb_id);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500221 }
222 }
223
224 return DRIBUF(buf);
225}
226
227/**
228 * Destroy Buffer
229 *
230 * TODO: depending on how flipping ends up working, we may need a refcnt or
231 * something like this to defer destroying a buffer that is currently being
232 * scanned out..
233 */
234static void
235OMAPDRI2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer)
236{
Rob Clark0bdd3702012-04-20 14:47:51 -0500237 OMAPDRI2BufferPtr buf = OMAPBUF(buffer);
238 /* Note: pDraw may already be deleted, so use the pPixmap here
239 * instead (since it is at least refcntd)
240 */
241 ScreenPtr pScreen = buf->pPixmap->drawable.pScreen;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500242 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark0bdd3702012-04-20 14:47:51 -0500243
244 if (--buf->refcnt > 0)
245 return;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500246
247 DEBUG_MSG("pDraw=%p, buffer=%p", pDraw, buffer);
248
Rob Clark0bdd3702012-04-20 14:47:51 -0500249 pScreen->DestroyPixmap(buf->pPixmap);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500250
251 free(buf);
252}
253
Rob Clark0bdd3702012-04-20 14:47:51 -0500254static void
255OMAPDRI2ReferenceBuffer(DRI2BufferPtr buffer)
256{
257 OMAPDRI2BufferPtr buf = OMAPBUF(buffer);
258 buf->refcnt++;
259}
260
Rob Clark4b8f30a2011-08-28 12:51:26 -0500261/**
262 *
263 */
264static void
265OMAPDRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
266 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
267{
268 ScreenPtr pScreen = pDraw->pScreen;
269 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
270 DrawablePtr pSrcDraw = dri2draw(pDraw, pSrcBuffer);
271 DrawablePtr pDstDraw = dri2draw(pDraw, pDstBuffer);
272 RegionPtr pCopyClip;
273 GCPtr pGC;
274
275 DEBUG_MSG("pDraw=%p, pDstBuffer=%p (%p), pSrcBuffer=%p (%p)",
276 pDraw, pDstBuffer, pSrcDraw, pSrcBuffer, pDstDraw);
277
278 pGC = GetScratchGC(pDstDraw->depth, pScreen);
279 if (!pGC) {
280 return;
281 }
282
283 pCopyClip = REGION_CREATE(pScreen, NULL, 0);
284 RegionCopy(pCopyClip, pRegion);
285 (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pCopyClip, 0);
286 ValidateGC(pDstDraw, pGC);
287
288 /* If the dst is the framebuffer, and we had a way to
289 * schedule a deferred blit synchronized w/ vsync, that
290 * would be a nice thing to do utilize here to avoid
291 * tearing.. when we have sync object support for GEM
292 * buffers, I think we could do something more clever
293 * here.
294 */
295
296 pGC->ops->CopyArea(pSrcDraw, pDstDraw, pGC,
297 0, 0, pDraw->width, pDraw->height, 0, 0);
298
Rob Clarke450d412012-01-08 19:33:48 -0600299 FreeScratchGC(pGC);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500300}
301
302/**
303 * Get current frame count and frame count timestamp, based on drawable's
304 * crtc.
305 */
306static int
307OMAPDRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc)
308{
309 ScreenPtr pScreen = pDraw->pScreen;
310 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
311 OMAPPtr pOMAP = OMAPPTR(pScrn);
312 drmVBlank vbl = { .request = {
313 .type = DRM_VBLANK_RELATIVE,
314 .sequence = 0,
315 } };
316 int ret;
317
318 ret = drmWaitVBlank(pOMAP->drmFD, &vbl);
319 if (ret) {
320 static int limit = 5;
321 if (limit) {
322 ERROR_MSG("get vblank counter failed: %s", strerror(errno));
323 limit--;
324 }
325 return FALSE;
326 }
327
328 if (ust) {
329 *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
330 }
331 if (msc) {
332 *msc = vbl.reply.sequence;
333 }
334
335 return TRUE;
336}
337
John Sheu022833e2012-08-15 11:40:11 -0700338#define OMAP_SWAP_FAKE_FLIP (1 << 0)
339#define OMAP_SWAP_FAIL (1 << 1)
340
Rob Clark4b8f30a2011-08-28 12:51:26 -0500341struct _OMAPDRISwapCmd {
Rob Clarka6762ef2012-04-12 17:38:39 -0500342 int type;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500343 ClientPtr client;
Rob Clark0bdd3702012-04-20 14:47:51 -0500344 ScreenPtr pScreen;
345 /* Note: store drawable ID, rather than drawable. It's possible that
346 * the drawable can be destroyed while we wait for page flip event:
347 */
348 XID draw_id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500349 DRI2BufferPtr pDstBuffer;
350 DRI2BufferPtr pSrcBuffer;
351 DRI2SwapEventPtr func;
John Sheu022833e2012-08-15 11:40:11 -0700352 int swapCount;
353 int flags;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500354 void *data;
355};
356
Rob Clark0bdd3702012-04-20 14:47:51 -0500357static const char *swap_names[] = {
358 [DRI2_EXCHANGE_COMPLETE] = "exchange",
359 [DRI2_BLIT_COMPLETE] = "blit",
360 [DRI2_FLIP_COMPLETE] = "flip,"
361};
362
Rob Clark4b8f30a2011-08-28 12:51:26 -0500363void
364OMAPDRI2SwapComplete(OMAPDRISwapCmd *cmd)
365{
Rob Clark0bdd3702012-04-20 14:47:51 -0500366 ScreenPtr pScreen = cmd->pScreen;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500367 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark67b875f2012-04-20 19:13:57 -0500368 OMAPPtr pOMAP = OMAPPTR(pScrn);
Rob Clark0bdd3702012-04-20 14:47:51 -0500369 DrawablePtr pDraw = NULL;
370 int status;
David Garbett3688b332012-05-11 12:17:34 +0100371 OMAPPixmapPrivPtr dst_priv;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500372
John Sheu022833e2012-08-15 11:40:11 -0700373 if (--cmd->swapCount > 0)
374 return;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500375
John Sheu022833e2012-08-15 11:40:11 -0700376 if ((cmd->flags & OMAP_SWAP_FAIL) == 0) {
377 DEBUG_MSG("%s complete: %d -> %d", swap_names[cmd->type],
378 cmd->pSrcBuffer->attachment, cmd->pDstBuffer->attachment);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500379
John Sheu022833e2012-08-15 11:40:11 -0700380 status = dixLookupDrawable(&pDraw, cmd->draw_id, serverClient,
381 M_ANY, DixWriteAccess);
382
383 if (status == Success) {
384 if (cmd->type != DRI2_BLIT_COMPLETE && (cmd->flags & OMAP_SWAP_FAKE_FLIP) == 0) {
385 assert(cmd->type == DRI2_FLIP_COMPLETE);
386 exchangebufs(pDraw, cmd->pSrcBuffer, cmd->pDstBuffer);
387 }
388
389 DRI2SwapComplete(cmd->client, pDraw, 0, 0, 0, cmd->type,
390 cmd->func, cmd->data);
391
392 if (cmd->type != DRI2_BLIT_COMPLETE && (cmd->flags & OMAP_SWAP_FAKE_FLIP) == 0) {
393 dst_priv = exaGetPixmapDriverPrivate(draw2pix(dri2draw(pDraw, cmd->pDstBuffer)));
394 assert(cmd->type == DRI2_FLIP_COMPLETE);
395 set_scanout_bo(pScrn, dst_priv->bo);
396 }
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100397 }
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100398 }
David Garbett3688b332012-05-11 12:17:34 +0100399
Rob Clark0bdd3702012-04-20 14:47:51 -0500400 /* drop extra refcnt we obtained prior to swap:
401 */
402 OMAPDRI2DestroyBuffer(pDraw, cmd->pSrcBuffer);
403 OMAPDRI2DestroyBuffer(pDraw, cmd->pDstBuffer);
Rob Clark67b875f2012-04-20 19:13:57 -0500404 pOMAP->pending_flips--;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500405
406 free(cmd);
407}
408
409/**
410 * ScheduleSwap is responsible for requesting a DRM vblank event for the
411 * appropriate frame.
412 *
413 * In the case of a blit (e.g. for a windowed swap) or buffer exchange,
414 * the vblank requested can simply be the last queued swap frame + the swap
415 * interval for the drawable.
416 *
417 * In the case of a page flip, we request an event for the last queued swap
418 * frame + swap interval - 1, since we'll need to queue the flip for the frame
419 * immediately following the received event.
420 */
421static int
422OMAPDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
423 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer,
424 CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
425 DRI2SwapEventPtr func, void *data)
426{
427 ScreenPtr pScreen = pDraw->pScreen;
428 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark67b875f2012-04-20 19:13:57 -0500429 OMAPPtr pOMAP = OMAPPTR(pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500430 OMAPDRI2BufferPtr src = OMAPBUF(pSrcBuffer);
431 OMAPDRI2BufferPtr dst = OMAPBUF(pDstBuffer);
432 OMAPDRISwapCmd *cmd = calloc(1, sizeof(*cmd));
David Garbett7d6a6e72012-05-11 11:52:45 +0100433 int src_fb_id, dst_fb_id;
434 OMAPPixmapPrivPtr src_priv, dst_priv;
John Sheu022833e2012-08-15 11:40:11 -0700435 int new_canflip, ret;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500436
437 cmd->client = client;
Rob Clark0bdd3702012-04-20 14:47:51 -0500438 cmd->pScreen = pScreen;
439 cmd->draw_id = pDraw->id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500440 cmd->pSrcBuffer = pSrcBuffer;
441 cmd->pDstBuffer = pDstBuffer;
John Sheu022833e2012-08-15 11:40:11 -0700442 cmd->swapCount = 0;
443 cmd->flags = 0;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500444 cmd->func = func;
445 cmd->data = data;
446
447 DEBUG_MSG("%d -> %d", pSrcBuffer->attachment, pDstBuffer->attachment);
448
Rob Clark0bdd3702012-04-20 14:47:51 -0500449 /* obtain extra ref on buffers to avoid them going away while we await
450 * the page flip event:
451 */
452 OMAPDRI2ReferenceBuffer(pSrcBuffer);
453 OMAPDRI2ReferenceBuffer(pDstBuffer);
Rob Clark67b875f2012-04-20 19:13:57 -0500454 pOMAP->pending_flips++;
Rob Clark0bdd3702012-04-20 14:47:51 -0500455
David Garbett7d6a6e72012-05-11 11:52:45 +0100456 src_priv = exaGetPixmapDriverPrivate(src->pPixmap);
457 dst_priv = exaGetPixmapDriverPrivate(dst->pPixmap);
458
459 src_fb_id = omap_bo_get_fb(src_priv->bo);
460 dst_fb_id = omap_bo_get_fb(dst_priv->bo);
461
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100462 new_canflip = canflip(pDraw);
463 if ((src->previous_canflip != -1 && src->previous_canflip != new_canflip) ||
Shirish S29e4a232012-07-13 19:34:24 -0700464 (dst->previous_canflip != -1 && dst->previous_canflip != new_canflip) ||
465 (pOMAP->has_resized))
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100466 {
467 /* The drawable has transitioned between being flippable and non-flippable
468 * or vice versa. Bump the serial number to force the DRI2 buffers to be
469 * re-allocated during the next frame so that:
470 * - It is able to be scanned out (if drawable is now flippable), or
471 * - It is not taking up possibly scarce scanout-able memory (if drawable
472 * is now not flippable)
Shirish S29e4a232012-07-13 19:34:24 -0700473 *
474 * has_resized: On hotplugging back buffer needs to be invalidates as well
475 * as Xsever invalidates only the front buffer.
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100476 */
477
478 PixmapPtr pPix = pScreen->GetWindowPixmap((WindowPtr)pDraw);
479 pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER;
480 }
481
482 src->previous_canflip = new_canflip;
483 dst->previous_canflip = new_canflip;
484
Shirish S29e4a232012-07-13 19:34:24 -0700485 if (src_fb_id && dst_fb_id && canflip(pDraw) && !(pOMAP->has_resized)) {
486 /* has_resized: On hotplug the fb size and crtc sizes arent updated
487 * hence on this event we do a copyb but flip from the next frame
488 * when the sizes are updated.
489 */
David Garbett7d6a6e72012-05-11 11:52:45 +0100490 DEBUG_MSG("can flip: %d -> %d", src_fb_id, dst_fb_id);
Rob Clarka6762ef2012-04-12 17:38:39 -0500491 cmd->type = DRI2_FLIP_COMPLETE;
John Sheu022833e2012-08-15 11:40:11 -0700492 /* TODO: handle rollback if only multiple CRTC flip is only partially successful
493 */
494 ret = drmmode_page_flip(pDraw, src_fb_id, cmd);
495
496 /* If using page flip events, we'll trigger an immediate completion in
497 * the case that no CRTCs were enabled to be flipped. If not using page
498 * flip events, trigger immediate completion unconditionally.
499 */
500 if (ret < 0) {
501 /*
502 * Error while flipping; bail.
503 */
504 cmd->flags |= OMAP_SWAP_FAIL;
505#if !OMAP_USE_PAGE_FLIP_EVENTS
506 cmd->swapCount = 0;
507#else
508 cmd->swapCount = -(ret + 1);
509 if (cmd->swapCount == 0)
510#endif
511 {
512 OMAPDRI2SwapComplete(cmd);
513 }
514 return FALSE;
515 } else {
516 if (ret == 0)
517 cmd->flags |= OMAP_SWAP_FAKE_FLIP;
518#if !OMAP_USE_PAGE_FLIP_EVENTS
519 cmd->swapCount = 0;
520#else
521 cmd->swapCount = ret;
522 if (cmd->swapCount == 0)
523#endif
524 {
525 OMAPDRI2SwapComplete(cmd);
526 }
527 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500528 } else {
529 /* fallback to blit: */
530 BoxRec box = {
531 .x1 = 0,
532 .y1 = 0,
533 .x2 = pDraw->width,
534 .y2 = pDraw->height,
535 };
536 RegionRec region;
537 RegionInit(&region, &box, 0);
538 OMAPDRI2CopyRegion(pDraw, &region, pDstBuffer, pSrcBuffer);
Rob Clarka6762ef2012-04-12 17:38:39 -0500539 cmd->type = DRI2_BLIT_COMPLETE;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500540 OMAPDRI2SwapComplete(cmd);
Shirish S29e4a232012-07-13 19:34:24 -0700541 pOMAP->has_resized = FALSE;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500542 }
543
544 return TRUE;
545}
546
547/**
548 * Request a DRM event when the requested conditions will be satisfied.
549 *
550 * We need to handle the event and ask the server to wake up the client when
551 * we receive it.
552 */
553static int
554OMAPDRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
555 CARD64 divisor, CARD64 remainder)
556{
557 ScreenPtr pScreen = pDraw->pScreen;
558 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
559// OMAPPtr pOMAP = OMAPPTR(pScrn);
560
561#if 0
562#endif
563 ERROR_MSG("not implemented");
564 return FALSE;
565}
566
567/**
568 * The DRI2 ScreenInit() function.. register our handler fxns w/ DRI2 core
569 */
570Bool
571OMAPDRI2ScreenInit(ScreenPtr pScreen)
572{
573 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
574 OMAPPtr pOMAP = OMAPPTR(pScrn);
575 DRI2InfoRec info = {
576 .version = 5,
577 .fd = pOMAP->drmFD,
John Sheub4344ae2012-06-15 17:44:24 -0700578 .driverName = "armsoc",
Rob Clark4b8f30a2011-08-28 12:51:26 -0500579 .deviceName = pOMAP->deviceName,
580 .CreateBuffer = OMAPDRI2CreateBuffer,
581 .DestroyBuffer = OMAPDRI2DestroyBuffer,
582 .CopyRegion = OMAPDRI2CopyRegion,
583 .ScheduleSwap = OMAPDRI2ScheduleSwap,
584 .ScheduleWaitMSC = OMAPDRI2ScheduleWaitMSC,
585 .GetMSC = OMAPDRI2GetMSC,
586 .AuthMagic = drmAuthMagic,
587 };
588 int minor = 1, major = 0;
589
590 if (xf86LoaderCheckSymbol("DRI2Version")) {
591 DRI2Version(&major, &minor);
592 }
593
594 if (minor < 1) {
595 WARNING_MSG("DRI2 requires DRI2 module version 1.1.0 or later");
596 return FALSE;
597 }
598
599 return DRI2ScreenInit(pScreen, &info);
600}
601
602/**
603 * The DRI2 CloseScreen() function.. unregister ourself w/ DRI2 core.
604 */
605void
606OMAPDRI2CloseScreen(ScreenPtr pScreen)
607{
Rob Clark67b875f2012-04-20 19:13:57 -0500608 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
609 OMAPPtr pOMAP = OMAPPTR(pScrn);
610 while (pOMAP->pending_flips > 0) {
611 DEBUG_MSG("waiting..");
612 drmmode_wait_for_event(pScrn);
613 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500614 DRI2CloseScreen(pScreen);
615}