1fa225cbcSrjs/**************************************************************************
2fa225cbcSrjs
3fa225cbcSrjsCopyright 2001 VA Linux Systems Inc., Fremont, California.
4fa225cbcSrjsCopyright © 2002 by David Dawes
5fa225cbcSrjs
6fa225cbcSrjsAll Rights Reserved.
7fa225cbcSrjs
8fa225cbcSrjsPermission is hereby granted, free of charge, to any person obtaining a
9fa225cbcSrjscopy of this software and associated documentation files (the "Software"),
10fa225cbcSrjsto deal in the Software without restriction, including without limitation
11fa225cbcSrjson the rights to use, copy, modify, merge, publish, distribute, sub
12fa225cbcSrjslicense, and/or sell copies of the Software, and to permit persons to whom
13fa225cbcSrjsthe Software is furnished to do so, subject to the following conditions:
14fa225cbcSrjs
15fa225cbcSrjsThe above copyright notice and this permission notice (including the next
16fa225cbcSrjsparagraph) shall be included in all copies or substantial portions of the
17fa225cbcSrjsSoftware.
18fa225cbcSrjs
19fa225cbcSrjsTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20fa225cbcSrjsIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21fa225cbcSrjsFITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22fa225cbcSrjsATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23fa225cbcSrjsDAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24fa225cbcSrjsOTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25fa225cbcSrjsUSE OR OTHER DEALINGS IN THE SOFTWARE.
26fa225cbcSrjs
27fa225cbcSrjs**************************************************************************/
28fa225cbcSrjs
29fa225cbcSrjs/*
30fa225cbcSrjs * Authors: Jeff Hartmann <jhartmann@valinux.com>
31fa225cbcSrjs *          David Dawes <dawes@xfree86.org>
32fa225cbcSrjs *          Keith Whitwell <keith@tungstengraphics.com>
33fa225cbcSrjs */
34fa225cbcSrjs
35fa225cbcSrjs#ifdef HAVE_CONFIG_H
36fa225cbcSrjs#include "config.h"
37fa225cbcSrjs#endif
38fa225cbcSrjs
39fa225cbcSrjs#include <stdio.h>
40fa225cbcSrjs#include <string.h>
41fa225cbcSrjs#include <assert.h>
42fa225cbcSrjs#include <sys/types.h>
43fa225cbcSrjs#include <sys/stat.h>
44fa225cbcSrjs#include <sys/ioctl.h>
45fa225cbcSrjs#include <errno.h>
46fa225cbcSrjs#include <unistd.h>
47fa225cbcSrjs#include <fcntl.h>
48fa225cbcSrjs
49fa225cbcSrjs#include "xf86.h"
50fa225cbcSrjs#include "xf86_OSproc.h"
51fa225cbcSrjs#include "xf86Priv.h"
52fa225cbcSrjs
53fa225cbcSrjs#include "xf86PciInfo.h"
54fa225cbcSrjs#include "xf86Pci.h"
55fa225cbcSrjs
56fa225cbcSrjs#include "windowstr.h"
57fa225cbcSrjs#include "shadow.h"
58fa225cbcSrjs
59fa225cbcSrjs#include "GL/glxtokens.h"
60fa225cbcSrjs
61fa225cbcSrjs#include "i830.h"
62fa225cbcSrjs#include "i830_dri.h"
63fa225cbcSrjs
64fa225cbcSrjs#include "i915_drm.h"
65fa225cbcSrjs
66fa225cbcSrjs#include "dri2.h"
67fa225cbcSrjs
68fa225cbcSrjs#ifdef DRI2
69fa225cbcSrjs#if DRI2INFOREC_VERSION >= 1
70fa225cbcSrjs#define USE_DRI2_1_1_0
71fa225cbcSrjs#endif
72fa225cbcSrjs
73fa225cbcSrjsextern XF86ModuleData dri2ModuleData;
74fa225cbcSrjs#endif
75fa225cbcSrjs
76fa225cbcSrjstypedef struct {
77fa225cbcSrjs    PixmapPtr pPixmap;
78fa225cbcSrjs    unsigned int attachment;
79fa225cbcSrjs} I830DRI2BufferPrivateRec, *I830DRI2BufferPrivatePtr;
80fa225cbcSrjs
81fa225cbcSrjs#ifndef USE_DRI2_1_1_0
82fa225cbcSrjsstatic DRI2BufferPtr
83fa225cbcSrjsI830DRI2CreateBuffers(DrawablePtr pDraw, unsigned int *attachments, int count)
84fa225cbcSrjs{
85fa225cbcSrjs    ScreenPtr pScreen = pDraw->pScreen;
86fa225cbcSrjs    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
87fa225cbcSrjs    I830Ptr pI830 = I830PTR(pScrn);
88fa225cbcSrjs    DRI2BufferPtr buffers;
89fa225cbcSrjs    dri_bo *bo;
90fa225cbcSrjs    int i;
91fa225cbcSrjs    I830DRI2BufferPrivatePtr privates;
92fa225cbcSrjs    PixmapPtr pPixmap, pDepthPixmap;
93fa225cbcSrjs
94fa225cbcSrjs    buffers = xcalloc(count, sizeof *buffers);
95fa225cbcSrjs    if (buffers == NULL)
96fa225cbcSrjs	return NULL;
97fa225cbcSrjs    privates = xcalloc(count, sizeof *privates);
98fa225cbcSrjs    if (privates == NULL) {
99fa225cbcSrjs	xfree(buffers);
100fa225cbcSrjs	return NULL;
101fa225cbcSrjs    }
102fa225cbcSrjs
103fa225cbcSrjs    pDepthPixmap = NULL;
104fa225cbcSrjs    for (i = 0; i < count; i++) {
105fa225cbcSrjs	if (attachments[i] == DRI2BufferFrontLeft) {
106fa225cbcSrjs	    pPixmap = get_drawable_pixmap(pDraw);
107fa225cbcSrjs	    pPixmap->refcnt++;
108fa225cbcSrjs	} else if (attachments[i] == DRI2BufferStencil && pDepthPixmap) {
109fa225cbcSrjs	    pPixmap = pDepthPixmap;
110fa225cbcSrjs	    pPixmap->refcnt++;
111fa225cbcSrjs	} else {
112fa225cbcSrjs	    unsigned int hint = 0;
113fa225cbcSrjs
114fa225cbcSrjs	    switch (attachments[i]) {
115fa225cbcSrjs	    case DRI2BufferDepth:
116fa225cbcSrjs		if (SUPPORTS_YTILING(pI830))
117fa225cbcSrjs		    hint = INTEL_CREATE_PIXMAP_TILING_Y;
118fa225cbcSrjs		else
119fa225cbcSrjs		    hint = INTEL_CREATE_PIXMAP_TILING_X;
120fa225cbcSrjs		break;
121fa225cbcSrjs	    case DRI2BufferFakeFrontLeft:
122fa225cbcSrjs	    case DRI2BufferFakeFrontRight:
123fa225cbcSrjs	    case DRI2BufferBackLeft:
124fa225cbcSrjs	    case DRI2BufferBackRight:
125fa225cbcSrjs		    hint = INTEL_CREATE_PIXMAP_TILING_X;
126fa225cbcSrjs		break;
127fa225cbcSrjs	    }
128fa225cbcSrjs
129fa225cbcSrjs	    if (!pI830->tiling ||
130fa225cbcSrjs		(!IS_I965G(pI830) && !pI830->kernel_exec_fencing))
131fa225cbcSrjs		hint = 0;
132fa225cbcSrjs
133fa225cbcSrjs	    pPixmap = (*pScreen->CreatePixmap)(pScreen,
134fa225cbcSrjs					       pDraw->width,
135fa225cbcSrjs					       pDraw->height,
136fa225cbcSrjs					       pDraw->depth,
137fa225cbcSrjs					       hint);
138fa225cbcSrjs
139fa225cbcSrjs	}
140fa225cbcSrjs
141fa225cbcSrjs	if (attachments[i] == DRI2BufferDepth)
142fa225cbcSrjs	    pDepthPixmap = pPixmap;
143fa225cbcSrjs
144fa225cbcSrjs	buffers[i].attachment = attachments[i];
145fa225cbcSrjs	buffers[i].pitch = pPixmap->devKind;
146fa225cbcSrjs	buffers[i].cpp = pPixmap->drawable.bitsPerPixel / 8;
147fa225cbcSrjs	buffers[i].driverPrivate = &privates[i];
148fa225cbcSrjs	buffers[i].flags = 0; /* not tiled */
149fa225cbcSrjs	privates[i].pPixmap = pPixmap;
150fa225cbcSrjs	privates[i].attachment = attachments[i];
151fa225cbcSrjs
152fa225cbcSrjs	bo = i830_get_pixmap_bo (pPixmap);
153fa225cbcSrjs	if (dri_bo_flink(bo, &buffers[i].name) != 0) {
154fa225cbcSrjs	    /* failed to name buffer */
155fa225cbcSrjs	}
156fa225cbcSrjs
157fa225cbcSrjs    }
158fa225cbcSrjs
159fa225cbcSrjs    return buffers;
160fa225cbcSrjs}
161fa225cbcSrjs
162fa225cbcSrjs#else
163fa225cbcSrjs
164fa225cbcSrjsstatic DRI2Buffer2Ptr
165fa225cbcSrjsI830DRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment,
166fa225cbcSrjs		     unsigned int format)
167fa225cbcSrjs{
168fa225cbcSrjs    ScreenPtr pScreen = pDraw->pScreen;
169fa225cbcSrjs    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
170fa225cbcSrjs    I830Ptr pI830 = I830PTR(pScrn);
171fa225cbcSrjs    DRI2Buffer2Ptr buffer;
172fa225cbcSrjs    dri_bo *bo;
173fa225cbcSrjs    I830DRI2BufferPrivatePtr privates;
174fa225cbcSrjs    PixmapPtr pPixmap;
175fa225cbcSrjs
176fa225cbcSrjs    buffer = xcalloc(1, sizeof *buffer);
177fa225cbcSrjs    if (buffer == NULL)
178fa225cbcSrjs	return NULL;
179fa225cbcSrjs    privates = xcalloc(1, sizeof *privates);
180fa225cbcSrjs    if (privates == NULL) {
181fa225cbcSrjs	xfree(buffer);
182fa225cbcSrjs	return NULL;
183fa225cbcSrjs    }
184fa225cbcSrjs
185fa225cbcSrjs    if (attachment == DRI2BufferFrontLeft) {
186fa225cbcSrjs	pPixmap = get_drawable_pixmap(pDraw);
187fa225cbcSrjs	pPixmap->refcnt++;
188fa225cbcSrjs    } else {
189fa225cbcSrjs	unsigned int hint = 0;
190fa225cbcSrjs
191fa225cbcSrjs	switch (attachment) {
192fa225cbcSrjs	case DRI2BufferDepth:
193fa225cbcSrjs	case DRI2BufferDepthStencil:
194fa225cbcSrjs	    if (SUPPORTS_YTILING(pI830))
195fa225cbcSrjs		hint = INTEL_CREATE_PIXMAP_TILING_Y;
196fa225cbcSrjs	    else
197fa225cbcSrjs		hint = INTEL_CREATE_PIXMAP_TILING_X;
198fa225cbcSrjs	    break;
199fa225cbcSrjs	case DRI2BufferFakeFrontLeft:
200fa225cbcSrjs	case DRI2BufferFakeFrontRight:
201fa225cbcSrjs	case DRI2BufferBackLeft:
202fa225cbcSrjs	case DRI2BufferBackRight:
203fa225cbcSrjs	    hint = INTEL_CREATE_PIXMAP_TILING_X;
204fa225cbcSrjs	    break;
205fa225cbcSrjs	}
206fa225cbcSrjs
207fa225cbcSrjs	if (!pI830->tiling ||
208fa225cbcSrjs	    (!IS_I965G(pI830) && !pI830->kernel_exec_fencing))
209fa225cbcSrjs	    hint = 0;
210fa225cbcSrjs
211fa225cbcSrjs	pPixmap = (*pScreen->CreatePixmap)(pScreen,
212fa225cbcSrjs					   pDraw->width,
213fa225cbcSrjs					   pDraw->height,
214fa225cbcSrjs					   (format != 0)?format:pDraw->depth,
215fa225cbcSrjs					   hint);
216fa225cbcSrjs
217fa225cbcSrjs    }
218fa225cbcSrjs
219fa225cbcSrjs
220fa225cbcSrjs    buffer->attachment = attachment;
221fa225cbcSrjs    buffer->pitch = pPixmap->devKind;
222fa225cbcSrjs    buffer->cpp = pPixmap->drawable.bitsPerPixel / 8;
223fa225cbcSrjs    buffer->driverPrivate = privates;
224fa225cbcSrjs    buffer->format = format;
225fa225cbcSrjs    buffer->flags = 0; /* not tiled */
226fa225cbcSrjs    privates->pPixmap = pPixmap;
227fa225cbcSrjs    privates->attachment = attachment;
228fa225cbcSrjs
229fa225cbcSrjs    bo = i830_get_pixmap_bo (pPixmap);
230fa225cbcSrjs    if (dri_bo_flink(bo, &buffer->name) != 0) {
231fa225cbcSrjs	/* failed to name buffer */
232fa225cbcSrjs    }
233fa225cbcSrjs
234fa225cbcSrjs    return buffer;
235fa225cbcSrjs}
236fa225cbcSrjs
237fa225cbcSrjs#endif
238fa225cbcSrjs
239fa225cbcSrjs#ifndef USE_DRI2_1_1_0
240fa225cbcSrjs
241fa225cbcSrjsstatic void
242fa225cbcSrjsI830DRI2DestroyBuffers(DrawablePtr pDraw, DRI2BufferPtr buffers, int count)
243fa225cbcSrjs{
244fa225cbcSrjs    ScreenPtr pScreen = pDraw->pScreen;
245fa225cbcSrjs    I830DRI2BufferPrivatePtr private;
246fa225cbcSrjs    int i;
247fa225cbcSrjs
248fa225cbcSrjs    for (i = 0; i < count; i++)
249fa225cbcSrjs    {
250fa225cbcSrjs	private = buffers[i].driverPrivate;
251fa225cbcSrjs	(*pScreen->DestroyPixmap)(private->pPixmap);
252fa225cbcSrjs    }
253fa225cbcSrjs
254fa225cbcSrjs    if (buffers)
255fa225cbcSrjs    {
256fa225cbcSrjs	xfree(buffers[0].driverPrivate);
257fa225cbcSrjs	xfree(buffers);
258fa225cbcSrjs    }
259fa225cbcSrjs}
260fa225cbcSrjs
261fa225cbcSrjs#else
262fa225cbcSrjs
263fa225cbcSrjsstatic void
264fa225cbcSrjsI830DRI2DestroyBuffer(DrawablePtr pDraw, DRI2Buffer2Ptr buffer)
265fa225cbcSrjs{
266fa225cbcSrjs    if (buffer) {
267fa225cbcSrjs	I830DRI2BufferPrivatePtr private = buffer->driverPrivate;
268fa225cbcSrjs	ScreenPtr pScreen = pDraw->pScreen;
269fa225cbcSrjs
270fa225cbcSrjs	(*pScreen->DestroyPixmap)(private->pPixmap);
271fa225cbcSrjs
272fa225cbcSrjs	xfree(private);
273fa225cbcSrjs	xfree(buffer);
274fa225cbcSrjs    }
275fa225cbcSrjs}
276fa225cbcSrjs
277fa225cbcSrjs#endif
278fa225cbcSrjs
279fa225cbcSrjsstatic void
280fa225cbcSrjsI830DRI2CopyRegion(DrawablePtr pDraw, RegionPtr pRegion,
281fa225cbcSrjs		   DRI2BufferPtr pDstBuffer, DRI2BufferPtr pSrcBuffer)
282fa225cbcSrjs{
283fa225cbcSrjs    I830DRI2BufferPrivatePtr srcPrivate = pSrcBuffer->driverPrivate;
284fa225cbcSrjs    I830DRI2BufferPrivatePtr dstPrivate = pDstBuffer->driverPrivate;
285fa225cbcSrjs    ScreenPtr pScreen = pDraw->pScreen;
286fa225cbcSrjs    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
287fa225cbcSrjs    I830Ptr pI830 = I830PTR(pScrn);
288fa225cbcSrjs    DrawablePtr src = (srcPrivate->attachment == DRI2BufferFrontLeft)
289fa225cbcSrjs	? pDraw : &srcPrivate->pPixmap->drawable;
290fa225cbcSrjs    DrawablePtr dst = (dstPrivate->attachment == DRI2BufferFrontLeft)
291fa225cbcSrjs	? pDraw : &dstPrivate->pPixmap->drawable;
292fa225cbcSrjs    RegionPtr pCopyClip;
293fa225cbcSrjs    GCPtr pGC;
294fa225cbcSrjs
295fa225cbcSrjs    pGC = GetScratchGC(pDraw->depth, pScreen);
296fa225cbcSrjs    pCopyClip = REGION_CREATE(pScreen, NULL, 0);
297fa225cbcSrjs    REGION_COPY(pScreen, pCopyClip, pRegion);
298fa225cbcSrjs    (*pGC->funcs->ChangeClip) (pGC, CT_REGION, pCopyClip, 0);
299fa225cbcSrjs    ValidateGC(dst, pGC);
300fa225cbcSrjs
301fa225cbcSrjs    /* Wait for the scanline to be outside the region to be copied */
302fa225cbcSrjs    if (pixmap_is_scanout(get_drawable_pixmap(dst)) && pI830->swapbuffers_wait) {
303fa225cbcSrjs	BoxPtr box;
304fa225cbcSrjs	BoxRec crtcbox;
305fa225cbcSrjs	int y1, y2;
306fa225cbcSrjs	int pipe = -1, event, load_scan_lines_pipe;
307fa225cbcSrjs	xf86CrtcPtr crtc;
308fa225cbcSrjs
309fa225cbcSrjs	box = REGION_EXTENTS(unused, pGC->pCompositeClip);
310fa225cbcSrjs	crtc = i830_covering_crtc(pScrn, box, NULL, &crtcbox);
311fa225cbcSrjs
312fa225cbcSrjs	/* Make sure the CRTC is valid and this is the real front buffer */
313fa225cbcSrjs	if (crtc != NULL && !crtc->rotatedData) {
314fa225cbcSrjs	    pipe = i830_crtc_to_pipe(crtc);
315fa225cbcSrjs
316fa225cbcSrjs	    if (pipe == 0) {
317fa225cbcSrjs		event = MI_WAIT_FOR_PIPEA_SCAN_LINE_WINDOW;
318fa225cbcSrjs		load_scan_lines_pipe = MI_LOAD_SCAN_LINES_DISPLAY_PIPEA;
319fa225cbcSrjs	    } else {
320fa225cbcSrjs		event = MI_WAIT_FOR_PIPEB_SCAN_LINE_WINDOW;
321fa225cbcSrjs		load_scan_lines_pipe = MI_LOAD_SCAN_LINES_DISPLAY_PIPEB;
322fa225cbcSrjs	    }
323fa225cbcSrjs
324fa225cbcSrjs	    /* Make sure we don't wait for a scanline that will never occur */
325fa225cbcSrjs	    y1 = (crtcbox.y1 <= box->y1) ? box->y1 - crtcbox.y1 : 0;
326fa225cbcSrjs	    y2 = (box->y2 <= crtcbox.y2) ?
327fa225cbcSrjs		box->y2 - crtcbox.y1 : crtcbox.y2 - crtcbox.y1;
328fa225cbcSrjs
329fa225cbcSrjs	    BEGIN_BATCH(5);
330fa225cbcSrjs	    /* The documentation says that the LOAD_SCAN_LINES command
331fa225cbcSrjs	     * always comes in pairs. Don't ask me why. */
332fa225cbcSrjs	    OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | load_scan_lines_pipe);
333fa225cbcSrjs	    OUT_BATCH((y1 << 16) | y2);
334fa225cbcSrjs	    OUT_BATCH(MI_LOAD_SCAN_LINES_INCL | load_scan_lines_pipe);
335fa225cbcSrjs	    OUT_BATCH((y1 << 16) | y2);
336fa225cbcSrjs	    OUT_BATCH(MI_WAIT_FOR_EVENT | event);
337fa225cbcSrjs	    ADVANCE_BATCH();
338fa225cbcSrjs	}
339fa225cbcSrjs    }
340fa225cbcSrjs
341fa225cbcSrjs    (*pGC->ops->CopyArea)(src, dst,
342fa225cbcSrjs			  pGC, 0, 0, pDraw->width, pDraw->height, 0, 0);
343fa225cbcSrjs    FreeScratchGC(pGC);
344fa225cbcSrjs
345fa225cbcSrjs    /* Emit a flush of the rendering cache, or on the 965 and beyond
346fa225cbcSrjs     * rendering results may not hit the framebuffer until significantly
347fa225cbcSrjs     * later.
348fa225cbcSrjs     */
349fa225cbcSrjs    I830EmitFlush(pScrn);
350fa225cbcSrjs    pI830->need_mi_flush = FALSE;
351fa225cbcSrjs
352fa225cbcSrjs    /* We can't rely on getting into the block handler before the DRI
353fa225cbcSrjs     * client gets to run again so flush now. */
354fa225cbcSrjs    intel_batch_flush(pScrn, TRUE);
355fa225cbcSrjs#if ALWAYS_SYNC
356fa225cbcSrjs    I830Sync(pScrn);
357fa225cbcSrjs#endif
358fa225cbcSrjs    drmCommandNone(pI830->drmSubFD, DRM_I915_GEM_THROTTLE);
359fa225cbcSrjs
360fa225cbcSrjs}
361fa225cbcSrjs
362fa225cbcSrjsBool I830DRI2ScreenInit(ScreenPtr pScreen)
363fa225cbcSrjs{
364fa225cbcSrjs    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
365fa225cbcSrjs    I830Ptr pI830 = I830PTR(pScrn);
366fa225cbcSrjs    DRI2InfoRec info;
367fa225cbcSrjs    char *p;
368fa225cbcSrjs    int i;
369fa225cbcSrjs    struct stat sbuf;
370fa225cbcSrjs    dev_t d;
371fa225cbcSrjs#ifdef USE_DRI2_1_1_0
372fa225cbcSrjs    int dri2_major = 1;
373fa225cbcSrjs    int dri2_minor = 0;
374fa225cbcSrjs#endif
375fa225cbcSrjs
376fa225cbcSrjs#ifdef USE_DRI2_1_1_0
377fa225cbcSrjs    if (xf86LoaderCheckSymbol("DRI2Version")) {
378fa225cbcSrjs	DRI2Version(& dri2_major, & dri2_minor);
379fa225cbcSrjs    }
380fa225cbcSrjs
381fa225cbcSrjs    if (dri2_minor < 1) {
382fa225cbcSrjs	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
383fa225cbcSrjs		   "DRI2 requires DRI2 module version 1.1.0 or later\n");
384fa225cbcSrjs	return FALSE;
385fa225cbcSrjs    }
386fa225cbcSrjs#endif
387fa225cbcSrjs
388fa225cbcSrjs    info.fd = pI830->drmSubFD;
389fa225cbcSrjs
390fa225cbcSrjs    /* The whole drmOpen thing is a fiasco and we need to find a way
391fa225cbcSrjs     * back to just using open(2).  For now, however, lets just make
392fa225cbcSrjs     * things worse with even more ad hoc directory walking code to
393fa225cbcSrjs     * discover the device file name. */
394fa225cbcSrjs
395fa225cbcSrjs    fstat(info.fd, &sbuf);
396fa225cbcSrjs    d = sbuf.st_rdev;
397fa225cbcSrjs
398fa225cbcSrjs    p = pI830->deviceName;
399fa225cbcSrjs    for (i = 0; i < DRM_MAX_MINOR; i++) {
400fa225cbcSrjs	sprintf(p, DRM_DEV_NAME, DRM_DIR_NAME, i);
401fa225cbcSrjs	if (stat(p, &sbuf) == 0 && sbuf.st_rdev == d)
402fa225cbcSrjs	    break;
403fa225cbcSrjs    }
404fa225cbcSrjs    if (i == DRM_MAX_MINOR) {
405fa225cbcSrjs	xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
406fa225cbcSrjs		   "DRI2: failed to open drm device\n");
407fa225cbcSrjs	return FALSE;
408fa225cbcSrjs    }
409fa225cbcSrjs
410fa225cbcSrjs    info.driverName = IS_I965G(pI830) ? "i965" : "i915";
411fa225cbcSrjs    info.deviceName = p;
412fa225cbcSrjs
413fa225cbcSrjs#if DRI2INFOREC_VERSION >= 3
414fa225cbcSrjs    info.version = 3;
415fa225cbcSrjs    info.CreateBuffer = I830DRI2CreateBuffer;
416fa225cbcSrjs    info.DestroyBuffer = I830DRI2DestroyBuffer;
417fa225cbcSrjs#else
418fa225cbcSrjs# ifdef USE_DRI2_1_1_0
419fa225cbcSrjs    info.version = 2;
420fa225cbcSrjs    info.CreateBuffers = NULL;
421fa225cbcSrjs    info.DestroyBuffers = NULL;
422fa225cbcSrjs    info.CreateBuffer = I830DRI2CreateBuffer;
423fa225cbcSrjs    info.DestroyBuffer = I830DRI2DestroyBuffer;
424fa225cbcSrjs# else
425fa225cbcSrjs    info.version = 1;
426fa225cbcSrjs    info.CreateBuffers = I830DRI2CreateBuffers;
427fa225cbcSrjs    info.DestroyBuffers = I830DRI2DestroyBuffers;
428fa225cbcSrjs# endif
429fa225cbcSrjs#endif
430fa225cbcSrjs
431fa225cbcSrjs    info.CopyRegion = I830DRI2CopyRegion;
432fa225cbcSrjs
433fa225cbcSrjs    return DRI2ScreenInit(pScreen, &info);
434fa225cbcSrjs}
435fa225cbcSrjs
436fa225cbcSrjsvoid I830DRI2CloseScreen(ScreenPtr pScreen)
437fa225cbcSrjs{
438fa225cbcSrjs    ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
439fa225cbcSrjs    I830Ptr pI830 = I830PTR(pScrn);
440fa225cbcSrjs
441fa225cbcSrjs    DRI2CloseScreen(pScreen);
442fa225cbcSrjs    pI830->directRenderingType = DRI_NONE;
443fa225cbcSrjs}
444