blob: 1ab48e04f64371895eba29f0b4fd68e22dd73c2b [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 /**
58 * The drm_framebuffer id for the buffer.. or 0 if the buffer cannot be
59 * directly scanned out by the hw (in which case we need to fall back to
60 * blitting)
61 */
62 uint32_t fb_id;
63
Rob Clark0bdd3702012-04-20 14:47:51 -050064 /**
65 * The DRI2 buffers are reference counted to avoid crashyness when the
66 * client detaches a dri2 drawable while we are still waiting for a
67 * page_flip event.
68 */
69 int refcnt;
70
Rob Clark4b8f30a2011-08-28 12:51:26 -050071} OMAPDRI2BufferRec, *OMAPDRI2BufferPtr;
72
73#define OMAPBUF(p) ((OMAPDRI2BufferPtr)(p))
74#define DRIBUF(p) ((DRI2BufferPtr)(&(p)->base))
75
76
Rob Clark4b8f30a2011-08-28 12:51:26 -050077static inline DrawablePtr
78dri2draw(DrawablePtr pDraw, DRI2BufferPtr buf)
79{
80 if (buf->attachment == DRI2BufferFrontLeft) {
81 return pDraw;
82 } else {
83 return &(OMAPBUF(buf)->pPixmap->drawable);
84 }
85}
86
87static inline Bool
Rob Clark99ab80d2012-04-12 17:38:07 -050088canexchange(DrawablePtr pDraw, DRI2BufferPtr a, DRI2BufferPtr b)
Rob Clark4b8f30a2011-08-28 12:51:26 -050089{
Rob Clark99ab80d2012-04-12 17:38:07 -050090 DrawablePtr da = dri2draw(pDraw, a);
91 DrawablePtr db = dri2draw(pDraw, b);
92
93 return DRI2CanFlip(pDraw) &&
94 (da->width == db->width) &&
95 (da->height == db->height) &&
96 (da->depth == db->depth);
Rob Clark4b8f30a2011-08-28 12:51:26 -050097}
98
99static Bool
100canflip(DrawablePtr pDraw)
101{
102 return (pDraw->type == DRAWABLE_WINDOW) &&
Rob Clark99ab80d2012-04-12 17:38:07 -0500103 DRI2CanFlip(pDraw);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500104}
105
106static inline Bool
107exchangebufs(DrawablePtr pDraw, DRI2BufferPtr a, DRI2BufferPtr b)
108{
Rob Clark4b8f30a2011-08-28 12:51:26 -0500109 OMAPPixmapExchange(draw2pix(dri2draw(pDraw, a)),
110 draw2pix(dri2draw(pDraw, b)));
111 exchange(a->name, b->name);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500112 return TRUE;
113}
114
115static PixmapPtr
116createpix(DrawablePtr pDraw)
117{
118 ScreenPtr pScreen = pDraw->pScreen;
119 int flags = canflip(pDraw) ? OMAP_CREATE_PIXMAP_SCANOUT : 0;
120 return pScreen->CreatePixmap(pScreen,
121 pDraw->width, pDraw->height, pDraw->depth, flags);
122}
123
124/**
125 * Create Buffer.
126 *
127 * Note that 'format' is used from the client side to specify the DRI buffer
128 * format, which could differ from the drawable format. For example, the
129 * drawable could be 32b RGB, but the DRI buffer some YUV format (video) or
130 * perhaps lower bit depth RGB (GL). The color conversion is handled when
131 * blitting to front buffer, and page-flipping (overlay or flipchain) can
132 * only be used if the display supports.
133 */
134static DRI2BufferPtr
135OMAPDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment,
136 unsigned int format)
137{
138 ScreenPtr pScreen = pDraw->pScreen;
139 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
140 OMAPPtr pOMAP = OMAPPTR(pScrn);
141 OMAPDRI2BufferPtr buf = calloc(1, sizeof(*buf));
142 PixmapPtr pPixmap;
143 struct omap_bo *bo;
144 int ret;
145
146 DEBUG_MSG("pDraw=%p, attachment=%d, format=%08x",
147 pDraw, attachment, format);
148
149 if (!buf) {
150 return NULL;
151 }
152
153 if (attachment == DRI2BufferFrontLeft) {
154 pPixmap = draw2pix(pDraw);
155
Rob Clark834f6462012-04-20 15:40:51 -0500156 /* to do flipping, if we don't have DMM, then we need a scanout
157 * capable (physically contiguous) buffer.. this bit of gymnastics
158 * ensures that.
Rob Clark4b8f30a2011-08-28 12:51:26 -0500159 *
Rob Clark834f6462012-04-20 15:40:51 -0500160 * TODO we may want to re-allocate and switch back to non-scanout
Rob Clark4b8f30a2011-08-28 12:51:26 -0500161 * buffer when client disconnects from drawable..
162 */
Rob Clark834f6462012-04-20 15:40:51 -0500163 if (canflip(pDraw) && !has_dmm(pOMAP) &&
164 (OMAPPixmapBo(pPixmap) != pOMAP->scanout)) {
165
Rob Clark4b8f30a2011-08-28 12:51:26 -0500166 /* need to re-allocate pixmap to get a scanout capable buffer */
167 PixmapPtr pNewPix = createpix(pDraw);
168
169 // TODO copy contents..
170
171 OMAPPixmapExchange(pPixmap, pNewPix);
172
173 pScreen->DestroyPixmap(pNewPix);
174 }
Rob Clark0bdd3702012-04-20 14:47:51 -0500175
176 pPixmap->refcnt++;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500177 } else {
178 pPixmap = createpix(pDraw);
179 }
180
181 bo = OMAPPixmapBo(pPixmap);
182
183 DRIBUF(buf)->attachment = attachment;
184 DRIBUF(buf)->pitch = exaGetPixmapPitch(pPixmap);
185 DRIBUF(buf)->cpp = pPixmap->drawable.bitsPerPixel / 8;
186 DRIBUF(buf)->format = format;
Rob Clark0bdd3702012-04-20 14:47:51 -0500187 buf->refcnt = 1;
188 buf->pPixmap = pPixmap;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500189
190 ret = omap_bo_get_name(bo, &DRIBUF(buf)->name);
191 if (ret) {
192 ERROR_MSG("could not get buffer name: %d", ret);
193 /* TODO cleanup */
194 return NULL;
195 }
196
Rob Clark4b8f30a2011-08-28 12:51:26 -0500197 /* Q: how to know across OMAP generations what formats that the display
198 * can support directly?
199 * A: attempt to create a drm_framebuffer, and if that fails then the
200 * hw must not support.. if buf->fb_id==0 then fall back to blitting
201 */
202 if (canflip(pDraw)) {
203 int ret = drmModeAddFB(pOMAP->drmFD, pDraw->width, pDraw->height,
204 pDraw->depth, pDraw->bitsPerPixel, DRIBUF(buf)->pitch,
205 omap_bo_handle(bo), &buf->fb_id);
206 if (ret) {
207 /* to-bad, so-sad, we can't flip */
208 WARNING_MSG("could not create fb: %d", ret);
209 buf->fb_id = 0;
210 }
211 }
212
213 return DRIBUF(buf);
214}
215
216/**
217 * Destroy Buffer
218 *
219 * TODO: depending on how flipping ends up working, we may need a refcnt or
220 * something like this to defer destroying a buffer that is currently being
221 * scanned out..
222 */
223static void
224OMAPDRI2DestroyBuffer(DrawablePtr pDraw, DRI2BufferPtr buffer)
225{
Rob Clark0bdd3702012-04-20 14:47:51 -0500226 OMAPDRI2BufferPtr buf = OMAPBUF(buffer);
227 /* Note: pDraw may already be deleted, so use the pPixmap here
228 * instead (since it is at least refcntd)
229 */
230 ScreenPtr pScreen = buf->pPixmap->drawable.pScreen;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500231 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
232 OMAPPtr pOMAP = OMAPPTR(pScrn);
Rob Clark0bdd3702012-04-20 14:47:51 -0500233
234 if (--buf->refcnt > 0)
235 return;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500236
237 DEBUG_MSG("pDraw=%p, buffer=%p", pDraw, buffer);
238
239 if (buf->fb_id) {
240 drmModeRmFB(pOMAP->drmFD, buf->fb_id);
241 }
242
Rob Clark0bdd3702012-04-20 14:47:51 -0500243 pScreen->DestroyPixmap(buf->pPixmap);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500244
245 free(buf);
246}
247
Rob Clark0bdd3702012-04-20 14:47:51 -0500248static void
249OMAPDRI2ReferenceBuffer(DRI2BufferPtr buffer)
250{
251 OMAPDRI2BufferPtr buf = OMAPBUF(buffer);
252 buf->refcnt++;
253}
254
Rob Clark4b8f30a2011-08-28 12:51:26 -0500255/**
256 *
257 */
258static void
259OMAPDRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
260 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
261{
262 ScreenPtr pScreen = pDraw->pScreen;
263 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
264 DrawablePtr pSrcDraw = dri2draw(pDraw, pSrcBuffer);
265 DrawablePtr pDstDraw = dri2draw(pDraw, pDstBuffer);
266 RegionPtr pCopyClip;
267 GCPtr pGC;
268
269 DEBUG_MSG("pDraw=%p, pDstBuffer=%p (%p), pSrcBuffer=%p (%p)",
270 pDraw, pDstBuffer, pSrcDraw, pSrcBuffer, pDstDraw);
271
272 pGC = GetScratchGC(pDstDraw->depth, pScreen);
273 if (!pGC) {
274 return;
275 }
276
277 pCopyClip = REGION_CREATE(pScreen, NULL, 0);
278 RegionCopy(pCopyClip, pRegion);
279 (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pCopyClip, 0);
280 ValidateGC(pDstDraw, pGC);
281
282 /* If the dst is the framebuffer, and we had a way to
283 * schedule a deferred blit synchronized w/ vsync, that
284 * would be a nice thing to do utilize here to avoid
285 * tearing.. when we have sync object support for GEM
286 * buffers, I think we could do something more clever
287 * here.
288 */
289
290 pGC->ops->CopyArea(pSrcDraw, pDstDraw, pGC,
291 0, 0, pDraw->width, pDraw->height, 0, 0);
292
Rob Clarke450d412012-01-08 19:33:48 -0600293 FreeScratchGC(pGC);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500294}
295
296/**
297 * Get current frame count and frame count timestamp, based on drawable's
298 * crtc.
299 */
300static int
301OMAPDRI2GetMSC(DrawablePtr pDraw, CARD64 *ust, CARD64 *msc)
302{
303 ScreenPtr pScreen = pDraw->pScreen;
304 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
305 OMAPPtr pOMAP = OMAPPTR(pScrn);
306 drmVBlank vbl = { .request = {
307 .type = DRM_VBLANK_RELATIVE,
308 .sequence = 0,
309 } };
310 int ret;
311
312 ret = drmWaitVBlank(pOMAP->drmFD, &vbl);
313 if (ret) {
314 static int limit = 5;
315 if (limit) {
316 ERROR_MSG("get vblank counter failed: %s", strerror(errno));
317 limit--;
318 }
319 return FALSE;
320 }
321
322 if (ust) {
323 *ust = ((CARD64)vbl.reply.tval_sec * 1000000) + vbl.reply.tval_usec;
324 }
325 if (msc) {
326 *msc = vbl.reply.sequence;
327 }
328
329 return TRUE;
330}
331
332struct _OMAPDRISwapCmd {
Rob Clarka6762ef2012-04-12 17:38:39 -0500333 int type;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500334 ClientPtr client;
Rob Clark0bdd3702012-04-20 14:47:51 -0500335 ScreenPtr pScreen;
336 /* Note: store drawable ID, rather than drawable. It's possible that
337 * the drawable can be destroyed while we wait for page flip event:
338 */
339 XID draw_id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500340 DRI2BufferPtr pDstBuffer;
341 DRI2BufferPtr pSrcBuffer;
342 DRI2SwapEventPtr func;
343 void *data;
344};
345
Rob Clark0bdd3702012-04-20 14:47:51 -0500346static const char *swap_names[] = {
347 [DRI2_EXCHANGE_COMPLETE] = "exchange",
348 [DRI2_BLIT_COMPLETE] = "blit",
349 [DRI2_FLIP_COMPLETE] = "flip,"
350};
351
Rob Clark4b8f30a2011-08-28 12:51:26 -0500352void
353OMAPDRI2SwapComplete(OMAPDRISwapCmd *cmd)
354{
Rob Clark0bdd3702012-04-20 14:47:51 -0500355 ScreenPtr pScreen = cmd->pScreen;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500356 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark67b875f2012-04-20 19:13:57 -0500357 OMAPPtr pOMAP = OMAPPTR(pScrn);
Rob Clark0bdd3702012-04-20 14:47:51 -0500358 DrawablePtr pDraw = NULL;
359 int status;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500360
Rob Clark0bdd3702012-04-20 14:47:51 -0500361 DEBUG_MSG("%s complete: %d -> %d", swap_names[cmd->type],
362 cmd->pSrcBuffer->attachment, cmd->pDstBuffer->attachment);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500363
Rob Clark0bdd3702012-04-20 14:47:51 -0500364 status = dixLookupDrawable(&pDraw, cmd->draw_id, serverClient,
365 M_ANY, DixWriteAccess);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500366
Rob Clark0bdd3702012-04-20 14:47:51 -0500367 if (status == Success) {
368 if (cmd->type != DRI2_BLIT_COMPLETE)
369 exchangebufs(pDraw, cmd->pSrcBuffer, cmd->pDstBuffer);
370
371 DRI2SwapComplete(cmd->client, pDraw, 0, 0, 0, cmd->type,
372 cmd->func, cmd->data);
373 }
374
375 /* drop extra refcnt we obtained prior to swap:
376 */
377 OMAPDRI2DestroyBuffer(pDraw, cmd->pSrcBuffer);
378 OMAPDRI2DestroyBuffer(pDraw, cmd->pDstBuffer);
Rob Clark67b875f2012-04-20 19:13:57 -0500379 pOMAP->pending_flips--;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500380
381 free(cmd);
382}
383
384/**
385 * ScheduleSwap is responsible for requesting a DRM vblank event for the
386 * appropriate frame.
387 *
388 * In the case of a blit (e.g. for a windowed swap) or buffer exchange,
389 * the vblank requested can simply be the last queued swap frame + the swap
390 * interval for the drawable.
391 *
392 * In the case of a page flip, we request an event for the last queued swap
393 * frame + swap interval - 1, since we'll need to queue the flip for the frame
394 * immediately following the received event.
395 */
396static int
397OMAPDRI2ScheduleSwap(ClientPtr client, DrawablePtr pDraw,
398 DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer,
399 CARD64 *target_msc, CARD64 divisor, CARD64 remainder,
400 DRI2SwapEventPtr func, void *data)
401{
402 ScreenPtr pScreen = pDraw->pScreen;
403 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
Rob Clark67b875f2012-04-20 19:13:57 -0500404 OMAPPtr pOMAP = OMAPPTR(pScrn);
Rob Clark4b8f30a2011-08-28 12:51:26 -0500405 OMAPDRI2BufferPtr src = OMAPBUF(pSrcBuffer);
406 OMAPDRI2BufferPtr dst = OMAPBUF(pDstBuffer);
407 OMAPDRISwapCmd *cmd = calloc(1, sizeof(*cmd));
408
409 cmd->client = client;
Rob Clark0bdd3702012-04-20 14:47:51 -0500410 cmd->pScreen = pScreen;
411 cmd->draw_id = pDraw->id;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500412 cmd->pSrcBuffer = pSrcBuffer;
413 cmd->pDstBuffer = pDstBuffer;
414 cmd->func = func;
415 cmd->data = data;
416
417 DEBUG_MSG("%d -> %d", pSrcBuffer->attachment, pDstBuffer->attachment);
418
Rob Clark0bdd3702012-04-20 14:47:51 -0500419 /* obtain extra ref on buffers to avoid them going away while we await
420 * the page flip event:
421 */
422 OMAPDRI2ReferenceBuffer(pSrcBuffer);
423 OMAPDRI2ReferenceBuffer(pDstBuffer);
Rob Clark67b875f2012-04-20 19:13:57 -0500424 pOMAP->pending_flips++;
Rob Clark0bdd3702012-04-20 14:47:51 -0500425
Rob Clark4b8f30a2011-08-28 12:51:26 -0500426 if (src->fb_id && dst->fb_id) {
427 DEBUG_MSG("can flip: %d -> %d", src->fb_id, dst->fb_id);
Rob Clarka6762ef2012-04-12 17:38:39 -0500428 cmd->type = DRI2_FLIP_COMPLETE;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500429 drmmode_page_flip(pDraw, src->fb_id, cmd);
Rob Clark99ab80d2012-04-12 17:38:07 -0500430 } else if (canexchange(pDraw, pSrcBuffer, pDstBuffer)) {
431 /* we can get away w/ pointer swap.. yah! */
Rob Clarka6762ef2012-04-12 17:38:39 -0500432 cmd->type = DRI2_EXCHANGE_COMPLETE;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500433 OMAPDRI2SwapComplete(cmd);
434 } else {
435 /* fallback to blit: */
436 BoxRec box = {
437 .x1 = 0,
438 .y1 = 0,
439 .x2 = pDraw->width,
440 .y2 = pDraw->height,
441 };
442 RegionRec region;
443 RegionInit(&region, &box, 0);
444 OMAPDRI2CopyRegion(pDraw, &region, pDstBuffer, pSrcBuffer);
Rob Clarka6762ef2012-04-12 17:38:39 -0500445 cmd->type = DRI2_BLIT_COMPLETE;
Rob Clark4b8f30a2011-08-28 12:51:26 -0500446 OMAPDRI2SwapComplete(cmd);
447 }
448
449 return TRUE;
450}
451
452/**
453 * Request a DRM event when the requested conditions will be satisfied.
454 *
455 * We need to handle the event and ask the server to wake up the client when
456 * we receive it.
457 */
458static int
459OMAPDRI2ScheduleWaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
460 CARD64 divisor, CARD64 remainder)
461{
462 ScreenPtr pScreen = pDraw->pScreen;
463 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
464// OMAPPtr pOMAP = OMAPPTR(pScrn);
465
466#if 0
467#endif
468 ERROR_MSG("not implemented");
469 return FALSE;
470}
471
472/**
473 * The DRI2 ScreenInit() function.. register our handler fxns w/ DRI2 core
474 */
475Bool
476OMAPDRI2ScreenInit(ScreenPtr pScreen)
477{
478 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
479 OMAPPtr pOMAP = OMAPPTR(pScrn);
480 DRI2InfoRec info = {
481 .version = 5,
482 .fd = pOMAP->drmFD,
483 .driverName = "omap",
484 .deviceName = pOMAP->deviceName,
485 .CreateBuffer = OMAPDRI2CreateBuffer,
486 .DestroyBuffer = OMAPDRI2DestroyBuffer,
487 .CopyRegion = OMAPDRI2CopyRegion,
488 .ScheduleSwap = OMAPDRI2ScheduleSwap,
489 .ScheduleWaitMSC = OMAPDRI2ScheduleWaitMSC,
490 .GetMSC = OMAPDRI2GetMSC,
491 .AuthMagic = drmAuthMagic,
492 };
493 int minor = 1, major = 0;
494
495 if (xf86LoaderCheckSymbol("DRI2Version")) {
496 DRI2Version(&major, &minor);
497 }
498
499 if (minor < 1) {
500 WARNING_MSG("DRI2 requires DRI2 module version 1.1.0 or later");
501 return FALSE;
502 }
503
504 return DRI2ScreenInit(pScreen, &info);
505}
506
507/**
508 * The DRI2 CloseScreen() function.. unregister ourself w/ DRI2 core.
509 */
510void
511OMAPDRI2CloseScreen(ScreenPtr pScreen)
512{
Rob Clark67b875f2012-04-20 19:13:57 -0500513 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
514 OMAPPtr pOMAP = OMAPPTR(pScrn);
515 while (pOMAP->pending_flips > 0) {
516 DEBUG_MSG("waiting..");
517 drmmode_wait_for_event(pScrn);
518 }
Rob Clark4b8f30a2011-08-28 12:51:26 -0500519 DRI2CloseScreen(pScreen);
520}