blob: 4e2587ccfbc9797dba8e865c3ec62ae08bfca2de [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
Ray Smith3c33c3d2013-03-26 16:06:37 +000044#include "drmmode_driver.h"
45
Rob Clark4b8f30a2011-08-28 12:51:26 -050046typedef struct {
47 DRI2BufferRec base;
48
Rob Clark99ab80d2012-04-12 17:38:07 -050049 /**
50 * Pixmap that is backing the buffer
51 *
52 * NOTE: don't track the pixmap ptr for the front buffer if it is
53 * a window.. this could get reallocated from beneath us, so we should
54 * always use draw2pix to be sure to have the correct one
55 */
Rob Clark4b8f30a2011-08-28 12:51:26 -050056 PixmapPtr pPixmap;
57
58 /**
Rob Clark0bdd3702012-04-20 14:47:51 -050059 * The DRI2 buffers are reference counted to avoid crashyness when the
60 * client detaches a dri2 drawable while we are still waiting for a
61 * page_flip event.
62 */
63 int refcnt;
64
Raymond Smith4a0c0aa2012-06-20 10:50:39 +010065 /**
66 * The value of canflip() for the previous frame. Used so that we can tell
67 * whether the buffer should be re-allocated, e.g into scanout-able
68 * memory if the buffer can now be flipped.
69 *
70 * We don't want to re-allocate every frame because it is unnecessary
71 * overhead most of the time apart from when we switch from flipping
72 * to blitting or vice versa.
73 *
74 * We should bump the serial number of the drawable if canflip() returns
75 * something different to what is stored here, so that the DRI2 buffers
76 * will get re-allocated.
77 */
78 int previous_canflip;
79
Rob Clark4b8f30a2011-08-28 12:51:26 -050080} OMAPDRI2BufferRec, *OMAPDRI2BufferPtr;
81
82#define OMAPBUF(p) ((OMAPDRI2BufferPtr)(p))
83#define DRIBUF(p) ((DRI2BufferPtr)(&(p)->base))
84
85
Rob Clark4b8f30a2011-08-28 12:51:26 -050086static inline DrawablePtr
87dri2draw(DrawablePtr pDraw, DRI2BufferPtr buf)
88{
89 if (buf->attachment == DRI2BufferFrontLeft) {
90 return pDraw;
91 } else {
92 return &(OMAPBUF(buf)->pPixmap->drawable);
93 }
94}
95
Rob Clark4b8f30a2011-08-28 12:51:26 -050096static Bool
97canflip(DrawablePtr pDraw)
98{
Dave Barnishc50baf52012-11-29 14:39:36 +000099 ScreenPtr pScreen = pDraw->pScreen;
100 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
101 OMAPPtr pOMAP = OMAPPTR(pScrn);
102
103 if( pOMAP->NoFlip ) {
104 /* flipping is disabled by user option */
105 return FALSE;
106 } else {
107 return (pDraw->type == DRAWABLE_WINDOW) &&
108 DRI2CanFlip(pDraw);
109 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500110}
111
112static inline Bool
113exchangebufs(DrawablePtr pDraw, DRI2BufferPtr a, DRI2BufferPtr b)
114{
David Garbettae5a6362012-07-02 10:15:47 +0100115 PixmapPtr aPix = draw2pix(dri2draw(pDraw, a));
116 PixmapPtr bPix = draw2pix(dri2draw(pDraw, b));
117
118 OMAPPixmapExchange(aPix,bPix);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500119 exchange(a->name, b->name);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500120 return TRUE;
121}
122
123static PixmapPtr
124createpix(DrawablePtr pDraw)
125{
126 ScreenPtr pScreen = pDraw->pScreen;
127 int flags = canflip(pDraw) ? OMAP_CREATE_PIXMAP_SCANOUT : 0;
128 return pScreen->CreatePixmap(pScreen,
129 pDraw->width, pDraw->height, pDraw->depth, flags);
130}
131
132/**
133 * Create Buffer.
134 *
135 * Note that 'format' is used from the client side to specify the DRI buffer
136 * format, which could differ from the drawable format. For example, the
137 * drawable could be 32b RGB, but the DRI buffer some YUV format (video) or
138 * perhaps lower bit depth RGB (GL). The color conversion is handled when
139 * blitting to front buffer, and page-flipping (overlay or flipchain) can
140 * only be used if the display supports.
141 */
142static DRI2BufferPtr
143OMAPDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment,
144 unsigned int format)
145{
146 ScreenPtr pScreen = pDraw->pScreen;
147 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark4b8f30a2011-08-28 12:51:26 -0500148 OMAPDRI2BufferPtr buf = calloc(1, sizeof(*buf));
Ray Smith9a3797b2013-03-15 15:33:04 +0000149 PixmapPtr pPixmap = NULL;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500150 struct omap_bo *bo;
151 int ret;
152
153 DEBUG_MSG("pDraw=%p, attachment=%d, format=%08x",
154 pDraw, attachment, format);
155
156 if (!buf) {
Ray Smith9a3797b2013-03-15 15:33:04 +0000157 ERROR_MSG("Couldn't allocate internal buffer structure");
Rob Clark4b8f30a2011-08-28 12:51:26 -0500158 return NULL;
159 }
160
161 if (attachment == DRI2BufferFrontLeft) {
162 pPixmap = draw2pix(pDraw);
163
Raymond Smith2b4620b2012-05-01 12:00:41 +0100164
Dave Barnish2742d152013-03-13 13:36:58 +0000165/* 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 +0100166 * buffers are scanout-able we'll not bother allocating *another* scanout buffer and just use the one we already have
167 * and save that extra buffer size */
168#if 0
Dave Barnish2742d152013-03-13 13:36:58 +0000169 /* to do flipping, if we don't have DMM, then we need a scanout
170 * capable (physically contiguous) buffer.. this bit of gymnastics
171 * ensures that.
172 */
Rob Clark834f6462012-04-20 15:40:51 -0500173 if (canflip(pDraw) && !has_dmm(pOMAP) &&
174 (OMAPPixmapBo(pPixmap) != pOMAP->scanout)) {
175
Rob Clark4b8f30a2011-08-28 12:51:26 -0500176 /* need to re-allocate pixmap to get a scanout capable buffer */
177 PixmapPtr pNewPix = createpix(pDraw);
178
Rob Clark4b8f30a2011-08-28 12:51:26 -0500179 OMAPPixmapExchange(pPixmap, pNewPix);
180
181 pScreen->DestroyPixmap(pNewPix);
182 }
Raymond Smith2b4620b2012-05-01 12:00:41 +0100183#endif
Rob Clark0bdd3702012-04-20 14:47:51 -0500184
185 pPixmap->refcnt++;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500186 } else {
187 pPixmap = createpix(pDraw);
188 }
189
Ray Smith2bc3bf62013-03-15 12:05:08 +0000190 if (!pPixmap)
191 {
192 assert(attachment != DRI2BufferFrontLeft);
193 ERROR_MSG("Failed to create back buffer for window");
Ray Smith9a3797b2013-03-15 15:33:04 +0000194 goto fail;
Ray Smith2bc3bf62013-03-15 12:05:08 +0000195 }
196
Rob Clark4b8f30a2011-08-28 12:51:26 -0500197 bo = OMAPPixmapBo(pPixmap);
Raymond Smithd15a7342012-05-01 12:01:52 +0100198 if (!bo)
199 {
200 ERROR_MSG("Attempting to DRI2 wrap a pixmap with no DRM buffer object backing");
Ray Smith9a3797b2013-03-15 15:33:04 +0000201 goto fail;
Raymond Smithd15a7342012-05-01 12:01:52 +0100202 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500203
204 DRIBUF(buf)->attachment = attachment;
205 DRIBUF(buf)->pitch = exaGetPixmapPitch(pPixmap);
206 DRIBUF(buf)->cpp = pPixmap->drawable.bitsPerPixel / 8;
207 DRIBUF(buf)->format = format;
Raymond Smith2f93cb12012-05-10 07:41:34 +0100208 DRIBUF(buf)->flags = 0;
Rob Clark0bdd3702012-04-20 14:47:51 -0500209 buf->refcnt = 1;
210 buf->pPixmap = pPixmap;
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100211 buf->previous_canflip = -1;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500212
213 ret = omap_bo_get_name(bo, &DRIBUF(buf)->name);
214 if (ret) {
215 ERROR_MSG("could not get buffer name: %d", ret);
Ray Smith9a3797b2013-03-15 15:33:04 +0000216 goto fail;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500217 }
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);
Ray Smith9a3797b2013-03-15 15:33:04 +0000237
238fail:
239 if (pPixmap != NULL)
240 {
241 if (attachment != DRI2BufferFrontLeft)
242 {
243 pScreen->DestroyPixmap(pPixmap);
244 }
245 else
246 {
247 pPixmap->refcnt--;
248 }
249 }
250 free(buf);
251
252 return NULL;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500253}
254
255/**
256 * Destroy Buffer
257 *
Dave Barnish2742d152013-03-13 13:36:58 +0000258 * TODO: MIDEGL-1464: Depending on how flipping ends up working, we may need a refcnt or
Rob Clark4b8f30a2011-08-28 12:51:26 -0500259 * something like this to defer destroying a buffer that is currently being
260 * scanned out..
261 */
262static void
263OMAPDRI2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer)
264{
Rob Clark0bdd3702012-04-20 14:47:51 -0500265 OMAPDRI2BufferPtr buf = OMAPBUF(buffer);
266 /* Note: pDraw may already be deleted, so use the pPixmap here
267 * instead (since it is at least refcntd)
268 */
269 ScreenPtr pScreen = buf->pPixmap->drawable.pScreen;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500270 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark0bdd3702012-04-20 14:47:51 -0500271
272 if (--buf->refcnt > 0)
273 return;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500274
275 DEBUG_MSG("pDraw=%p, buffer=%p", pDraw, buffer);
276
David Garbettae5a6362012-07-02 10:15:47 +0100277 OMAPDeregisterExternalAccess(buf->pPixmap);
278
Rob Clark0bdd3702012-04-20 14:47:51 -0500279 pScreen->DestroyPixmap(buf->pPixmap);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500280
281 free(buf);
282}
283
Rob Clark0bdd3702012-04-20 14:47:51 -0500284static void
285OMAPDRI2ReferenceBuffer(DRI2BufferPtr buffer)
286{
287 OMAPDRI2BufferPtr buf = OMAPBUF(buffer);
288 buf->refcnt++;
289}
290
Rob Clark4b8f30a2011-08-28 12:51:26 -0500291/**
292 *
293 */
294static void
295OMAPDRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
296 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
297{
298 ScreenPtr pScreen = pDraw->pScreen;
299 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
300 DrawablePtr pSrcDraw = dri2draw(pDraw, pSrcBuffer);
301 DrawablePtr pDstDraw = dri2draw(pDraw, pDstBuffer);
302 RegionPtr pCopyClip;
303 GCPtr pGC;
304
305 DEBUG_MSG("pDraw=%p, pDstBuffer=%p (%p), pSrcBuffer=%p (%p)",
306 pDraw, pDstBuffer, pSrcDraw, pSrcBuffer, pDstDraw);
307
308 pGC = GetScratchGC(pDstDraw->depth, pScreen);
309 if (!pGC) {
310 return;
311 }
312
313 pCopyClip = REGION_CREATE(pScreen, NULL, 0);
314 RegionCopy(pCopyClip, pRegion);
315 (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pCopyClip, 0);
316 ValidateGC(pDstDraw, pGC);
317
318 /* If the dst is the framebuffer, and we had a way to
319 * schedule a deferred blit synchronized w/ vsync, that
320 * would be a nice thing to do utilize here to avoid
321 * tearing.. when we have sync object support for GEM
322 * buffers, I think we could do something more clever
323 * here.
324 */
325
326 pGC->ops->CopyArea(pSrcDraw, pDstDraw, pGC,
327 0, 0, pDraw->width, pDraw->height, 0, 0);
328
Rob Clarke450d412012-01-08 19:33:48 -0600329 FreeScratchGC(pGC);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500330}
331
332/**
333 * Get current frame count and frame count timestamp, based on drawable's
334 * crtc.
335 */
336static int
337OMAPDRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc)
338{
339 ScreenPtr pScreen = pDraw->pScreen;
340 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
341 OMAPPtr pOMAP = OMAPPTR(pScrn);
342 drmVBlank vbl = { .request = {
343 .type = DRM_VBLANK_RELATIVE,
344 .sequence = 0,
345 } };
346 int ret;
347
348 ret = drmWaitVBlank(pOMAP->drmFD, &vbl);
349 if (ret) {
350 static int limit = 5;
351 if (limit) {
352 ERROR_MSG("get vblank counter failed: %s", strerror(errno));
353 limit--;
354 }
355 return FALSE;
356 }
357
358 if (ust) {
359 *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
360 }
361 if (msc) {
362 *msc = vbl.reply.sequence;
363 }
364
365 return TRUE;
366}
367
John Sheu022833e2012-08-15 11:40:11 -0700368#define OMAP_SWAP_FAKE_FLIP (1 << 0)
369#define OMAP_SWAP_FAIL (1 << 1)
370
Rob Clark4b8f30a2011-08-28 12:51:26 -0500371struct _OMAPDRISwapCmd {
Rob Clarka6762ef2012-04-12 17:38:39 -0500372 int type;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500373 ClientPtr client;
Rob Clark0bdd3702012-04-20 14:47:51 -0500374 ScreenPtr pScreen;
375 /* Note: store drawable ID, rather than drawable. It's possible that
376 * the drawable can be destroyed while we wait for page flip event:
377 */
378 XID draw_id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500379 DRI2BufferPtr pDstBuffer;
380 DRI2BufferPtr pSrcBuffer;
381 DRI2SwapEventPtr func;
John Sheu022833e2012-08-15 11:40:11 -0700382 int swapCount;
383 int flags;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500384 void *data;
385};
386
Rob Clark0bdd3702012-04-20 14:47:51 -0500387static const char *swap_names[] = {
388 [DRI2_EXCHANGE_COMPLETE] = "exchange",
389 [DRI2_BLIT_COMPLETE] = "blit",
390 [DRI2_FLIP_COMPLETE] = "flip,"
391};
392
Rob Clark4b8f30a2011-08-28 12:51:26 -0500393void
394OMAPDRI2SwapComplete(OMAPDRISwapCmd *cmd)
395{
Rob Clark0bdd3702012-04-20 14:47:51 -0500396 ScreenPtr pScreen = cmd->pScreen;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500397 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark67b875f2012-04-20 19:13:57 -0500398 OMAPPtr pOMAP = OMAPPTR(pScrn);
Rob Clark0bdd3702012-04-20 14:47:51 -0500399 DrawablePtr pDraw = NULL;
400 int status;
Sean Paul269c9712012-09-04 15:17:33 -0700401 OMAPPixmapPrivPtr src_priv, dst_priv;
402 struct omap_bo *old_src_bo, *old_dst_bo;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500403
John Sheu022833e2012-08-15 11:40:11 -0700404 if (--cmd->swapCount > 0)
405 return;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500406
Sean Paul269c9712012-09-04 15:17:33 -0700407 /* Save the old source bo for unreference below */
408 src_priv = exaGetPixmapDriverPrivate(OMAPBUF(cmd->pSrcBuffer)->pPixmap);
409 dst_priv = exaGetPixmapDriverPrivate(OMAPBUF(cmd->pDstBuffer)->pPixmap);
410 old_src_bo = src_priv->bo;
411 old_dst_bo = dst_priv->bo;
412
John Sheu022833e2012-08-15 11:40:11 -0700413 if ((cmd->flags & OMAP_SWAP_FAIL) == 0) {
414 DEBUG_MSG("%s complete: %d -> %d", swap_names[cmd->type],
415 cmd->pSrcBuffer->attachment, cmd->pDstBuffer->attachment);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500416
John Sheu022833e2012-08-15 11:40:11 -0700417 status = dixLookupDrawable(&pDraw, cmd->draw_id, serverClient,
418 M_ANY, DixWriteAccess);
419
420 if (status == Success) {
421 if (cmd->type != DRI2_BLIT_COMPLETE && (cmd->flags & OMAP_SWAP_FAKE_FLIP) == 0) {
422 assert(cmd->type == DRI2_FLIP_COMPLETE);
423 exchangebufs(pDraw, cmd->pSrcBuffer, cmd->pDstBuffer);
424 }
425
426 DRI2SwapComplete(cmd->client, pDraw, 0, 0, 0, cmd->type,
427 cmd->func, cmd->data);
428
429 if (cmd->type != DRI2_BLIT_COMPLETE && (cmd->flags & OMAP_SWAP_FAKE_FLIP) == 0) {
430 dst_priv = exaGetPixmapDriverPrivate(draw2pix(dri2draw(pDraw, cmd->pDstBuffer)));
431 assert(cmd->type == DRI2_FLIP_COMPLETE);
432 set_scanout_bo(pScrn, dst_priv->bo);
433 }
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100434 }
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100435 }
David Garbett3688b332012-05-11 12:17:34 +0100436
Rob Clark0bdd3702012-04-20 14:47:51 -0500437 /* drop extra refcnt we obtained prior to swap:
438 */
439 OMAPDRI2DestroyBuffer(pDraw, cmd->pSrcBuffer);
440 OMAPDRI2DestroyBuffer(pDraw, cmd->pDstBuffer);
Sean Paul269c9712012-09-04 15:17:33 -0700441 omap_bo_unreference(old_src_bo);
442 omap_bo_unreference(old_dst_bo);
Rob Clark67b875f2012-04-20 19:13:57 -0500443 pOMAP->pending_flips--;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500444
445 free(cmd);
446}
447
448/**
449 * ScheduleSwap is responsible for requesting a DRM vblank event for the
450 * appropriate frame.
451 *
452 * In the case of a blit (e.g. for a windowed swap) or buffer exchange,
453 * the vblank requested can simply be the last queued swap frame + the swap
454 * interval for the drawable.
455 *
456 * In the case of a page flip, we request an event for the last queued swap
457 * frame + swap interval - 1, since we'll need to queue the flip for the frame
458 * immediately following the received event.
459 */
460static int
461OMAPDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
462 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer,
463 CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
464 DRI2SwapEventPtr func, void *data)
465{
466 ScreenPtr pScreen = pDraw->pScreen;
467 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark67b875f2012-04-20 19:13:57 -0500468 OMAPPtr pOMAP = OMAPPTR(pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500469 OMAPDRI2BufferPtr src = OMAPBUF(pSrcBuffer);
470 OMAPDRI2BufferPtr dst = OMAPBUF(pDstBuffer);
471 OMAPDRISwapCmd *cmd = calloc(1, sizeof(*cmd));
David Garbett7d6a6e72012-05-11 11:52:45 +0100472 int src_fb_id, dst_fb_id;
473 OMAPPixmapPrivPtr src_priv, dst_priv;
John Sheu022833e2012-08-15 11:40:11 -0700474 int new_canflip, ret;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500475
476 cmd->client = client;
Rob Clark0bdd3702012-04-20 14:47:51 -0500477 cmd->pScreen = pScreen;
478 cmd->draw_id = pDraw->id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500479 cmd->pSrcBuffer = pSrcBuffer;
480 cmd->pDstBuffer = pDstBuffer;
John Sheu022833e2012-08-15 11:40:11 -0700481 cmd->swapCount = 0;
482 cmd->flags = 0;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500483 cmd->func = func;
484 cmd->data = data;
485
486 DEBUG_MSG("%d -> %d", pSrcBuffer->attachment, pDstBuffer->attachment);
487
Rob Clark0bdd3702012-04-20 14:47:51 -0500488 /* obtain extra ref on buffers to avoid them going away while we await
489 * the page flip event:
490 */
491 OMAPDRI2ReferenceBuffer(pSrcBuffer);
492 OMAPDRI2ReferenceBuffer(pDstBuffer);
Rob Clark67b875f2012-04-20 19:13:57 -0500493 pOMAP->pending_flips++;
Rob Clark0bdd3702012-04-20 14:47:51 -0500494
David Garbett7d6a6e72012-05-11 11:52:45 +0100495 src_priv = exaGetPixmapDriverPrivate(src->pPixmap);
496 dst_priv = exaGetPixmapDriverPrivate(dst->pPixmap);
497
498 src_fb_id = omap_bo_get_fb(src_priv->bo);
499 dst_fb_id = omap_bo_get_fb(dst_priv->bo);
500
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100501 new_canflip = canflip(pDraw);
502 if ((src->previous_canflip != -1 && src->previous_canflip != new_canflip) ||
Shirish S29e4a232012-07-13 19:34:24 -0700503 (dst->previous_canflip != -1 && dst->previous_canflip != new_canflip) ||
504 (pOMAP->has_resized))
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100505 {
506 /* The drawable has transitioned between being flippable and non-flippable
507 * or vice versa. Bump the serial number to force the DRI2 buffers to be
508 * re-allocated during the next frame so that:
509 * - It is able to be scanned out (if drawable is now flippable), or
510 * - It is not taking up possibly scarce scanout-able memory (if drawable
511 * is now not flippable)
Shirish S29e4a232012-07-13 19:34:24 -0700512 *
513 * has_resized: On hotplugging back buffer needs to be invalidates as well
514 * as Xsever invalidates only the front buffer.
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100515 */
516
517 PixmapPtr pPix = pScreen->GetWindowPixmap((WindowPtr)pDraw);
518 pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER;
519 }
520
521 src->previous_canflip = new_canflip;
522 dst->previous_canflip = new_canflip;
523
Sean Paul269c9712012-09-04 15:17:33 -0700524 omap_bo_reference(src_priv->bo);
525 omap_bo_reference(dst_priv->bo);
Shirish S29e4a232012-07-13 19:34:24 -0700526 if (src_fb_id && dst_fb_id && canflip(pDraw) && !(pOMAP->has_resized)) {
527 /* has_resized: On hotplug the fb size and crtc sizes arent updated
528 * hence on this event we do a copyb but flip from the next frame
529 * when the sizes are updated.
530 */
David Garbett7d6a6e72012-05-11 11:52:45 +0100531 DEBUG_MSG("can flip: %d -> %d", src_fb_id, dst_fb_id);
Rob Clarka6762ef2012-04-12 17:38:39 -0500532 cmd->type = DRI2_FLIP_COMPLETE;
Dave Barnish2742d152013-03-13 13:36:58 +0000533 /* TODO: MIDEGL-1461: Handle rollback if multiple CRTC flip is only partially successful
John Sheu022833e2012-08-15 11:40:11 -0700534 */
535 ret = drmmode_page_flip(pDraw, src_fb_id, cmd);
536
537 /* If using page flip events, we'll trigger an immediate completion in
538 * the case that no CRTCs were enabled to be flipped. If not using page
539 * flip events, trigger immediate completion unconditionally.
540 */
541 if (ret < 0) {
542 /*
543 * Error while flipping; bail.
544 */
545 cmd->flags |= OMAP_SWAP_FAIL;
Ray Smith3c33c3d2013-03-26 16:06:37 +0000546
547 if (pOMAP->drmmode->use_page_flip_events)
548 cmd->swapCount = -(ret + 1);
549 else
550 cmd->swapCount = 0;
551
John Sheu022833e2012-08-15 11:40:11 -0700552 if (cmd->swapCount == 0)
John Sheu022833e2012-08-15 11:40:11 -0700553 {
554 OMAPDRI2SwapComplete(cmd);
555 }
556 return FALSE;
557 } else {
558 if (ret == 0)
559 cmd->flags |= OMAP_SWAP_FAKE_FLIP;
Ray Smith3c33c3d2013-03-26 16:06:37 +0000560
561 if (pOMAP->drmmode->use_page_flip_events)
562 cmd->swapCount = ret;
563 else
564 cmd->swapCount = 0;
565
John Sheu022833e2012-08-15 11:40:11 -0700566 if (cmd->swapCount == 0)
John Sheu022833e2012-08-15 11:40:11 -0700567 {
568 OMAPDRI2SwapComplete(cmd);
569 }
570 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500571 } else {
572 /* fallback to blit: */
573 BoxRec box = {
574 .x1 = 0,
575 .y1 = 0,
576 .x2 = pDraw->width,
577 .y2 = pDraw->height,
578 };
579 RegionRec region;
580 RegionInit(&region, &box, 0);
581 OMAPDRI2CopyRegion(pDraw, &region, pDstBuffer, pSrcBuffer);
Rob Clarka6762ef2012-04-12 17:38:39 -0500582 cmd->type = DRI2_BLIT_COMPLETE;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500583 OMAPDRI2SwapComplete(cmd);
Shirish S29e4a232012-07-13 19:34:24 -0700584 pOMAP->has_resized = FALSE;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500585 }
586
587 return TRUE;
588}
589
590/**
591 * Request a DRM event when the requested conditions will be satisfied.
592 *
593 * We need to handle the event and ask the server to wake up the client when
594 * we receive it.
595 */
596static int
597OMAPDRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
598 CARD64 divisor, CARD64 remainder)
599{
600 ScreenPtr pScreen = pDraw->pScreen;
601 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
602// OMAPPtr pOMAP = OMAPPTR(pScrn);
603
604#if 0
605#endif
606 ERROR_MSG("not implemented");
607 return FALSE;
608}
609
610/**
611 * The DRI2 ScreenInit() function.. register our handler fxns w/ DRI2 core
612 */
613Bool
614OMAPDRI2ScreenInit(ScreenPtr pScreen)
615{
616 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
617 OMAPPtr pOMAP = OMAPPTR(pScrn);
618 DRI2InfoRec info = {
619 .version = 5,
620 .fd = pOMAP->drmFD,
John Sheub4344ae2012-06-15 17:44:24 -0700621 .driverName = "armsoc",
Rob Clark4b8f30a2011-08-28 12:51:26 -0500622 .deviceName = pOMAP->deviceName,
623 .CreateBuffer = OMAPDRI2CreateBuffer,
624 .DestroyBuffer = OMAPDRI2DestroyBuffer,
625 .CopyRegion = OMAPDRI2CopyRegion,
626 .ScheduleSwap = OMAPDRI2ScheduleSwap,
627 .ScheduleWaitMSC = OMAPDRI2ScheduleWaitMSC,
628 .GetMSC = OMAPDRI2GetMSC,
629 .AuthMagic = drmAuthMagic,
630 };
631 int minor = 1, major = 0;
632
633 if (xf86LoaderCheckSymbol("DRI2Version")) {
634 DRI2Version(&major, &minor);
635 }
636
637 if (minor < 1) {
638 WARNING_MSG("DRI2 requires DRI2 module version 1.1.0 or later");
639 return FALSE;
640 }
641
642 return DRI2ScreenInit(pScreen, &info);
643}
644
645/**
646 * The DRI2 CloseScreen() function.. unregister ourself w/ DRI2 core.
647 */
648void
649OMAPDRI2CloseScreen(ScreenPtr pScreen)
650{
Rob Clark67b875f2012-04-20 19:13:57 -0500651 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
652 OMAPPtr pOMAP = OMAPPTR(pScrn);
653 while (pOMAP->pending_flips > 0) {
654 DEBUG_MSG("waiting..");
655 drmmode_wait_for_event(pScrn);
656 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500657 DRI2CloseScreen(pScreen);
658}