blob: 5a51bf81ab9ca47d8fe332971599b6bd7a8f83a2 [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
44
45typedef struct {
46 DRI2BufferRec base;
47
Rob Clark99ab80d2012-04-12 17:38:07 -050048 /**
49 * Pixmap that is backing the buffer
50 *
51 * NOTE: don't track the pixmap ptr for the front buffer if it is
52 * a window.. this could get reallocated from beneath us, so we should
53 * always use draw2pix to be sure to have the correct one
54 */
Rob Clark4b8f30a2011-08-28 12:51:26 -050055 PixmapPtr pPixmap;
56
57 /**
Rob Clark0bdd3702012-04-20 14:47:51 -050058 * The DRI2 buffers are reference counted to avoid crashyness when the
59 * client detaches a dri2 drawable while we are still waiting for a
60 * page_flip event.
61 */
62 int refcnt;
63
Raymond Smith4a0c0aa2012-06-20 10:50:39 +010064 /**
65 * The value of canflip() for the previous frame. Used so that we can tell
66 * whether the buffer should be re-allocated, e.g into scanout-able
67 * memory if the buffer can now be flipped.
68 *
69 * We don't want to re-allocate every frame because it is unnecessary
70 * overhead most of the time apart from when we switch from flipping
71 * to blitting or vice versa.
72 *
73 * We should bump the serial number of the drawable if canflip() returns
74 * something different to what is stored here, so that the DRI2 buffers
75 * will get re-allocated.
76 */
77 int previous_canflip;
78
Rob Clark4b8f30a2011-08-28 12:51:26 -050079} OMAPDRI2BufferRec, *OMAPDRI2BufferPtr;
80
81#define OMAPBUF(p) ((OMAPDRI2BufferPtr)(p))
82#define DRIBUF(p) ((DRI2BufferPtr)(&(p)->base))
83
84
Rob Clark4b8f30a2011-08-28 12:51:26 -050085static inline DrawablePtr
86dri2draw(DrawablePtr pDraw, DRI2BufferPtr buf)
87{
88 if (buf->attachment == DRI2BufferFrontLeft) {
89 return pDraw;
90 } else {
91 return &(OMAPBUF(buf)->pPixmap->drawable);
92 }
93}
94
Rob Clark4b8f30a2011-08-28 12:51:26 -050095static Bool
96canflip(DrawablePtr pDraw)
97{
98 return (pDraw->type == DRAWABLE_WINDOW) &&
Rob Clark99ab80d2012-04-12 17:38:07 -050099 DRI2CanFlip(pDraw);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500100}
101
102static inline Bool
103exchangebufs(DrawablePtr pDraw, DRI2BufferPtr a, DRI2BufferPtr b)
104{
Rob Clark4b8f30a2011-08-28 12:51:26 -0500105 OMAPPixmapExchange(draw2pix(dri2draw(pDraw, a)),
106 draw2pix(dri2draw(pDraw, b)));
107 exchange(a->name, b->name);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500108 return TRUE;
109}
110
111static PixmapPtr
112createpix(DrawablePtr pDraw)
113{
114 ScreenPtr pScreen = pDraw->pScreen;
115 int flags = canflip(pDraw) ? OMAP_CREATE_PIXMAP_SCANOUT : 0;
116 return pScreen->CreatePixmap(pScreen,
117 pDraw->width, pDraw->height, pDraw->depth, flags);
118}
119
120/**
121 * Create Buffer.
122 *
123 * Note that 'format' is used from the client side to specify the DRI buffer
124 * format, which could differ from the drawable format. For example, the
125 * drawable could be 32b RGB, but the DRI buffer some YUV format (video) or
126 * perhaps lower bit depth RGB (GL). The color conversion is handled when
127 * blitting to front buffer, and page-flipping (overlay or flipchain) can
128 * only be used if the display supports.
129 */
130static DRI2BufferPtr
131OMAPDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment,
132 unsigned int format)
133{
134 ScreenPtr pScreen = pDraw->pScreen;
135 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
136 OMAPPtr pOMAP = OMAPPTR(pScrn);
137 OMAPDRI2BufferPtr buf = calloc(1, sizeof(*buf));
138 PixmapPtr pPixmap;
139 struct omap_bo *bo;
140 int ret;
141
142 DEBUG_MSG("pDraw=%p, attachment=%d, format=%08x",
143 pDraw, attachment, format);
144
145 if (!buf) {
146 return NULL;
147 }
148
149 if (attachment == DRI2BufferFrontLeft) {
150 pPixmap = draw2pix(pDraw);
151
Rob Clark834f6462012-04-20 15:40:51 -0500152 /* to do flipping, if we don't have DMM, then we need a scanout
153 * capable (physically contiguous) buffer.. this bit of gymnastics
154 * ensures that.
Rob Clark4b8f30a2011-08-28 12:51:26 -0500155 *
Rob Clark834f6462012-04-20 15:40:51 -0500156 * TODO we may want to re-allocate and switch back to non-scanout
Rob Clark4b8f30a2011-08-28 12:51:26 -0500157 * buffer when client disconnects from drawable..
158 */
Raymond Smith2b4620b2012-05-01 12:00:41 +0100159
160/* TODO: We don't have enough memory to allocate three physically contiguous buffers at the same time! Because all our
161 * buffers are scanout-able we'll not bother allocating *another* scanout buffer and just use the one we already have
162 * and save that extra buffer size */
163#if 0
Rob Clark834f6462012-04-20 15:40:51 -0500164 if (canflip(pDraw) && !has_dmm(pOMAP) &&
165 (OMAPPixmapBo(pPixmap) != pOMAP->scanout)) {
166
Rob Clark4b8f30a2011-08-28 12:51:26 -0500167 /* need to re-allocate pixmap to get a scanout capable buffer */
168 PixmapPtr pNewPix = createpix(pDraw);
169
170 // TODO copy contents..
171
172 OMAPPixmapExchange(pPixmap, pNewPix);
173
174 pScreen->DestroyPixmap(pNewPix);
175 }
Raymond Smith2b4620b2012-05-01 12:00:41 +0100176#endif
Rob Clark0bdd3702012-04-20 14:47:51 -0500177
178 pPixmap->refcnt++;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500179 } else {
180 pPixmap = createpix(pDraw);
181 }
182
183 bo = OMAPPixmapBo(pPixmap);
Raymond Smithd15a7342012-05-01 12:01:52 +0100184 if (!bo)
185 {
186 ERROR_MSG("Attempting to DRI2 wrap a pixmap with no DRM buffer object backing");
187 /* TODO: Returning NULL here ends up in a segfault all the way in pixman which has no backtrace. We get
188 * a more friendly segfault if we just let it be dereferenced in a few lines */
189 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500190
191 DRIBUF(buf)->attachment = attachment;
192 DRIBUF(buf)->pitch = exaGetPixmapPitch(pPixmap);
193 DRIBUF(buf)->cpp = pPixmap->drawable.bitsPerPixel / 8;
194 DRIBUF(buf)->format = format;
Raymond Smith2f93cb12012-05-10 07:41:34 +0100195 DRIBUF(buf)->flags = 0;
Rob Clark0bdd3702012-04-20 14:47:51 -0500196 buf->refcnt = 1;
197 buf->pPixmap = pPixmap;
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100198 buf->previous_canflip = -1;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500199
200 ret = omap_bo_get_name(bo, &DRIBUF(buf)->name);
201 if (ret) {
202 ERROR_MSG("could not get buffer name: %d", ret);
203 /* TODO cleanup */
204 return NULL;
205 }
206
Rob Clark4b8f30a2011-08-28 12:51:26 -0500207 /* Q: how to know across OMAP generations what formats that the display
208 * can support directly?
209 * A: attempt to create a drm_framebuffer, and if that fails then the
David Garbett7d6a6e72012-05-11 11:52:45 +0100210 * hw must not support.. then fall back to blitting
Rob Clark4b8f30a2011-08-28 12:51:26 -0500211 */
David Garbett7d6a6e72012-05-11 11:52:45 +0100212 if (canflip(pDraw) && attachment != DRI2BufferFrontLeft) {
213 uint32_t new_fb_id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500214 int ret = drmModeAddFB(pOMAP->drmFD, pDraw->width, pDraw->height,
215 pDraw->depth, pDraw->bitsPerPixel, DRIBUF(buf)->pitch,
David Garbett7d6a6e72012-05-11 11:52:45 +0100216 omap_bo_handle(bo), &new_fb_id);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500217 if (ret) {
218 /* to-bad, so-sad, we can't flip */
219 WARNING_MSG("could not create fb: %d", ret);
David Garbett7d6a6e72012-05-11 11:52:45 +0100220 } else {
221 omap_bo_set_fb(bo, new_fb_id);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500222 }
223 }
224
225 return DRIBUF(buf);
226}
227
228/**
229 * Destroy Buffer
230 *
231 * TODO: depending on how flipping ends up working, we may need a refcnt or
232 * something like this to defer destroying a buffer that is currently being
233 * scanned out..
234 */
235static void
236OMAPDRI2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer)
237{
Rob Clark0bdd3702012-04-20 14:47:51 -0500238 OMAPDRI2BufferPtr buf = OMAPBUF(buffer);
239 /* Note: pDraw may already be deleted, so use the pPixmap here
240 * instead (since it is at least refcntd)
241 */
242 ScreenPtr pScreen = buf->pPixmap->drawable.pScreen;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500243 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark0bdd3702012-04-20 14:47:51 -0500244
245 if (--buf->refcnt > 0)
246 return;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500247
248 DEBUG_MSG("pDraw=%p, buffer=%p", pDraw, buffer);
249
Rob Clark0bdd3702012-04-20 14:47:51 -0500250 pScreen->DestroyPixmap(buf->pPixmap);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500251
252 free(buf);
253}
254
Rob Clark0bdd3702012-04-20 14:47:51 -0500255static void
256OMAPDRI2ReferenceBuffer(DRI2BufferPtr buffer)
257{
258 OMAPDRI2BufferPtr buf = OMAPBUF(buffer);
259 buf->refcnt++;
260}
261
Rob Clark4b8f30a2011-08-28 12:51:26 -0500262/**
263 *
264 */
265static void
266OMAPDRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
267 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
268{
269 ScreenPtr pScreen = pDraw->pScreen;
270 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
271 DrawablePtr pSrcDraw = dri2draw(pDraw, pSrcBuffer);
272 DrawablePtr pDstDraw = dri2draw(pDraw, pDstBuffer);
273 RegionPtr pCopyClip;
274 GCPtr pGC;
275
276 DEBUG_MSG("pDraw=%p, pDstBuffer=%p (%p), pSrcBuffer=%p (%p)",
277 pDraw, pDstBuffer, pSrcDraw, pSrcBuffer, pDstDraw);
278
279 pGC = GetScratchGC(pDstDraw->depth, pScreen);
280 if (!pGC) {
281 return;
282 }
283
284 pCopyClip = REGION_CREATE(pScreen, NULL, 0);
285 RegionCopy(pCopyClip, pRegion);
286 (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pCopyClip, 0);
287 ValidateGC(pDstDraw, pGC);
288
289 /* If the dst is the framebuffer, and we had a way to
290 * schedule a deferred blit synchronized w/ vsync, that
291 * would be a nice thing to do utilize here to avoid
292 * tearing.. when we have sync object support for GEM
293 * buffers, I think we could do something more clever
294 * here.
295 */
296
297 pGC->ops->CopyArea(pSrcDraw, pDstDraw, pGC,
298 0, 0, pDraw->width, pDraw->height, 0, 0);
299
Rob Clarke450d412012-01-08 19:33:48 -0600300 FreeScratchGC(pGC);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500301}
302
303/**
304 * Get current frame count and frame count timestamp, based on drawable's
305 * crtc.
306 */
307static int
308OMAPDRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc)
309{
310 ScreenPtr pScreen = pDraw->pScreen;
311 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
312 OMAPPtr pOMAP = OMAPPTR(pScrn);
313 drmVBlank vbl = { .request = {
314 .type = DRM_VBLANK_RELATIVE,
315 .sequence = 0,
316 } };
317 int ret;
318
319 ret = drmWaitVBlank(pOMAP->drmFD, &vbl);
320 if (ret) {
321 static int limit = 5;
322 if (limit) {
323 ERROR_MSG("get vblank counter failed: %s", strerror(errno));
324 limit--;
325 }
326 return FALSE;
327 }
328
329 if (ust) {
330 *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
331 }
332 if (msc) {
333 *msc = vbl.reply.sequence;
334 }
335
336 return TRUE;
337}
338
339struct _OMAPDRISwapCmd {
Rob Clarka6762ef2012-04-12 17:38:39 -0500340 int type;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500341 ClientPtr client;
Rob Clark0bdd3702012-04-20 14:47:51 -0500342 ScreenPtr pScreen;
343 /* Note: store drawable ID, rather than drawable. It's possible that
344 * the drawable can be destroyed while we wait for page flip event:
345 */
346 XID draw_id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500347 DRI2BufferPtr pDstBuffer;
348 DRI2BufferPtr pSrcBuffer;
349 DRI2SwapEventPtr func;
350 void *data;
351};
352
Rob Clark0bdd3702012-04-20 14:47:51 -0500353static const char *swap_names[] = {
354 [DRI2_EXCHANGE_COMPLETE] = "exchange",
355 [DRI2_BLIT_COMPLETE] = "blit",
356 [DRI2_FLIP_COMPLETE] = "flip,"
357};
358
Rob Clark4b8f30a2011-08-28 12:51:26 -0500359void
360OMAPDRI2SwapComplete(OMAPDRISwapCmd *cmd)
361{
Rob Clark0bdd3702012-04-20 14:47:51 -0500362 ScreenPtr pScreen = cmd->pScreen;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500363 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark67b875f2012-04-20 19:13:57 -0500364 OMAPPtr pOMAP = OMAPPTR(pScrn);
Rob Clark0bdd3702012-04-20 14:47:51 -0500365 DrawablePtr pDraw = NULL;
366 int status;
David Garbett3688b332012-05-11 12:17:34 +0100367 OMAPPixmapPrivPtr dst_priv;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500368
Rob Clark0bdd3702012-04-20 14:47:51 -0500369 DEBUG_MSG("%s complete: %d -> %d", swap_names[cmd->type],
370 cmd->pSrcBuffer->attachment, cmd->pDstBuffer->attachment);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500371
Rob Clark0bdd3702012-04-20 14:47:51 -0500372 status = dixLookupDrawable(&pDraw, cmd->draw_id, serverClient,
373 M_ANY, DixWriteAccess);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500374
Rob Clark0bdd3702012-04-20 14:47:51 -0500375 if (status == Success) {
376 if (cmd->type != DRI2_BLIT_COMPLETE)
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100377 {
378 assert(cmd->type == DRI2_FLIP_COMPLETE);
Rob Clark0bdd3702012-04-20 14:47:51 -0500379 exchangebufs(pDraw, cmd->pSrcBuffer, cmd->pDstBuffer);
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100380 }
Rob Clark0bdd3702012-04-20 14:47:51 -0500381
382 DRI2SwapComplete(cmd->client, pDraw, 0, 0, 0, cmd->type,
383 cmd->func, cmd->data);
384 }
385
David Garbett3688b332012-05-11 12:17:34 +0100386 dst_priv = exaGetPixmapDriverPrivate(draw2pix(dri2draw(pDraw, cmd->pDstBuffer)));
387
Raymond Smith8487a8a2012-05-22 15:07:26 +0100388 if (cmd->type != DRI2_BLIT_COMPLETE)
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100389 {
390 assert(cmd->type == DRI2_FLIP_COMPLETE);
Raymond Smith8487a8a2012-05-22 15:07:26 +0100391 set_scanout_bo(pScrn, dst_priv->bo);
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100392 }
David Garbett3688b332012-05-11 12:17:34 +0100393
Rob Clark0bdd3702012-04-20 14:47:51 -0500394 /* drop extra refcnt we obtained prior to swap:
395 */
396 OMAPDRI2DestroyBuffer(pDraw, cmd->pSrcBuffer);
397 OMAPDRI2DestroyBuffer(pDraw, cmd->pDstBuffer);
Rob Clark67b875f2012-04-20 19:13:57 -0500398 pOMAP->pending_flips--;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500399
400 free(cmd);
401}
402
403/**
404 * ScheduleSwap is responsible for requesting a DRM vblank event for the
405 * appropriate frame.
406 *
407 * In the case of a blit (e.g. for a windowed swap) or buffer exchange,
408 * the vblank requested can simply be the last queued swap frame + the swap
409 * interval for the drawable.
410 *
411 * In the case of a page flip, we request an event for the last queued swap
412 * frame + swap interval - 1, since we'll need to queue the flip for the frame
413 * immediately following the received event.
414 */
415static int
416OMAPDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
417 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer,
418 CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
419 DRI2SwapEventPtr func, void *data)
420{
421 ScreenPtr pScreen = pDraw->pScreen;
422 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark67b875f2012-04-20 19:13:57 -0500423 OMAPPtr pOMAP = OMAPPTR(pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500424 OMAPDRI2BufferPtr src = OMAPBUF(pSrcBuffer);
425 OMAPDRI2BufferPtr dst = OMAPBUF(pDstBuffer);
426 OMAPDRISwapCmd *cmd = calloc(1, sizeof(*cmd));
David Garbett7d6a6e72012-05-11 11:52:45 +0100427 int src_fb_id, dst_fb_id;
428 OMAPPixmapPrivPtr src_priv, dst_priv;
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100429 int new_canflip;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500430
431 cmd->client = client;
Rob Clark0bdd3702012-04-20 14:47:51 -0500432 cmd->pScreen = pScreen;
433 cmd->draw_id = pDraw->id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500434 cmd->pSrcBuffer = pSrcBuffer;
435 cmd->pDstBuffer = pDstBuffer;
436 cmd->func = func;
437 cmd->data = data;
438
439 DEBUG_MSG("%d -> %d", pSrcBuffer->attachment, pDstBuffer->attachment);
440
Rob Clark0bdd3702012-04-20 14:47:51 -0500441 /* obtain extra ref on buffers to avoid them going away while we await
442 * the page flip event:
443 */
444 OMAPDRI2ReferenceBuffer(pSrcBuffer);
445 OMAPDRI2ReferenceBuffer(pDstBuffer);
Rob Clark67b875f2012-04-20 19:13:57 -0500446 pOMAP->pending_flips++;
Rob Clark0bdd3702012-04-20 14:47:51 -0500447
David Garbett7d6a6e72012-05-11 11:52:45 +0100448 src_priv = exaGetPixmapDriverPrivate(src->pPixmap);
449 dst_priv = exaGetPixmapDriverPrivate(dst->pPixmap);
450
451 src_fb_id = omap_bo_get_fb(src_priv->bo);
452 dst_fb_id = omap_bo_get_fb(dst_priv->bo);
453
Raymond Smith4a0c0aa2012-06-20 10:50:39 +0100454 new_canflip = canflip(pDraw);
455 if ((src->previous_canflip != -1 && src->previous_canflip != new_canflip) ||
456 (dst->previous_canflip != -1 && dst->previous_canflip != new_canflip))
457 {
458 /* The drawable has transitioned between being flippable and non-flippable
459 * or vice versa. Bump the serial number to force the DRI2 buffers to be
460 * re-allocated during the next frame so that:
461 * - It is able to be scanned out (if drawable is now flippable), or
462 * - It is not taking up possibly scarce scanout-able memory (if drawable
463 * is now not flippable)
464 */
465
466 PixmapPtr pPix = pScreen->GetWindowPixmap((WindowPtr)pDraw);
467 pPix->drawable.serialNumber = NEXT_SERIAL_NUMBER;
468 }
469
470 src->previous_canflip = new_canflip;
471 dst->previous_canflip = new_canflip;
472
David Garbetta04b7052012-05-09 18:00:48 +0100473 if (src_fb_id && dst_fb_id && canflip(pDraw)) {
David Garbett7d6a6e72012-05-11 11:52:45 +0100474 DEBUG_MSG("can flip: %d -> %d", src_fb_id, dst_fb_id);
Rob Clarka6762ef2012-04-12 17:38:39 -0500475 cmd->type = DRI2_FLIP_COMPLETE;
David Garbett7d6a6e72012-05-11 11:52:45 +0100476 drmmode_page_flip(pDraw, src_fb_id, cmd);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500477 } else {
478 /* fallback to blit: */
479 BoxRec box = {
480 .x1 = 0,
481 .y1 = 0,
482 .x2 = pDraw->width,
483 .y2 = pDraw->height,
484 };
485 RegionRec region;
486 RegionInit(&region, &box, 0);
487 OMAPDRI2CopyRegion(pDraw, &region, pDstBuffer, pSrcBuffer);
Rob Clarka6762ef2012-04-12 17:38:39 -0500488 cmd->type = DRI2_BLIT_COMPLETE;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500489 OMAPDRI2SwapComplete(cmd);
490 }
491
492 return TRUE;
493}
494
495/**
496 * Request a DRM event when the requested conditions will be satisfied.
497 *
498 * We need to handle the event and ask the server to wake up the client when
499 * we receive it.
500 */
501static int
502OMAPDRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
503 CARD64 divisor, CARD64 remainder)
504{
505 ScreenPtr pScreen = pDraw->pScreen;
506 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
507// OMAPPtr pOMAP = OMAPPTR(pScrn);
508
509#if 0
510#endif
511 ERROR_MSG("not implemented");
512 return FALSE;
513}
514
515/**
516 * The DRI2 ScreenInit() function.. register our handler fxns w/ DRI2 core
517 */
518Bool
519OMAPDRI2ScreenInit(ScreenPtr pScreen)
520{
521 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
522 OMAPPtr pOMAP = OMAPPTR(pScrn);
523 DRI2InfoRec info = {
524 .version = 5,
525 .fd = pOMAP->drmFD,
526 .driverName = "omap",
527 .deviceName = pOMAP->deviceName,
528 .CreateBuffer = OMAPDRI2CreateBuffer,
529 .DestroyBuffer = OMAPDRI2DestroyBuffer,
530 .CopyRegion = OMAPDRI2CopyRegion,
531 .ScheduleSwap = OMAPDRI2ScheduleSwap,
532 .ScheduleWaitMSC = OMAPDRI2ScheduleWaitMSC,
533 .GetMSC = OMAPDRI2GetMSC,
534 .AuthMagic = drmAuthMagic,
535 };
536 int minor = 1, major = 0;
537
538 if (xf86LoaderCheckSymbol("DRI2Version")) {
539 DRI2Version(&major, &minor);
540 }
541
542 if (minor < 1) {
543 WARNING_MSG("DRI2 requires DRI2 module version 1.1.0 or later");
544 return FALSE;
545 }
546
547 return DRI2ScreenInit(pScreen, &info);
548}
549
550/**
551 * The DRI2 CloseScreen() function.. unregister ourself w/ DRI2 core.
552 */
553void
554OMAPDRI2CloseScreen(ScreenPtr pScreen)
555{
Rob Clark67b875f2012-04-20 19:13:57 -0500556 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
557 OMAPPtr pOMAP = OMAPPTR(pScrn);
558 while (pOMAP->pending_flips > 0) {
559 DEBUG_MSG("waiting..");
560 drmmode_wait_for_event(pScrn);
561 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500562 DRI2CloseScreen(pScreen);
563}