blob: 237efac40d1961ccd57b3a059733c4e97e4a93e1 [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{
Dave Barnishc50baf52012-11-29 14:39:36 +000097 ScreenPtr pScreen = pDraw->pScreen;
98 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
99 OMAPPtr pOMAP = OMAPPTR(pScrn);
100
101 if( pOMAP->NoFlip ) {
102 /* flipping is disabled by user option */
103 return FALSE;
104 } else {
105 return (pDraw->type == DRAWABLE_WINDOW) &&
106 DRI2CanFlip(pDraw);
107 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500108}
109
110static inline Bool
111exchangebufs(DrawablePtr pDraw, DRI2BufferPtr a, DRI2BufferPtr b)
112{
David Garbettae5a6362012-07-02 10:15:47 +0100113 PixmapPtr aPix = draw2pix(dri2draw(pDraw, a));
114 PixmapPtr bPix = draw2pix(dri2draw(pDraw, b));
115
116 OMAPPixmapExchange(aPix,bPix);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500117 exchange(a->name, b->name);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500118 return TRUE;
119}
120
121static PixmapPtr
122createpix(DrawablePtr pDraw)
123{
124 ScreenPtr pScreen = pDraw->pScreen;
125 int flags = canflip(pDraw) ? OMAP_CREATE_PIXMAP_SCANOUT : 0;
126 return pScreen->CreatePixmap(pScreen,
127 pDraw->width, pDraw->height, pDraw->depth, flags);
128}
129
130/**
131 * Create Buffer.
132 *
133 * Note that 'format' is used from the client side to specify the DRI buffer
134 * format, which could differ from the drawable format. For example, the
135 * drawable could be 32b RGB, but the DRI buffer some YUV format (video) or
136 * perhaps lower bit depth RGB (GL). The color conversion is handled when
137 * blitting to front buffer, and page-flipping (overlay or flipchain) can
138 * only be used if the display supports.
139 */
140static DRI2BufferPtr
141OMAPDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment,
142 unsigned int format)
143{
144 ScreenPtr pScreen = pDraw->pScreen;
145 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark4b8f30a2011-08-28 12:51:26 -0500146 OMAPDRI2BufferPtr buf = calloc(1, sizeof(*buf));
147 PixmapPtr pPixmap;
148 struct omap_bo *bo;
149 int ret;
150
151 DEBUG_MSG("pDraw=%p, attachment=%d, format=%08x",
152 pDraw, attachment, format);
153
154 if (!buf) {
155 return NULL;
156 }
157
158 if (attachment == DRI2BufferFrontLeft) {
159 pPixmap = draw2pix(pDraw);
160
Raymond Smith2b4620b2012-05-01 12:00:41 +0100161
Dave Barnish2742d152013-03-13 13:36:58 +0000162/* TODO: MIDEGL-1442: We don't have enough memory to allocate three physically contiguous buffers at the same time! Because all our
Raymond Smith2b4620b2012-05-01 12:00:41 +0100163 * buffers are scanout-able we'll not bother allocating *another* scanout buffer and just use the one we already have
164 * and save that extra buffer size */
165#if 0
Dave Barnish2742d152013-03-13 13:36:58 +0000166 /* to do flipping, if we don't have DMM, then we need a scanout
167 * capable (physically contiguous) buffer.. this bit of gymnastics
168 * ensures that.
169 */
Rob Clark834f6462012-04-20 15:40:51 -0500170 if (canflip(pDraw) && !has_dmm(pOMAP) &&
171 (OMAPPixmapBo(pPixmap) != pOMAP->scanout)) {
172
Rob Clark4b8f30a2011-08-28 12:51:26 -0500173 /* need to re-allocate pixmap to get a scanout capable buffer */
174 PixmapPtr pNewPix = createpix(pDraw);
175
Rob Clark4b8f30a2011-08-28 12:51:26 -0500176 OMAPPixmapExchange(pPixmap, pNewPix);
177
178 pScreen->DestroyPixmap(pNewPix);
179 }
Raymond Smith2b4620b2012-05-01 12:00:41 +0100180#endif
Rob Clark0bdd3702012-04-20 14:47:51 -0500181
182 pPixmap->refcnt++;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500183 } else {
184 pPixmap = createpix(pDraw);
185 }
186
Ray Smith2bc3bf62013-03-15 12:05:08 +0000187 if (!pPixmap)
188 {
189 assert(attachment != DRI2BufferFrontLeft);
190 ERROR_MSG("Failed to create back buffer for window");
191 free(buf);
192 return NULL;
193 }
194
Rob Clark4b8f30a2011-08-28 12:51:26 -0500195 bo = OMAPPixmapBo(pPixmap);
Raymond Smithd15a7342012-05-01 12:01:52 +0100196 if (!bo)
197 {
198 ERROR_MSG("Attempting to DRI2 wrap a pixmap with no DRM buffer object backing");
Ray Smith2bc3bf62013-03-15 12:05:08 +0000199 free(buf);
200 return NULL;
Raymond Smithd15a7342012-05-01 12:01:52 +0100201 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500202
203 DRIBUF(buf)->attachment = attachment;
204 DRIBUF(buf)->pitch = exaGetPixmapPitch(pPixmap);
205 DRIBUF(buf)->cpp = pPixmap->drawable.bitsPerPixel / 8;
206 DRIBUF(buf)->format = format;
Raymond Smith2f93cb12012-05-10 07:41:34 +0100207 DRIBUF(buf)->flags = 0;
Rob Clark0bdd3702012-04-20 14:47:51 -0500208 buf->refcnt = 1;
209 buf->pPixmap = pPixmap;
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100210 buf->previous_canflip = -1;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500211
212 ret = omap_bo_get_name(bo, &DRIBUF(buf)->name);
213 if (ret) {
214 ERROR_MSG("could not get buffer name: %d", ret);
Dave Barnish2742d152013-03-13 13:36:58 +0000215 /* TODO: MIDEGL-1462: cleanup */
Rob Clark4b8f30a2011-08-28 12:51:26 -0500216 return NULL;
217 }
218
Rob Clark4b8f30a2011-08-28 12:51:26 -0500219 /* Q: how to know across OMAP generations what formats that the display
220 * can support directly?
221 * A: attempt to create a drm_framebuffer, and if that fails then the
David Garbett7d6a6e72012-05-11 11:52:45 +0100222 * hw must not support.. then fall back to blitting
Rob Clark4b8f30a2011-08-28 12:51:26 -0500223 */
David Garbett7d6a6e72012-05-11 11:52:45 +0100224 if (canflip(pDraw) && attachment != DRI2BufferFrontLeft) {
Sean Paul3e107302012-08-30 12:08:12 -0700225 int ret = omap_bo_add_fb(bo);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500226 if (ret) {
227 /* to-bad, so-sad, we can't flip */
228 WARNING_MSG("could not create fb: %d", ret);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500229 }
230 }
231
David Garbettae5a6362012-07-02 10:15:47 +0100232 /* Register Pixmap as having a buffer that can be accessed externally,
233 * so needs synchronised access */
234 OMAPRegisterExternalAccess(pPixmap);
235
Rob Clark4b8f30a2011-08-28 12:51:26 -0500236 return DRIBUF(buf);
237}
238
239/**
240 * Destroy Buffer
241 *
Dave Barnish2742d152013-03-13 13:36:58 +0000242 * TODO: MIDEGL-1464: Depending on how flipping ends up working, we may need a refcnt or
Rob Clark4b8f30a2011-08-28 12:51:26 -0500243 * something like this to defer destroying a buffer that is currently being
244 * scanned out..
245 */
246static void
247OMAPDRI2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer)
248{
Rob Clark0bdd3702012-04-20 14:47:51 -0500249 OMAPDRI2BufferPtr buf = OMAPBUF(buffer);
250 /* Note: pDraw may already be deleted, so use the pPixmap here
251 * instead (since it is at least refcntd)
252 */
253 ScreenPtr pScreen = buf->pPixmap->drawable.pScreen;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500254 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark0bdd3702012-04-20 14:47:51 -0500255
256 if (--buf->refcnt > 0)
257 return;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500258
259 DEBUG_MSG("pDraw=%p, buffer=%p", pDraw, buffer);
260
David Garbettae5a6362012-07-02 10:15:47 +0100261 OMAPDeregisterExternalAccess(buf->pPixmap);
262
Rob Clark0bdd3702012-04-20 14:47:51 -0500263 pScreen->DestroyPixmap(buf->pPixmap);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500264
265 free(buf);
266}
267
Rob Clark0bdd3702012-04-20 14:47:51 -0500268static void
269OMAPDRI2ReferenceBuffer(DRI2BufferPtr buffer)
270{
271 OMAPDRI2BufferPtr buf = OMAPBUF(buffer);
272 buf->refcnt++;
273}
274
Rob Clark4b8f30a2011-08-28 12:51:26 -0500275/**
276 *
277 */
278static void
279OMAPDRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
280 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
281{
282 ScreenPtr pScreen = pDraw->pScreen;
283 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
284 DrawablePtr pSrcDraw = dri2draw(pDraw, pSrcBuffer);
285 DrawablePtr pDstDraw = dri2draw(pDraw, pDstBuffer);
286 RegionPtr pCopyClip;
287 GCPtr pGC;
288
289 DEBUG_MSG("pDraw=%p, pDstBuffer=%p (%p), pSrcBuffer=%p (%p)",
290 pDraw, pDstBuffer, pSrcDraw, pSrcBuffer, pDstDraw);
291
292 pGC = GetScratchGC(pDstDraw->depth, pScreen);
293 if (!pGC) {
294 return;
295 }
296
297 pCopyClip = REGION_CREATE(pScreen, NULL, 0);
298 RegionCopy(pCopyClip, pRegion);
299 (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pCopyClip, 0);
300 ValidateGC(pDstDraw, pGC);
301
302 /* If the dst is the framebuffer, and we had a way to
303 * schedule a deferred blit synchronized w/ vsync, that
304 * would be a nice thing to do utilize here to avoid
305 * tearing.. when we have sync object support for GEM
306 * buffers, I think we could do something more clever
307 * here.
308 */
309
310 pGC->ops->CopyArea(pSrcDraw, pDstDraw, pGC,
311 0, 0, pDraw->width, pDraw->height, 0, 0);
312
Rob Clarke450d412012-01-08 19:33:48 -0600313 FreeScratchGC(pGC);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500314}
315
316/**
317 * Get current frame count and frame count timestamp, based on drawable's
318 * crtc.
319 */
320static int
321OMAPDRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc)
322{
323 ScreenPtr pScreen = pDraw->pScreen;
324 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
325 OMAPPtr pOMAP = OMAPPTR(pScrn);
326 drmVBlank vbl = { .request = {
327 .type = DRM_VBLANK_RELATIVE,
328 .sequence = 0,
329 } };
330 int ret;
331
332 ret = drmWaitVBlank(pOMAP->drmFD, &vbl);
333 if (ret) {
334 static int limit = 5;
335 if (limit) {
336 ERROR_MSG("get vblank counter failed: %s", strerror(errno));
337 limit--;
338 }
339 return FALSE;
340 }
341
342 if (ust) {
343 *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
344 }
345 if (msc) {
346 *msc = vbl.reply.sequence;
347 }
348
349 return TRUE;
350}
351
John Sheu022833e2012-08-15 11:40:11 -0700352#define OMAP_SWAP_FAKE_FLIP (1 << 0)
353#define OMAP_SWAP_FAIL (1 << 1)
354
Rob Clark4b8f30a2011-08-28 12:51:26 -0500355struct _OMAPDRISwapCmd {
Rob Clarka6762ef2012-04-12 17:38:39 -0500356 int type;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500357 ClientPtr client;
Rob Clark0bdd3702012-04-20 14:47:51 -0500358 ScreenPtr pScreen;
359 /* Note: store drawable ID, rather than drawable. It's possible that
360 * the drawable can be destroyed while we wait for page flip event:
361 */
362 XID draw_id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500363 DRI2BufferPtr pDstBuffer;
364 DRI2BufferPtr pSrcBuffer;
365 DRI2SwapEventPtr func;
John Sheu022833e2012-08-15 11:40:11 -0700366 int swapCount;
367 int flags;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500368 void *data;
369};
370
Rob Clark0bdd3702012-04-20 14:47:51 -0500371static const char *swap_names[] = {
372 [DRI2_EXCHANGE_COMPLETE] = "exchange",
373 [DRI2_BLIT_COMPLETE] = "blit",
374 [DRI2_FLIP_COMPLETE] = "flip,"
375};
376
Rob Clark4b8f30a2011-08-28 12:51:26 -0500377void
378OMAPDRI2SwapComplete(OMAPDRISwapCmd *cmd)
379{
Rob Clark0bdd3702012-04-20 14:47:51 -0500380 ScreenPtr pScreen = cmd->pScreen;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500381 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark67b875f2012-04-20 19:13:57 -0500382 OMAPPtr pOMAP = OMAPPTR(pScrn);
Rob Clark0bdd3702012-04-20 14:47:51 -0500383 DrawablePtr pDraw = NULL;
384 int status;
Sean Paul269c9712012-09-04 15:17:33 -0700385 OMAPPixmapPrivPtr src_priv, dst_priv;
386 struct omap_bo *old_src_bo, *old_dst_bo;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500387
John Sheu022833e2012-08-15 11:40:11 -0700388 if (--cmd->swapCount > 0)
389 return;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500390
Sean Paul269c9712012-09-04 15:17:33 -0700391 /* Save the old source bo for unreference below */
392 src_priv = exaGetPixmapDriverPrivate(OMAPBUF(cmd->pSrcBuffer)->pPixmap);
393 dst_priv = exaGetPixmapDriverPrivate(OMAPBUF(cmd->pDstBuffer)->pPixmap);
394 old_src_bo = src_priv->bo;
395 old_dst_bo = dst_priv->bo;
396
John Sheu022833e2012-08-15 11:40:11 -0700397 if ((cmd->flags & OMAP_SWAP_FAIL) == 0) {
398 DEBUG_MSG("%s complete: %d -> %d", swap_names[cmd->type],
399 cmd->pSrcBuffer->attachment, cmd->pDstBuffer->attachment);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500400
John Sheu022833e2012-08-15 11:40:11 -0700401 status = dixLookupDrawable(&pDraw, cmd->draw_id, serverClient,
402 M_ANY, DixWriteAccess);
403
404 if (status == Success) {
405 if (cmd->type != DRI2_BLIT_COMPLETE && (cmd->flags & OMAP_SWAP_FAKE_FLIP) == 0) {
406 assert(cmd->type == DRI2_FLIP_COMPLETE);
407 exchangebufs(pDraw, cmd->pSrcBuffer, cmd->pDstBuffer);
408 }
409
410 DRI2SwapComplete(cmd->client, pDraw, 0, 0, 0, cmd->type,
411 cmd->func, cmd->data);
412
413 if (cmd->type != DRI2_BLIT_COMPLETE && (cmd->flags & OMAP_SWAP_FAKE_FLIP) == 0) {
414 dst_priv = exaGetPixmapDriverPrivate(draw2pix(dri2draw(pDraw, cmd->pDstBuffer)));
415 assert(cmd->type == DRI2_FLIP_COMPLETE);
416 set_scanout_bo(pScrn, dst_priv->bo);
417 }
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100418 }
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100419 }
David Garbett3688b332012-05-11 12:17:34 +0100420
Rob Clark0bdd3702012-04-20 14:47:51 -0500421 /* drop extra refcnt we obtained prior to swap:
422 */
423 OMAPDRI2DestroyBuffer(pDraw, cmd->pSrcBuffer);
424 OMAPDRI2DestroyBuffer(pDraw, cmd->pDstBuffer);
Sean Paul269c9712012-09-04 15:17:33 -0700425 omap_bo_unreference(old_src_bo);
426 omap_bo_unreference(old_dst_bo);
Rob Clark67b875f2012-04-20 19:13:57 -0500427 pOMAP->pending_flips--;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500428
429 free(cmd);
430}
431
432/**
433 * ScheduleSwap is responsible for requesting a DRM vblank event for the
434 * appropriate frame.
435 *
436 * In the case of a blit (e.g. for a windowed swap) or buffer exchange,
437 * the vblank requested can simply be the last queued swap frame + the swap
438 * interval for the drawable.
439 *
440 * In the case of a page flip, we request an event for the last queued swap
441 * frame + swap interval - 1, since we'll need to queue the flip for the frame
442 * immediately following the received event.
443 */
444static int
445OMAPDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
446 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer,
447 CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
448 DRI2SwapEventPtr func, void *data)
449{
450 ScreenPtr pScreen = pDraw->pScreen;
451 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark67b875f2012-04-20 19:13:57 -0500452 OMAPPtr pOMAP = OMAPPTR(pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500453 OMAPDRI2BufferPtr src = OMAPBUF(pSrcBuffer);
454 OMAPDRI2BufferPtr dst = OMAPBUF(pDstBuffer);
455 OMAPDRISwapCmd *cmd = calloc(1, sizeof(*cmd));
David Garbett7d6a6e72012-05-11 11:52:45 +0100456 int src_fb_id, dst_fb_id;
457 OMAPPixmapPrivPtr src_priv, dst_priv;
John Sheu022833e2012-08-15 11:40:11 -0700458 int new_canflip, ret;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500459
460 cmd->client = client;
Rob Clark0bdd3702012-04-20 14:47:51 -0500461 cmd->pScreen = pScreen;
462 cmd->draw_id = pDraw->id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500463 cmd->pSrcBuffer = pSrcBuffer;
464 cmd->pDstBuffer = pDstBuffer;
John Sheu022833e2012-08-15 11:40:11 -0700465 cmd->swapCount = 0;
466 cmd->flags = 0;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500467 cmd->func = func;
468 cmd->data = data;
469
470 DEBUG_MSG("%d -> %d", pSrcBuffer->attachment, pDstBuffer->attachment);
471
Rob Clark0bdd3702012-04-20 14:47:51 -0500472 /* obtain extra ref on buffers to avoid them going away while we await
473 * the page flip event:
474 */
475 OMAPDRI2ReferenceBuffer(pSrcBuffer);
476 OMAPDRI2ReferenceBuffer(pDstBuffer);
Rob Clark67b875f2012-04-20 19:13:57 -0500477 pOMAP->pending_flips++;
Rob Clark0bdd3702012-04-20 14:47:51 -0500478
David Garbett7d6a6e72012-05-11 11:52:45 +0100479 src_priv = exaGetPixmapDriverPrivate(src->pPixmap);
480 dst_priv = exaGetPixmapDriverPrivate(dst->pPixmap);
481
482 src_fb_id = omap_bo_get_fb(src_priv->bo);
483 dst_fb_id = omap_bo_get_fb(dst_priv->bo);
484
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100485 new_canflip = canflip(pDraw);
486 if ((src->previous_canflip != -1 && src->previous_canflip != new_canflip) ||
Shirish S29e4a232012-07-13 19:34:24 -0700487 (dst->previous_canflip != -1 && dst->previous_canflip != new_canflip) ||
488 (pOMAP->has_resized))
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100489 {
490 /* The drawable has transitioned between being flippable and non-flippable
491 * or vice versa. Bump the serial number to force the DRI2 buffers to be
492 * re-allocated during the next frame so that:
493 * - It is able to be scanned out (if drawable is now flippable), or
494 * - It is not taking up possibly scarce scanout-able memory (if drawable
495 * is now not flippable)
Shirish S29e4a232012-07-13 19:34:24 -0700496 *
497 * has_resized: On hotplugging back buffer needs to be invalidates as well
498 * as Xsever invalidates only the front buffer.
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100499 */
500
501 PixmapPtr pPix = pScreen->GetWindowPixmap((WindowPtr)pDraw);
502 pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER;
503 }
504
505 src->previous_canflip = new_canflip;
506 dst->previous_canflip = new_canflip;
507
Sean Paul269c9712012-09-04 15:17:33 -0700508 omap_bo_reference(src_priv->bo);
509 omap_bo_reference(dst_priv->bo);
Shirish S29e4a232012-07-13 19:34:24 -0700510 if (src_fb_id && dst_fb_id && canflip(pDraw) && !(pOMAP->has_resized)) {
511 /* has_resized: On hotplug the fb size and crtc sizes arent updated
512 * hence on this event we do a copyb but flip from the next frame
513 * when the sizes are updated.
514 */
David Garbett7d6a6e72012-05-11 11:52:45 +0100515 DEBUG_MSG("can flip: %d -> %d", src_fb_id, dst_fb_id);
Rob Clarka6762ef2012-04-12 17:38:39 -0500516 cmd->type = DRI2_FLIP_COMPLETE;
Dave Barnish2742d152013-03-13 13:36:58 +0000517 /* TODO: MIDEGL-1461: Handle rollback if multiple CRTC flip is only partially successful
John Sheu022833e2012-08-15 11:40:11 -0700518 */
519 ret = drmmode_page_flip(pDraw, src_fb_id, cmd);
520
521 /* If using page flip events, we'll trigger an immediate completion in
522 * the case that no CRTCs were enabled to be flipped. If not using page
523 * flip events, trigger immediate completion unconditionally.
524 */
525 if (ret < 0) {
526 /*
527 * Error while flipping; bail.
528 */
529 cmd->flags |= OMAP_SWAP_FAIL;
530#if !OMAP_USE_PAGE_FLIP_EVENTS
531 cmd->swapCount = 0;
532#else
533 cmd->swapCount = -(ret + 1);
534 if (cmd->swapCount == 0)
535#endif
536 {
537 OMAPDRI2SwapComplete(cmd);
538 }
539 return FALSE;
540 } else {
541 if (ret == 0)
542 cmd->flags |= OMAP_SWAP_FAKE_FLIP;
543#if !OMAP_USE_PAGE_FLIP_EVENTS
544 cmd->swapCount = 0;
545#else
546 cmd->swapCount = ret;
547 if (cmd->swapCount == 0)
548#endif
549 {
550 OMAPDRI2SwapComplete(cmd);
551 }
552 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500553 } else {
554 /* fallback to blit: */
555 BoxRec box = {
556 .x1 = 0,
557 .y1 = 0,
558 .x2 = pDraw->width,
559 .y2 = pDraw->height,
560 };
561 RegionRec region;
562 RegionInit(&region, &box, 0);
563 OMAPDRI2CopyRegion(pDraw, &region, pDstBuffer, pSrcBuffer);
Rob Clarka6762ef2012-04-12 17:38:39 -0500564 cmd->type = DRI2_BLIT_COMPLETE;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500565 OMAPDRI2SwapComplete(cmd);
Shirish S29e4a232012-07-13 19:34:24 -0700566 pOMAP->has_resized = FALSE;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500567 }
568
569 return TRUE;
570}
571
572/**
573 * Request a DRM event when the requested conditions will be satisfied.
574 *
575 * We need to handle the event and ask the server to wake up the client when
576 * we receive it.
577 */
578static int
579OMAPDRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
580 CARD64 divisor, CARD64 remainder)
581{
582 ScreenPtr pScreen = pDraw->pScreen;
583 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
584// OMAPPtr pOMAP = OMAPPTR(pScrn);
585
586#if 0
587#endif
588 ERROR_MSG("not implemented");
589 return FALSE;
590}
591
592/**
593 * The DRI2 ScreenInit() function.. register our handler fxns w/ DRI2 core
594 */
595Bool
596OMAPDRI2ScreenInit(ScreenPtr pScreen)
597{
598 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
599 OMAPPtr pOMAP = OMAPPTR(pScrn);
600 DRI2InfoRec info = {
601 .version = 5,
602 .fd = pOMAP->drmFD,
John Sheub4344ae2012-06-15 17:44:24 -0700603 .driverName = "armsoc",
Rob Clark4b8f30a2011-08-28 12:51:26 -0500604 .deviceName = pOMAP->deviceName,
605 .CreateBuffer = OMAPDRI2CreateBuffer,
606 .DestroyBuffer = OMAPDRI2DestroyBuffer,
607 .CopyRegion = OMAPDRI2CopyRegion,
608 .ScheduleSwap = OMAPDRI2ScheduleSwap,
609 .ScheduleWaitMSC = OMAPDRI2ScheduleWaitMSC,
610 .GetMSC = OMAPDRI2GetMSC,
611 .AuthMagic = drmAuthMagic,
612 };
613 int minor = 1, major = 0;
614
615 if (xf86LoaderCheckSymbol("DRI2Version")) {
616 DRI2Version(&major, &minor);
617 }
618
619 if (minor < 1) {
620 WARNING_MSG("DRI2 requires DRI2 module version 1.1.0 or later");
621 return FALSE;
622 }
623
624 return DRI2ScreenInit(pScreen, &info);
625}
626
627/**
628 * The DRI2 CloseScreen() function.. unregister ourself w/ DRI2 core.
629 */
630void
631OMAPDRI2CloseScreen(ScreenPtr pScreen)
632{
Rob Clark67b875f2012-04-20 19:13:57 -0500633 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
634 OMAPPtr pOMAP = OMAPPTR(pScrn);
635 while (pOMAP->pending_flips > 0) {
636 DEBUG_MSG("waiting..");
637 drmmode_wait_for_event(pScrn);
638 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500639 DRI2CloseScreen(pScreen);
640}