blob: ebcaebeaed342a9bbee73f88b85c8e2106b92bb6 [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));
Ray Smith9a3797b2013-03-15 15:33:04 +0000147 PixmapPtr pPixmap = NULL;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500148 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) {
Ray Smith9a3797b2013-03-15 15:33:04 +0000155 ERROR_MSG("Couldn't allocate internal buffer structure");
Rob Clark4b8f30a2011-08-28 12:51:26 -0500156 return NULL;
157 }
158
159 if (attachment == DRI2BufferFrontLeft) {
160 pPixmap = draw2pix(pDraw);
161
Raymond Smith2b4620b2012-05-01 12:00:41 +0100162
Dave Barnish2742d152013-03-13 13:36:58 +0000163/* 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 +0100164 * buffers are scanout-able we'll not bother allocating *another* scanout buffer and just use the one we already have
165 * and save that extra buffer size */
166#if 0
Dave Barnish2742d152013-03-13 13:36:58 +0000167 /* to do flipping, if we don't have DMM, then we need a scanout
168 * capable (physically contiguous) buffer.. this bit of gymnastics
169 * ensures that.
170 */
Rob Clark834f6462012-04-20 15:40:51 -0500171 if (canflip(pDraw) && !has_dmm(pOMAP) &&
172 (OMAPPixmapBo(pPixmap) != pOMAP->scanout)) {
173
Rob Clark4b8f30a2011-08-28 12:51:26 -0500174 /* need to re-allocate pixmap to get a scanout capable buffer */
175 PixmapPtr pNewPix = createpix(pDraw);
176
Rob Clark4b8f30a2011-08-28 12:51:26 -0500177 OMAPPixmapExchange(pPixmap, pNewPix);
178
179 pScreen->DestroyPixmap(pNewPix);
180 }
Raymond Smith2b4620b2012-05-01 12:00:41 +0100181#endif
Rob Clark0bdd3702012-04-20 14:47:51 -0500182
183 pPixmap->refcnt++;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500184 } else {
185 pPixmap = createpix(pDraw);
186 }
187
Ray Smith2bc3bf62013-03-15 12:05:08 +0000188 if (!pPixmap)
189 {
190 assert(attachment != DRI2BufferFrontLeft);
191 ERROR_MSG("Failed to create back buffer for window");
Ray Smith9a3797b2013-03-15 15:33:04 +0000192 goto fail;
Ray Smith2bc3bf62013-03-15 12:05:08 +0000193 }
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 Smith9a3797b2013-03-15 15:33:04 +0000199 goto fail;
Raymond Smithd15a7342012-05-01 12:01:52 +0100200 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500201
202 DRIBUF(buf)->attachment = attachment;
203 DRIBUF(buf)->pitch = exaGetPixmapPitch(pPixmap);
204 DRIBUF(buf)->cpp = pPixmap->drawable.bitsPerPixel / 8;
205 DRIBUF(buf)->format = format;
Raymond Smith2f93cb12012-05-10 07:41:34 +0100206 DRIBUF(buf)->flags = 0;
Rob Clark0bdd3702012-04-20 14:47:51 -0500207 buf->refcnt = 1;
208 buf->pPixmap = pPixmap;
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100209 buf->previous_canflip = -1;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500210
211 ret = omap_bo_get_name(bo, &DRIBUF(buf)->name);
212 if (ret) {
213 ERROR_MSG("could not get buffer name: %d", ret);
Ray Smith9a3797b2013-03-15 15:33:04 +0000214 goto fail;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500215 }
216
Rob Clark4b8f30a2011-08-28 12:51:26 -0500217 /* Q: how to know across OMAP generations what formats that the display
218 * can support directly?
219 * A: attempt to create a drm_framebuffer, and if that fails then the
David Garbett7d6a6e72012-05-11 11:52:45 +0100220 * hw must not support.. then fall back to blitting
Rob Clark4b8f30a2011-08-28 12:51:26 -0500221 */
David Garbett7d6a6e72012-05-11 11:52:45 +0100222 if (canflip(pDraw) && attachment != DRI2BufferFrontLeft) {
Sean Paul3e107302012-08-30 12:08:12 -0700223 int ret = omap_bo_add_fb(bo);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500224 if (ret) {
225 /* to-bad, so-sad, we can't flip */
226 WARNING_MSG("could not create fb: %d", ret);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500227 }
228 }
229
David Garbettae5a6362012-07-02 10:15:47 +0100230 /* Register Pixmap as having a buffer that can be accessed externally,
231 * so needs synchronised access */
232 OMAPRegisterExternalAccess(pPixmap);
233
Rob Clark4b8f30a2011-08-28 12:51:26 -0500234 return DRIBUF(buf);
Ray Smith9a3797b2013-03-15 15:33:04 +0000235
236fail:
237 if (pPixmap != NULL)
238 {
239 if (attachment != DRI2BufferFrontLeft)
240 {
241 pScreen->DestroyPixmap(pPixmap);
242 }
243 else
244 {
245 pPixmap->refcnt--;
246 }
247 }
248 free(buf);
249
250 return NULL;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500251}
252
253/**
254 * Destroy Buffer
255 *
Dave Barnish2742d152013-03-13 13:36:58 +0000256 * TODO: MIDEGL-1464: Depending on how flipping ends up working, we may need a refcnt or
Rob Clark4b8f30a2011-08-28 12:51:26 -0500257 * something like this to defer destroying a buffer that is currently being
258 * scanned out..
259 */
260static void
261OMAPDRI2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer)
262{
Rob Clark0bdd3702012-04-20 14:47:51 -0500263 OMAPDRI2BufferPtr buf = OMAPBUF(buffer);
264 /* Note: pDraw may already be deleted, so use the pPixmap here
265 * instead (since it is at least refcntd)
266 */
267 ScreenPtr pScreen = buf->pPixmap->drawable.pScreen;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500268 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark0bdd3702012-04-20 14:47:51 -0500269
270 if (--buf->refcnt > 0)
271 return;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500272
273 DEBUG_MSG("pDraw=%p, buffer=%p", pDraw, buffer);
274
David Garbettae5a6362012-07-02 10:15:47 +0100275 OMAPDeregisterExternalAccess(buf->pPixmap);
276
Rob Clark0bdd3702012-04-20 14:47:51 -0500277 pScreen->DestroyPixmap(buf->pPixmap);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500278
279 free(buf);
280}
281
Rob Clark0bdd3702012-04-20 14:47:51 -0500282static void
283OMAPDRI2ReferenceBuffer(DRI2BufferPtr buffer)
284{
285 OMAPDRI2BufferPtr buf = OMAPBUF(buffer);
286 buf->refcnt++;
287}
288
Rob Clark4b8f30a2011-08-28 12:51:26 -0500289/**
290 *
291 */
292static void
293OMAPDRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
294 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
295{
296 ScreenPtr pScreen = pDraw->pScreen;
297 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
298 DrawablePtr pSrcDraw = dri2draw(pDraw, pSrcBuffer);
299 DrawablePtr pDstDraw = dri2draw(pDraw, pDstBuffer);
300 RegionPtr pCopyClip;
301 GCPtr pGC;
302
303 DEBUG_MSG("pDraw=%p, pDstBuffer=%p (%p), pSrcBuffer=%p (%p)",
304 pDraw, pDstBuffer, pSrcDraw, pSrcBuffer, pDstDraw);
305
306 pGC = GetScratchGC(pDstDraw->depth, pScreen);
307 if (!pGC) {
308 return;
309 }
310
311 pCopyClip = REGION_CREATE(pScreen, NULL, 0);
312 RegionCopy(pCopyClip, pRegion);
313 (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pCopyClip, 0);
314 ValidateGC(pDstDraw, pGC);
315
316 /* If the dst is the framebuffer, and we had a way to
317 * schedule a deferred blit synchronized w/ vsync, that
318 * would be a nice thing to do utilize here to avoid
319 * tearing.. when we have sync object support for GEM
320 * buffers, I think we could do something more clever
321 * here.
322 */
323
324 pGC->ops->CopyArea(pSrcDraw, pDstDraw, pGC,
325 0, 0, pDraw->width, pDraw->height, 0, 0);
326
Rob Clarke450d412012-01-08 19:33:48 -0600327 FreeScratchGC(pGC);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500328}
329
330/**
331 * Get current frame count and frame count timestamp, based on drawable's
332 * crtc.
333 */
334static int
335OMAPDRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc)
336{
337 ScreenPtr pScreen = pDraw->pScreen;
338 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
339 OMAPPtr pOMAP = OMAPPTR(pScrn);
340 drmVBlank vbl = { .request = {
341 .type = DRM_VBLANK_RELATIVE,
342 .sequence = 0,
343 } };
344 int ret;
345
346 ret = drmWaitVBlank(pOMAP->drmFD, &vbl);
347 if (ret) {
348 static int limit = 5;
349 if (limit) {
350 ERROR_MSG("get vblank counter failed: %s", strerror(errno));
351 limit--;
352 }
353 return FALSE;
354 }
355
356 if (ust) {
357 *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
358 }
359 if (msc) {
360 *msc = vbl.reply.sequence;
361 }
362
363 return TRUE;
364}
365
John Sheu022833e2012-08-15 11:40:11 -0700366#define OMAP_SWAP_FAKE_FLIP (1 << 0)
367#define OMAP_SWAP_FAIL (1 << 1)
368
Rob Clark4b8f30a2011-08-28 12:51:26 -0500369struct _OMAPDRISwapCmd {
Rob Clarka6762ef2012-04-12 17:38:39 -0500370 int type;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500371 ClientPtr client;
Rob Clark0bdd3702012-04-20 14:47:51 -0500372 ScreenPtr pScreen;
373 /* Note: store drawable ID, rather than drawable. It's possible that
374 * the drawable can be destroyed while we wait for page flip event:
375 */
376 XID draw_id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500377 DRI2BufferPtr pDstBuffer;
378 DRI2BufferPtr pSrcBuffer;
379 DRI2SwapEventPtr func;
John Sheu022833e2012-08-15 11:40:11 -0700380 int swapCount;
381 int flags;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500382 void *data;
383};
384
Rob Clark0bdd3702012-04-20 14:47:51 -0500385static const char *swap_names[] = {
386 [DRI2_EXCHANGE_COMPLETE] = "exchange",
387 [DRI2_BLIT_COMPLETE] = "blit",
388 [DRI2_FLIP_COMPLETE] = "flip,"
389};
390
Rob Clark4b8f30a2011-08-28 12:51:26 -0500391void
392OMAPDRI2SwapComplete(OMAPDRISwapCmd *cmd)
393{
Rob Clark0bdd3702012-04-20 14:47:51 -0500394 ScreenPtr pScreen = cmd->pScreen;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500395 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark67b875f2012-04-20 19:13:57 -0500396 OMAPPtr pOMAP = OMAPPTR(pScrn);
Rob Clark0bdd3702012-04-20 14:47:51 -0500397 DrawablePtr pDraw = NULL;
398 int status;
Sean Paul269c9712012-09-04 15:17:33 -0700399 OMAPPixmapPrivPtr src_priv, dst_priv;
400 struct omap_bo *old_src_bo, *old_dst_bo;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500401
John Sheu022833e2012-08-15 11:40:11 -0700402 if (--cmd->swapCount > 0)
403 return;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500404
Sean Paul269c9712012-09-04 15:17:33 -0700405 /* Save the old source bo for unreference below */
406 src_priv = exaGetPixmapDriverPrivate(OMAPBUF(cmd->pSrcBuffer)->pPixmap);
407 dst_priv = exaGetPixmapDriverPrivate(OMAPBUF(cmd->pDstBuffer)->pPixmap);
408 old_src_bo = src_priv->bo;
409 old_dst_bo = dst_priv->bo;
410
John Sheu022833e2012-08-15 11:40:11 -0700411 if ((cmd->flags & OMAP_SWAP_FAIL) == 0) {
412 DEBUG_MSG("%s complete: %d -> %d", swap_names[cmd->type],
413 cmd->pSrcBuffer->attachment, cmd->pDstBuffer->attachment);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500414
John Sheu022833e2012-08-15 11:40:11 -0700415 status = dixLookupDrawable(&pDraw, cmd->draw_id, serverClient,
416 M_ANY, DixWriteAccess);
417
418 if (status == Success) {
419 if (cmd->type != DRI2_BLIT_COMPLETE && (cmd->flags & OMAP_SWAP_FAKE_FLIP) == 0) {
420 assert(cmd->type == DRI2_FLIP_COMPLETE);
421 exchangebufs(pDraw, cmd->pSrcBuffer, cmd->pDstBuffer);
422 }
423
424 DRI2SwapComplete(cmd->client, pDraw, 0, 0, 0, cmd->type,
425 cmd->func, cmd->data);
426
427 if (cmd->type != DRI2_BLIT_COMPLETE && (cmd->flags & OMAP_SWAP_FAKE_FLIP) == 0) {
428 dst_priv = exaGetPixmapDriverPrivate(draw2pix(dri2draw(pDraw, cmd->pDstBuffer)));
429 assert(cmd->type == DRI2_FLIP_COMPLETE);
430 set_scanout_bo(pScrn, dst_priv->bo);
431 }
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100432 }
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100433 }
David Garbett3688b332012-05-11 12:17:34 +0100434
Rob Clark0bdd3702012-04-20 14:47:51 -0500435 /* drop extra refcnt we obtained prior to swap:
436 */
437 OMAPDRI2DestroyBuffer(pDraw, cmd->pSrcBuffer);
438 OMAPDRI2DestroyBuffer(pDraw, cmd->pDstBuffer);
Sean Paul269c9712012-09-04 15:17:33 -0700439 omap_bo_unreference(old_src_bo);
440 omap_bo_unreference(old_dst_bo);
Rob Clark67b875f2012-04-20 19:13:57 -0500441 pOMAP->pending_flips--;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500442
443 free(cmd);
444}
445
446/**
447 * ScheduleSwap is responsible for requesting a DRM vblank event for the
448 * appropriate frame.
449 *
450 * In the case of a blit (e.g. for a windowed swap) or buffer exchange,
451 * the vblank requested can simply be the last queued swap frame + the swap
452 * interval for the drawable.
453 *
454 * In the case of a page flip, we request an event for the last queued swap
455 * frame + swap interval - 1, since we'll need to queue the flip for the frame
456 * immediately following the received event.
457 */
458static int
459OMAPDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
460 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer,
461 CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
462 DRI2SwapEventPtr func, void *data)
463{
464 ScreenPtr pScreen = pDraw->pScreen;
465 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark67b875f2012-04-20 19:13:57 -0500466 OMAPPtr pOMAP = OMAPPTR(pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500467 OMAPDRI2BufferPtr src = OMAPBUF(pSrcBuffer);
468 OMAPDRI2BufferPtr dst = OMAPBUF(pDstBuffer);
469 OMAPDRISwapCmd *cmd = calloc(1, sizeof(*cmd));
David Garbett7d6a6e72012-05-11 11:52:45 +0100470 int src_fb_id, dst_fb_id;
471 OMAPPixmapPrivPtr src_priv, dst_priv;
John Sheu022833e2012-08-15 11:40:11 -0700472 int new_canflip, ret;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500473
474 cmd->client = client;
Rob Clark0bdd3702012-04-20 14:47:51 -0500475 cmd->pScreen = pScreen;
476 cmd->draw_id = pDraw->id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500477 cmd->pSrcBuffer = pSrcBuffer;
478 cmd->pDstBuffer = pDstBuffer;
John Sheu022833e2012-08-15 11:40:11 -0700479 cmd->swapCount = 0;
480 cmd->flags = 0;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500481 cmd->func = func;
482 cmd->data = data;
483
484 DEBUG_MSG("%d -> %d", pSrcBuffer->attachment, pDstBuffer->attachment);
485
Rob Clark0bdd3702012-04-20 14:47:51 -0500486 /* obtain extra ref on buffers to avoid them going away while we await
487 * the page flip event:
488 */
489 OMAPDRI2ReferenceBuffer(pSrcBuffer);
490 OMAPDRI2ReferenceBuffer(pDstBuffer);
Rob Clark67b875f2012-04-20 19:13:57 -0500491 pOMAP->pending_flips++;
Rob Clark0bdd3702012-04-20 14:47:51 -0500492
David Garbett7d6a6e72012-05-11 11:52:45 +0100493 src_priv = exaGetPixmapDriverPrivate(src->pPixmap);
494 dst_priv = exaGetPixmapDriverPrivate(dst->pPixmap);
495
496 src_fb_id = omap_bo_get_fb(src_priv->bo);
497 dst_fb_id = omap_bo_get_fb(dst_priv->bo);
498
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100499 new_canflip = canflip(pDraw);
500 if ((src->previous_canflip != -1 && src->previous_canflip != new_canflip) ||
Shirish S29e4a232012-07-13 19:34:24 -0700501 (dst->previous_canflip != -1 && dst->previous_canflip != new_canflip) ||
502 (pOMAP->has_resized))
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100503 {
504 /* The drawable has transitioned between being flippable and non-flippable
505 * or vice versa. Bump the serial number to force the DRI2 buffers to be
506 * re-allocated during the next frame so that:
507 * - It is able to be scanned out (if drawable is now flippable), or
508 * - It is not taking up possibly scarce scanout-able memory (if drawable
509 * is now not flippable)
Shirish S29e4a232012-07-13 19:34:24 -0700510 *
511 * has_resized: On hotplugging back buffer needs to be invalidates as well
512 * as Xsever invalidates only the front buffer.
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100513 */
514
515 PixmapPtr pPix = pScreen->GetWindowPixmap((WindowPtr)pDraw);
516 pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER;
517 }
518
519 src->previous_canflip = new_canflip;
520 dst->previous_canflip = new_canflip;
521
Sean Paul269c9712012-09-04 15:17:33 -0700522 omap_bo_reference(src_priv->bo);
523 omap_bo_reference(dst_priv->bo);
Shirish S29e4a232012-07-13 19:34:24 -0700524 if (src_fb_id && dst_fb_id && canflip(pDraw) && !(pOMAP->has_resized)) {
525 /* has_resized: On hotplug the fb size and crtc sizes arent updated
526 * hence on this event we do a copyb but flip from the next frame
527 * when the sizes are updated.
528 */
David Garbett7d6a6e72012-05-11 11:52:45 +0100529 DEBUG_MSG("can flip: %d -> %d", src_fb_id, dst_fb_id);
Rob Clarka6762ef2012-04-12 17:38:39 -0500530 cmd->type = DRI2_FLIP_COMPLETE;
Dave Barnish2742d152013-03-13 13:36:58 +0000531 /* TODO: MIDEGL-1461: Handle rollback if multiple CRTC flip is only partially successful
John Sheu022833e2012-08-15 11:40:11 -0700532 */
533 ret = drmmode_page_flip(pDraw, src_fb_id, cmd);
534
535 /* If using page flip events, we'll trigger an immediate completion in
536 * the case that no CRTCs were enabled to be flipped. If not using page
537 * flip events, trigger immediate completion unconditionally.
538 */
539 if (ret < 0) {
540 /*
541 * Error while flipping; bail.
542 */
543 cmd->flags |= OMAP_SWAP_FAIL;
544#if !OMAP_USE_PAGE_FLIP_EVENTS
545 cmd->swapCount = 0;
546#else
547 cmd->swapCount = -(ret + 1);
548 if (cmd->swapCount == 0)
549#endif
550 {
551 OMAPDRI2SwapComplete(cmd);
552 }
553 return FALSE;
554 } else {
555 if (ret == 0)
556 cmd->flags |= OMAP_SWAP_FAKE_FLIP;
557#if !OMAP_USE_PAGE_FLIP_EVENTS
558 cmd->swapCount = 0;
559#else
560 cmd->swapCount = ret;
561 if (cmd->swapCount == 0)
562#endif
563 {
564 OMAPDRI2SwapComplete(cmd);
565 }
566 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500567 } else {
568 /* fallback to blit: */
569 BoxRec box = {
570 .x1 = 0,
571 .y1 = 0,
572 .x2 = pDraw->width,
573 .y2 = pDraw->height,
574 };
575 RegionRec region;
576 RegionInit(&region, &box, 0);
577 OMAPDRI2CopyRegion(pDraw, &region, pDstBuffer, pSrcBuffer);
Rob Clarka6762ef2012-04-12 17:38:39 -0500578 cmd->type = DRI2_BLIT_COMPLETE;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500579 OMAPDRI2SwapComplete(cmd);
Shirish S29e4a232012-07-13 19:34:24 -0700580 pOMAP->has_resized = FALSE;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500581 }
582
583 return TRUE;
584}
585
586/**
587 * Request a DRM event when the requested conditions will be satisfied.
588 *
589 * We need to handle the event and ask the server to wake up the client when
590 * we receive it.
591 */
592static int
593OMAPDRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
594 CARD64 divisor, CARD64 remainder)
595{
596 ScreenPtr pScreen = pDraw->pScreen;
597 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
598// OMAPPtr pOMAP = OMAPPTR(pScrn);
599
600#if 0
601#endif
602 ERROR_MSG("not implemented");
603 return FALSE;
604}
605
606/**
607 * The DRI2 ScreenInit() function.. register our handler fxns w/ DRI2 core
608 */
609Bool
610OMAPDRI2ScreenInit(ScreenPtr pScreen)
611{
612 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
613 OMAPPtr pOMAP = OMAPPTR(pScrn);
614 DRI2InfoRec info = {
615 .version = 5,
616 .fd = pOMAP->drmFD,
John Sheub4344ae2012-06-15 17:44:24 -0700617 .driverName = "armsoc",
Rob Clark4b8f30a2011-08-28 12:51:26 -0500618 .deviceName = pOMAP->deviceName,
619 .CreateBuffer = OMAPDRI2CreateBuffer,
620 .DestroyBuffer = OMAPDRI2DestroyBuffer,
621 .CopyRegion = OMAPDRI2CopyRegion,
622 .ScheduleSwap = OMAPDRI2ScheduleSwap,
623 .ScheduleWaitMSC = OMAPDRI2ScheduleWaitMSC,
624 .GetMSC = OMAPDRI2GetMSC,
625 .AuthMagic = drmAuthMagic,
626 };
627 int minor = 1, major = 0;
628
629 if (xf86LoaderCheckSymbol("DRI2Version")) {
630 DRI2Version(&major, &minor);
631 }
632
633 if (minor < 1) {
634 WARNING_MSG("DRI2 requires DRI2 module version 1.1.0 or later");
635 return FALSE;
636 }
637
638 return DRI2ScreenInit(pScreen, &info);
639}
640
641/**
642 * The DRI2 CloseScreen() function.. unregister ourself w/ DRI2 core.
643 */
644void
645OMAPDRI2CloseScreen(ScreenPtr pScreen)
646{
Rob Clark67b875f2012-04-20 19:13:57 -0500647 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
648 OMAPPtr pOMAP = OMAPPTR(pScrn);
649 while (pOMAP->pending_flips > 0) {
650 DEBUG_MSG("waiting..");
651 drmmode_wait_for_event(pScrn);
652 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500653 DRI2CloseScreen(pScreen);
654}