2 * Generic EGL driver for DRI. This is basically an "adaptor" driver
3 * that allows libEGL to load/use regular DRI drivers.
5 * This file contains all the code needed to interface DRI-based drivers
8 * There's a lot of dependencies on fbdev and the /sys/ filesystem.
23 #include "egldriver.h"
24 #include "egldisplay.h"
25 #include "eglcontext.h"
26 #include "eglconfig.h"
27 #include "eglconfigutil.h"
28 #include "eglsurface.h"
29 #include "eglscreen.h"
30 #include "eglglobals.h"
36 const char *sysfs
= "/sys/class";
38 static const int empty_attribute_list
[1] = { None
};
43 * Given a card number, return the name of the DRI driver to use.
44 * This generally means reading the contents of
45 * /sys/class/drm/cardX/dri_library_name, where X is the card number
48 driver_name_from_card_number(int card
, char *driverName
, int maxDriverName
)
54 snprintf(path
, sizeof(path
), "%s/drm/card%d/dri_library_name", sysfs
, card
);
60 fgets(driverName
, maxDriverName
, f
);
63 if ((length
= strlen(driverName
)) > 1) {
64 /* remove the trailing newline from sysfs */
65 driverName
[length
- 1] = '\0';
66 strncat(driverName
, "_dri", maxDriverName
);
77 * The bootstrap function.
78 * Return a new driDriver object and plug in API functions.
79 * This function, in turn, loads a specific DRI driver (ex: r200_dri.so).
82 _eglMain(_EGLDisplay
*dpy
, const char *args
)
85 const int card
= args
? atoi(args
) : 0;
86 _EGLDriver
*driver
= NULL
;
87 char driverName
[1000];
89 if (!driver_name_from_card_number(card
, driverName
, sizeof(driverName
))) {
91 "Unable to determine driver name for card %d\n", card
);
95 _eglLog(_EGL_DEBUG
, "Driver name: %s\n", driverName
);
97 driver
= _eglOpenDriver(dpy
, driverName
, args
);
105 struct dirent
*dirent
;
110 _EGLDriver
*driver
= NULL
;;
112 snprintf(path
, sizeof(path
), "%s/drm", sysfs
);
113 if (!(dir
= opendir(path
))) {
114 _eglLog(_EGL_WARNING
, "%s DRM devices not found.", path
);
118 /* loop over dir entries looking for cardX where "X" is in the
119 * dpy->DriverName ":X" string.
121 while ((dirent
= readdir(dir
))) {
123 if (strncmp(&dirent
->d_name
[0], "card", 4) != 0)
125 if (strcmp(&dirent
->d_name
[4], &driverName
[1]) != 0)
128 snprintf(path
, sizeof(path
), "%s/drm/card%s/dri_library_name",
129 sysfs
, &driverName
[1]);
130 _eglLog(_EGL_INFO
, "Opening %s", path
);
132 file
= fopen(path
, "r");
134 _eglLog(_EGL_WARNING
, "Failed to open %s", path
);
137 fgets(path
, sizeof(path
), file
);
140 strcpy(path
, "r200\n");
142 if ((length
= strlen(path
)) > 0)
143 path
[length
- 1] = '\0'; /* remove the trailing newline from sysfs */
144 strncat(path
, "_dri", sizeof(path
));
146 driver
= _eglOpenDriver(dpy
, path
);
158 * Called by eglCreateContext via drv->API.CreateContext().
161 _eglDRICreateContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
,
162 EGLContext share_list
, const EGLint
*attrib_list
)
164 driDisplay
*disp
= Lookup_driDisplay(dpy
);
165 driContext
*c
, *share
;
168 __GLcontextModes visMode
;
170 c
= (driContext
*) calloc(1, sizeof(*c
));
172 return EGL_NO_CONTEXT
;
174 conf
= _eglLookupConfig(drv
, dpy
, config
);
177 if (!_eglInitContext(drv
, &c
->Base
, conf
, attrib_list
)) {
179 return EGL_NO_CONTEXT
;
182 if (share_list
!= EGL_NO_CONTEXT
) {
183 _EGLContext
*shareCtx
= _eglLookupContext(share_list
);
185 _eglError(EGL_BAD_CONTEXT
, "eglCreateContext(share_list)");
189 share
= Lookup_driContext(share_list
);
191 sharePriv
= share
->driContext
.private;
195 _eglConfigToContextModesRec(conf
, &visMode
);
197 c
->driContext
.private = disp
->driScreen
.createNewContext(disp
, &visMode
,
198 GLX_WINDOW_BIT
, sharePriv
, &c
->driContext
);
199 if (!c
->driContext
.private) {
204 /* link to display */
205 _eglLinkContext(&c
->Base
, &disp
->Base
);
207 return _eglGetContextHandle(&c
->Base
);
212 _eglDRIMakeCurrent(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
,
213 EGLSurface read
, EGLContext context
)
215 driDisplay
*disp
= Lookup_driDisplay(dpy
);
216 driContext
*ctx
= Lookup_driContext(context
);
218 __DRIid drawBuf
= (__DRIid
) draw
;
219 __DRIid readBuf
= (__DRIid
) read
;
221 b
= _eglMakeCurrent(drv
, dpy
, draw
, read
, context
);
226 ctx
->driContext
.bindContext(disp
, 0, drawBuf
, readBuf
, &ctx
->driContext
);
230 /* _mesa_make_current( NULL, NULL, NULL );*/
237 _eglDRICreatePbufferSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
,
238 const EGLint
*attrib_list
)
243 conf
= _eglLookupConfig(drv
, dpy
, config
);
246 surf
= (driSurface
*) calloc(1, sizeof(*surf
));
248 return EGL_NO_SURFACE
;
251 if (!_eglInitSurface(drv
, &surf
->Base
, EGL_PBUFFER_BIT
,
252 conf
, attrib_list
)) {
254 return EGL_NO_SURFACE
;
257 /* create software-based pbuffer */
260 GLcontext
*ctx
= NULL
; /* this _should_ be OK */
262 __GLcontextModes visMode
;
263 _EGLConfig
*conf
= _eglLookupConfig(drv
, dpy
, config
);
264 assert(conf
); /* bad config should be caught earlier */
265 _eglConfigToContextModesRec(conf
, &visMode
);
268 surf
->mesa_framebuffer
= _mesa_create_framebuffer(&visMode
);
269 _mesa_add_soft_renderbuffers(surf
->mesa_framebuffer
,
270 GL_TRUE
, /* color bufs */
271 visMode
.haveDepthBuffer
,
272 visMode
.haveStencilBuffer
,
273 visMode
.haveAccumBuffer
,
274 GL_FALSE
, /* alpha */
275 GL_FALSE
/* aux */ );
277 /* set pbuffer/framebuffer size */
278 _mesa_resize_framebuffer(ctx
, surf
->mesa_framebuffer
,
279 surf
->Base
.Width
, surf
->Base
.Height
);
283 _eglLinkSurface(&surf
->Base
, _eglLookupDisplay(dpy
));
285 return surf
->Base
.Handle
;
290 _eglDRIDestroySurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
)
292 driDisplay
*disp
= Lookup_driDisplay(dpy
);
293 driSurface
*fs
= Lookup_driSurface(surface
);
295 _eglUnlinkSurface(&fs
->Base
);
297 fs
->drawable
.destroyDrawable(disp
, fs
->drawable
.private);
299 if (!_eglIsSurfaceBound(&fs
->Base
))
306 _eglDRIDestroyContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLContext context
)
308 driDisplay
*disp
= Lookup_driDisplay(dpy
);
309 driContext
*fc
= Lookup_driContext(context
);
311 _eglUnlinkContext(&fc
->Base
);
313 fc
->driContext
.destroyContext(disp
, 0, fc
->driContext
.private);
315 if (!_eglIsContextBound(&fc
->Base
))
322 * Create a drawing surface which can be directly displayed on a screen.
325 _eglDRICreateScreenSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig cfg
,
326 const EGLint
*attrib_list
)
328 _EGLConfig
*config
= _eglLookupConfig(drv
, dpy
, cfg
);
329 driDisplay
*disp
= Lookup_driDisplay(dpy
);
331 __GLcontextModes visMode
;
334 surface
= (driSurface
*) calloc(1, sizeof(*surface
));
336 return EGL_NO_SURFACE
;
339 /* init base class, do error checking, etc. */
340 if (!_eglInitSurface(drv
, &surface
->Base
, EGL_SCREEN_BIT_MESA
,
341 config
, attrib_list
)) {
343 return EGL_NO_SURFACE
;
346 _eglLinkSurface(&surface
->Base
&disp
->Base
);
350 * XXX this is where we should allocate video memory for the surface!
354 /* convert EGLConfig to GLvisual */
355 _eglConfigToContextModesRec(config
, &visMode
);
357 drawBuf
= (__DRIid
) _eglGetSurfaceHandle(&surface
->Base
);
359 /* Create a new DRI drawable */
360 if (!disp
->driScreen
.createNewDrawable(disp
, &visMode
, drawBuf
,
361 &surface
->drawable
, GLX_WINDOW_BIT
,
362 empty_attribute_list
)) {
363 _eglUnlinkSurface(&surface
->Base
);
365 return EGL_NO_SURFACE
;
368 return surface
->Base
.Handle
;
373 * Set the fbdev colormap to a simple linear ramp.
376 _eglDRILoadColormap(driScreen
*scrn
)
378 char path
[ NAME_MAX
];
382 /* cmap attribute uses 256 lines of 16 bytes.
383 * Allocate one extra char for the \0 added by sprintf()
385 if ( !( buffer
= malloc( 256 * 16 + 1 ) ) ) {
386 _eglLog(_EGL_WARNING
, "Out of memory in _eglDRILoadColormap");
390 /* cmap attribute uses 256 lines of 16 bytes */
391 for ( i
= 0; i
< 256; i
++ ) {
392 int c
= (i
<< 8) | i
; /* expand to 16-bit value */
393 sprintf(&buffer
[i
* 16], "%02x%c%04x%04x%04x\n", i
, ' ', c
, c
, c
);
396 snprintf(path
, sizeof(path
), "%s/graphics/%s/color_map", sysfs
, scrn
->fb
);
397 if ( !( fd
= open( path
, O_RDWR
) ) ) {
398 _eglLog(_EGL_WARNING
, "Unable to open %s to set colormap", path
);
401 write( fd
, buffer
, 256 * 16 );
409 * Show the given surface on the named screen.
410 * If surface is EGL_NO_SURFACE, disable the screen's output.
411 * Called via eglShowSurfaceMESA().
414 _eglDRIShowScreenSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
,
415 EGLScreenMESA screen
,
416 EGLSurface surface
, EGLModeMESA m
)
418 driDisplay
*display
= Lookup_driDisplay(dpy
);
419 driScreen
*scrn
= Lookup_driScreen(dpy
, screen
);
420 driSurface
*surf
= Lookup_driSurface(surface
);
421 _EGLMode
*mode
= _eglLookupMode(dpy
, m
);
423 char fname
[NAME_MAX
], buffer
[1000];
426 _eglLog(_EGL_DEBUG
, "Enter _eglDRIShowScreenSurface");
428 /* This will check that surface, screen, and mode are valid.
429 * Also, it checks that the surface is large enough for the mode, etc.
431 if (!_eglShowScreenSurfaceMESA(drv
, dpy
, screen
, surface
, m
))
434 assert(surface
== EGL_NO_SURFACE
|| surf
);
435 assert(m
== EGL_NO_MODE_MESA
|| mode
);
439 * Blank/unblank screen depending on if m == EGL_NO_MODE_MESA
441 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/blank", sysfs
, scrn
->fb
);
442 file
= fopen(fname
, "r+");
444 _eglLog(_EGL_WARNING
, "kernel patch?? chown all fb sysfs attrib to allow"
445 " write - %s\n", fname
);
448 snprintf(buffer
, sizeof(buffer
), "%d",
449 (m
== EGL_NO_MODE_MESA
? VESA_POWERDOWN
: VESA_VSYNC_SUSPEND
));
453 if (m
== EGL_NO_MODE_MESA
) {
458 _eglLog(_EGL_INFO
, "Setting display mode to %d x %d, %d bpp",
459 mode
->Width
, mode
->Height
, display
->bpp
);
462 * Set the display mode
464 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/mode", sysfs
, scrn
->fb
);
465 file
= fopen(fname
, "r+");
467 _eglLog(_EGL_WARNING
, "Failed to open %s to set mode", fname
);
470 /* note: nothing happens without the \n! */
471 snprintf(buffer
, sizeof(buffer
), "%s\n", mode
->Name
);
474 _eglLog(_EGL_INFO
, "Set mode to %s in %s", mode
->Name
, fname
);
479 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/bits_per_pixel",
481 file
= fopen(fname
, "r+");
483 _eglLog(_EGL_WARNING
, "Failed to open %s to set bpp", fname
);
486 display
->bpp
= GET_CONFIG_ATTRIB(surf
->Base
.Config
, EGL_BUFFER_SIZE
);
487 display
->cpp
= display
->bpp
/ 8;
488 snprintf(buffer
, sizeof(buffer
), "%d", display
->bpp
);
495 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/blank", sysfs
, scrn
->fb
);
496 file
= fopen(fname
, "r+");
498 _eglLog(_EGL_WARNING
, "Failed to open %s", fname
);
501 snprintf(buffer
, sizeof(buffer
), "%d", VESA_NO_BLANKING
);
506 * Set fbdev buffer virtual size to surface's size.
508 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/virtual_size", sysfs
, scrn
->fb
);
509 file
= fopen(fname
, "r+");
510 snprintf(buffer
, sizeof(buffer
), "%d,%d", surf
->Base
.Width
, surf
->Base
.Height
);
513 fgets(buffer
, sizeof(buffer
), file
);
514 sscanf(buffer
, "%d,%d", &display
->virtualWidth
, &display
->virtualHeight
);
518 * round up pitch as needed
520 temp
= display
->virtualWidth
;
521 switch (display
->bpp
/ 8) {
522 case 1: temp
= (display
->virtualWidth
+ 127) & ~127; break;
523 case 2: temp
= (display
->virtualWidth
+ 31) & ~31; break;
525 case 4: temp
= (display
->virtualWidth
+ 15) & ~15; break;
527 _eglLog(_EGL_WARNING
, "Bad display->bpp = %d in _eglDRIShowScreenSurface");
529 display
->virtualWidth
= temp
;
534 if (surf
->Base
.Width
< display
->virtualWidth
||
535 surf
->Base
.Height
< display
->virtualHeight
) {
536 /* this case _should_ have been caught at the top of this function */
537 _eglLog(_EGL_WARNING
, "too small of surface in _eglDRIShowScreenSurfaceMESA "
541 display
->virtualWidth
,
542 display
->virtualHeight
);
548 /* This used to be done in the _eglDRICreateScreens routine. */
549 _eglDRILoadColormap(scrn
);
556 * Called by eglSwapBuffers via the drv->API.SwapBuffers() pointer.
558 * If the backbuffer is on a videocard, this is extraordinarily slow!
561 _eglDRISwapBuffers(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
)
563 driSurface
*drawable
= Lookup_driSurface(draw
);
565 /* this does error checking */
566 if (!_eglSwapBuffers(drv
, dpy
, draw
))
569 drawable
->drawable
.swapBuffers(NULL
, drawable
->drawable
.private);
576 _eglDRIGetDisplayInfo(driDisplay
*dpy
)
578 char path
[ NAME_MAX
];
584 snprintf( path
, sizeof( path
), "%s/graphics/fb%d/device/device", sysfs
, dpy
->minor
);
585 file
= fopen( path
, "r" );
587 _eglLog(_EGL_WARNING
, "Unable to open %s", path
);
590 fgets( path
, sizeof( path
), file
);
591 sscanf( path
, "%x", &dpy
->chipset
);
594 sprintf(path
, DRM_DEV_NAME
, DRM_DIR_NAME
, dpy
->minor
);
595 if ( ( dpy
->drmFD
= open(path
, O_RDWR
, 0) ) < 0 ) {
596 _eglLog(_EGL_WARNING
, "drmOpen failed.");
600 /* Set the interface version, asking for 1.2 */
603 sv
.drm_dd_major
= -1;
604 if ((rc
= drmSetInterfaceVersion(dpy
->drmFD
, &sv
)))
608 if (drmGetMagic(dpy
->drmFD
, &magic
))
610 if (drmAuthMagic(dpy
->drmFD
, magic
))
613 /* Map framebuffer and SAREA */
615 drm_handle_t handle
, offset
;
621 if (drmGetMap(dpy
->drmFD
, i
, &offset
, &size
, &type
, &flags
,
625 if (type
== DRM_FRAME_BUFFER
) {
626 rc
= drmMap( dpy
->drmFD
, offset
, size
, (drmAddressPtr
) &dpy
->pFB
);
628 _eglLog(_EGL_WARNING
, "drmMap DRM_FAME_BUFFER failed");
632 _eglLog(_EGL_INFO
, "Found framebuffer size: %d", dpy
->fbSize
);
634 else if (type
== DRM_SHM
) {
635 rc
= drmMap(dpy
->drmFD
, offset
, size
, (drmAddressPtr
) &dpy
->pSAREA
);
637 _eglLog(_EGL_WARNING
, "drmMap DRM_SHM failed.");
640 dpy
->SAREASize
= SAREA_MAX
;
641 _eglLog(_EGL_DEBUG
, "mapped SAREA 0x%08lx to %p, size %d",
642 (unsigned long) offset
, dpy
->pSAREA
, dpy
->SAREASize
);
647 _eglLog(_EGL_WARNING
, "failed to map framebuffer");
652 /* if this happens, make sure you're using the most recent DRM modules */
653 _eglLog(_EGL_WARNING
, "failed to map SAREA");
657 memset( dpy
->pSAREA
, 0, dpy
->SAREASize
);
663 /* Return the DRI per screen structure */
665 __eglFindDRIScreen(__DRInativeDisplay
*ndpy
, int scrn
)
667 driDisplay
*disp
= (driDisplay
*)ndpy
;
668 return &disp
->driScreen
;
673 __eglCreateContextWithConfig(__DRInativeDisplay
* ndpy
, int screen
,
674 int configID
, void* context
,
675 drm_context_t
* hHWContext
)
677 __DRIscreen
*pDRIScreen
;
678 __DRIscreenPrivate
*psp
;
680 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
681 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
684 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
686 if (drmCreateContext(psp
->fd
, hHWContext
)) {
687 _eglLog(_EGL_WARNING
, "drmCreateContext failed.");
690 *(void**)context
= (void*) *hHWContext
;
693 __DRIscreen
*pDRIScreen
;
694 __DRIscreenPrivate
*psp
;
696 pDRIScreen
= __glXFindDRIScreen(dpy
, screen
);
697 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
701 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
704 if (drmCreateContext(psp
->fd
, hHWContext
)) {
705 _eglLog(_EGL_WARNING
, "drmCreateContext failed.");
708 *(void**)contextID
= (void*) *hHWContext
;
716 __eglDestroyContext( __DRInativeDisplay
* ndpy
, int screen
, __DRIid context
)
718 __DRIscreen
*pDRIScreen
;
719 __DRIscreenPrivate
*psp
;
721 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
722 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
725 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
727 drmDestroyContext(psp
->fd
, context
);
734 __eglCreateDrawable(__DRInativeDisplay
* ndpy
, int screen
,
735 __DRIid drawable
, drm_drawable_t
* hHWDrawable
)
737 __DRIscreen
*pDRIScreen
;
738 __DRIscreenPrivate
*psp
;
740 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
741 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
744 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
746 if (drmCreateDrawable(psp
->fd
, hHWDrawable
)) {
747 _eglLog(_EGL_WARNING
, "drmCreateDrawable failed.");
756 __eglDestroyDrawable( __DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
)
758 __DRIscreen
*pDRIScreen
;
759 __DRIscreenPrivate
*psp
;
761 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
762 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
765 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
767 drmDestroyDrawable(psp
->fd
, drawable
);
773 __eglGetDrawableInfo(__DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
,
774 unsigned int* index
, unsigned int* stamp
,
775 int* X
, int* Y
, int* W
, int* H
,
776 int* numClipRects
, drm_clip_rect_t
** pClipRects
,
777 int* backX
, int* backY
,
778 int* numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
780 __DRIscreen
*pDRIScreen
;
781 __DRIscreenPrivate
*psp
;
782 driSurface
*surf
= Lookup_driSurface((EGLSurface
) drawable
);
784 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
786 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
789 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
792 *W
= surf
->Base
.Width
;
793 *H
= surf
->Base
.Height
;
797 *numBackClipRects
= 0;
798 *pBackClipRects
= NULL
;
801 *pClipRects
= malloc(sizeof(**pClipRects
));
802 **pClipRects
= (drm_clip_rect_t
){0, 0, surf
->Base
.Width
, surf
->Base
.Height
};
804 psp
->pSAREA
->drawableTable
[0].stamp
= 1;
807 GLXDrawable drawable
= (GLXDrawable
) draw
;
808 drm_clip_rect_t
* cliprect
;
809 Display
* display
= (Display
*)dpy
;
810 __DRIcontextPrivate
*pcp
= (__DRIcontextPrivate
*)CurrentContext
->driContext
.private;
815 cliprect
= (drm_clip_rect_t
*) _mesa_malloc(sizeof(drm_clip_rect_t
));
816 cliprect
->x1
= drawable
->x
;
817 cliprect
->y1
= drawable
->y
;
818 cliprect
->x2
= drawable
->x
+ drawable
->w
;
819 cliprect
->y2
= drawable
->y
+ drawable
->h
;
821 /* the drawable index is by client id */
822 *index
= display
->clientID
;
824 *stamp
= pcp
->driScreenPriv
->pSAREA
->drawableTable
[display
->clientID
].stamp
;
827 *width
= drawable
->w
;
828 *height
= drawable
->h
;
830 *pClipRects
= cliprect
;
832 *backX
= drawable
->x
;
833 *backY
= drawable
->y
;
834 *numBackClipRects
= 0;
842 * Implement \c __DRIinterfaceMethods::getProcAddress.
845 get_proc_address(const char * proc_name
)
852 * Destroy a linked list of \c __GLcontextModes structures created by
853 * \c _gl_context_modes_create.
855 * \param modes Linked list of structures to be destroyed. All structres
856 * in the list will be freed.
859 __egl_context_modes_destroy(__GLcontextModes
*modes
)
861 while ( modes
!= NULL
) {
862 __GLcontextModes
* const next
= modes
->next
;
871 * Allocate a linked list of \c __GLcontextModes structures. The fields of
872 * each structure will be initialized to "reasonable" default values. In
873 * most cases this is the default value defined by table 3.4 of the GLX
874 * 1.3 specification. This means that most values are either initialized to
875 * zero or \c GLX_DONT_CARE (which is -1). As support for additional
876 * extensions is added, the new values will be initialized to appropriate
877 * values from the extension specification.
879 * \param count Number of structures to allocate.
880 * \param minimum_size Minimum size of a structure to allocate. This allows
881 * for differences in the version of the
882 * \c __GLcontextModes stucture used in libGL and in a
884 * \returns A pointer to the first element in a linked list of \c count
885 * stuctures on success, or \c NULL on failure.
887 * \warning Use of \c minimum_size does \b not guarantee binary compatibility.
888 * The fundamental assumption is that if the \c minimum_size
889 * specified by the driver and the size of the \c __GLcontextModes
890 * structure in libGL is the same, then the meaning of each byte in
891 * the structure is the same in both places. \b Be \b careful!
892 * Basically this means that fields have to be added in libGL and
893 * then propagated to drivers. Drivers should \b never arbitrarilly
894 * extend the \c __GLcontextModes data-structure.
896 static __GLcontextModes
*
897 __egl_context_modes_create(unsigned count
, size_t minimum_size
)
899 const size_t size
= (minimum_size
> sizeof( __GLcontextModes
))
900 ? minimum_size
: sizeof( __GLcontextModes
);
901 __GLcontextModes
* base
= NULL
;
902 __GLcontextModes
** next
;
906 for ( i
= 0 ; i
< count
; i
++ ) {
907 *next
= (__GLcontextModes
*) malloc( size
);
908 if ( *next
== NULL
) {
909 __egl_context_modes_destroy( base
);
914 (void) memset( *next
, 0, size
);
915 (*next
)->visualID
= GLX_DONT_CARE
;
916 (*next
)->visualType
= GLX_DONT_CARE
;
917 (*next
)->visualRating
= GLX_NONE
;
918 (*next
)->transparentPixel
= GLX_NONE
;
919 (*next
)->transparentRed
= GLX_DONT_CARE
;
920 (*next
)->transparentGreen
= GLX_DONT_CARE
;
921 (*next
)->transparentBlue
= GLX_DONT_CARE
;
922 (*next
)->transparentAlpha
= GLX_DONT_CARE
;
923 (*next
)->transparentIndex
= GLX_DONT_CARE
;
924 (*next
)->xRenderable
= GLX_DONT_CARE
;
925 (*next
)->fbconfigID
= GLX_DONT_CARE
;
926 (*next
)->swapMethod
= GLX_SWAP_UNDEFINED_OML
;
928 next
= & ((*next
)->next
);
936 __eglWindowExists(__DRInativeDisplay
*dpy
, __DRIid draw
)
943 * Get the unadjusted system time (UST). Currently, the UST is measured in
944 * microseconds since Epoc. The actual resolution of the UST may vary from
945 * system to system, and the units may vary from release to release.
946 * Drivers should not call this function directly. They should instead use
947 * \c glXGetProcAddress to obtain a pointer to the function.
949 * \param ust Location to store the 64-bit UST
950 * \returns Zero on success or a negative errno value on failure.
952 * \sa glXGetProcAddress, PFNGLXGETUSTPROC
954 * \since Internal API version 20030317.
957 __eglGetUST(int64_t *ust
)
965 if ( gettimeofday( & tv
, NULL
) == 0 ) {
966 ust
[0] = (tv
.tv_sec
* 1000000) + tv
.tv_usec
;
975 * Determine the refresh rate of the specified drawable and display.
977 * \param dpy Display whose refresh rate is to be determined.
978 * \param drawable Drawable whose refresh rate is to be determined.
979 * \param numerator Numerator of the refresh rate.
980 * \param demoninator Denominator of the refresh rate.
981 * \return If the refresh rate for the specified display and drawable could
982 * be calculated, True is returned. Otherwise False is returned.
984 * \note This function is implemented entirely client-side. A lot of other
985 * functionality is required to export GLX_OML_sync_control, so on
986 * XFree86 this function can be called for direct-rendering contexts
987 * when GLX_OML_sync_control appears in the client extension string.
990 __eglGetMSCRate(__DRInativeDisplay
* dpy
, __DRIid drawable
,
991 int32_t * numerator
, int32_t * denominator
)
998 * Table of functions exported by the loader to the driver.
1000 static const __DRIinterfaceMethods interface_methods
= {
1003 __egl_context_modes_create
,
1004 __egl_context_modes_destroy
,
1009 __eglCreateContextWithConfig
,
1010 __eglDestroyContext
,
1012 __eglCreateDrawable
,
1013 __eglDestroyDrawable
,
1014 __eglGetDrawableInfo
,
1022 __glXGetInternalVersion(void)
1027 static const char createNewScreenName
[] = "__driCreateNewScreen_20050727";
1031 * Do per-display initialization.
1034 _eglDRICreateDisplay(driDisplay
*dpy
, __DRIframebuffer
*framebuffer
)
1036 PFNCREATENEWSCREENFUNC createNewScreen
;
1037 int api_ver
= __glXGetInternalVersion();
1038 __DRIversion ddx_version
;
1039 __DRIversion dri_version
;
1040 __DRIversion drm_version
;
1041 drmVersionPtr version
;
1043 version
= drmGetVersion( dpy
->drmFD
);
1045 drm_version
.major
= version
->version_major
;
1046 drm_version
.minor
= version
->version_minor
;
1047 drm_version
.patch
= version
->version_patchlevel
;
1048 drmFreeVersion( version
);
1051 drm_version
.major
= -1;
1052 drm_version
.minor
= -1;
1053 drm_version
.patch
= -1;
1057 * Get device name (like "tdfx") and the ddx version numbers.
1058 * We'll check the version in each DRI driver's "createScreen"
1061 ddx_version
.major
= 4;
1062 ddx_version
.minor
= 0;
1063 ddx_version
.patch
= 0;
1066 * Get the DRI X extension version.
1068 dri_version
.major
= 4;
1069 dri_version
.minor
= 0;
1070 dri_version
.patch
= 0;
1072 createNewScreen
= ( PFNCREATENEWSCREENFUNC
) dlsym( dpy
->Base
.Driver
->LibHandle
, createNewScreenName
);
1073 if ( !createNewScreen
) {
1074 _eglLog(_EGL_WARNING
, "Couldn't find %s function in the driver.",
1075 createNewScreenName
);
1079 dpy
->driScreen
.private = createNewScreen( dpy
, 0, &dpy
->driScreen
, NULL
,
1080 &ddx_version
, &dri_version
,
1081 &drm_version
, framebuffer
,
1082 dpy
->pSAREA
, dpy
->drmFD
,
1084 & interface_methods
,
1086 if (!dpy
->driScreen
.private) {
1087 _eglLog(_EGL_WARNING
, "egldri.c: DRI create new screen failed");
1091 DRM_UNLOCK( dpy
->drmFD
, dpy
->pSAREA
, dpy
->serverContext
);
1098 * Create all the EGL screens for the given display.
1101 _eglDRICreateScreens(driDisplay
*dpy
)
1103 const int numScreens
= 1; /* XXX fix this someday */
1106 for (i
= 0; i
< numScreens
; i
++) {
1107 char path
[ NAME_MAX
];
1111 /* Create a screen */
1112 if ( !( s
= ( driScreen
* ) calloc( 1, sizeof( *s
) ) ) )
1115 snprintf( s
->fb
, NAME_MAX
, "fb%d", dpy
->minor
);
1116 _eglInitScreen( &s
->Base
);
1118 _eglAddScreen( &dpy
->Base
, &s
->Base
);
1120 /* Create the screen's mode list */
1121 snprintf( path
, sizeof( path
), "%s/graphics/%s/modes", sysfs
, s
->fb
);
1122 file
= fopen( path
, "r" );
1123 while ( fgets( path
, sizeof( path
), file
) ) {
1124 unsigned int x
, y
, r
;
1126 path
[ strlen( path
) - 1 ] = '\0'; /* strip off \n from sysfs */
1127 sscanf( path
, "%c:%ux%u-%u", &c
, &x
, &y
, &r
);
1128 _eglAddNewMode( &s
->Base
, x
, y
, r
* 1000, path
);
1133 * NOTE: we used to set the colormap here, but that didn't work reliably.
1134 * Some entries near the start of the table would get corrupted by later
1144 _eglDRIInitialize(_EGLDriver
*drv
, EGLDisplay dpy
,
1145 EGLint
*major
, EGLint
*minor
)
1147 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
1148 driDisplay
*display
;
1149 const char *driverName
= (const char *) disp
->NativeDisplay
;
1153 /* Create new driDisplay object to replace the _EGLDisplay that was
1154 * previously created.
1156 display
= calloc(1, sizeof(*display
));
1157 display
->Base
= *disp
;
1158 _eglSaveDisplay(&display
->Base
);
1164 sscanf(driverName
+ 1, "%d", &display
->minor
);
1166 drv
->Initialized
= EGL_TRUE
;
1172 _eglDRITerminate(_EGLDriver
*drv
, EGLDisplay dpy
)
1174 driDisplay
*display
= Lookup_driDisplay(dpy
);
1175 _eglCleanupDisplay(&display
->Base
);/*rename that function*/
1183 * Plug in the DRI-specific functions into the driver's dispatch table.
1184 * Also, enable some EGL extensions.
1187 _eglDRIInitDriverFallbacks(_EGLDriver
*drv
)
1189 _eglInitDriverFallbacks(drv
);
1191 drv
->API
.Initialize
= _eglDRIInitialize
;
1192 drv
->API
.Terminate
= _eglDRITerminate
;
1193 drv
->API
.CreateContext
= _eglDRICreateContext
;
1194 drv
->API
.MakeCurrent
= _eglDRIMakeCurrent
;
1195 drv
->API
.CreatePbufferSurface
= _eglDRICreatePbufferSurface
;
1196 drv
->API
.DestroySurface
= _eglDRIDestroySurface
;
1197 drv
->API
.DestroyContext
= _eglDRIDestroyContext
;
1198 drv
->API
.CreateScreenSurfaceMESA
= _eglDRICreateScreenSurfaceMESA
;
1199 drv
->API
.ShowScreenSurfaceMESA
= _eglDRIShowScreenSurfaceMESA
;
1200 drv
->API
.SwapBuffers
= _eglDRISwapBuffers
;
1202 /* enable supported extensions */
1203 drv
->Extensions
.MESA_screen_surface
= EGL_TRUE
;
1204 drv
->Extensions
.MESA_copy_context
= EGL_TRUE
;