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 char *displayString
= (const char *) dpy
->NativeDisplay
;
86 const int card
= atoi(args
);
87 _EGLDriver
*driver
= NULL
;
88 char driverName
[1000];
90 if (!driver_name_from_card_number(card
, driverName
, sizeof(driverName
))) {
92 "Unable to determine driver name for card %d\n", card
);
96 _eglLog(_EGL_DEBUG
, "Driver name: %s\n", driverName
);
98 driver
= _eglOpenDriver(dpy
, driverName
);
106 struct dirent
*dirent
;
111 _EGLDriver
*driver
= NULL
;;
113 snprintf(path
, sizeof(path
), "%s/drm", sysfs
);
114 if (!(dir
= opendir(path
))) {
115 _eglLog(_EGL_WARNING
, "%s DRM devices not found.", path
);
118 while ((dirent
= readdir(dir
))) {
120 if (strncmp(&dirent
->d_name
[0], "card", 4) != 0)
122 if (strcmp(&dirent
->d_name
[4], &driverName
[1]) != 0)
125 snprintf(path
, sizeof(path
), "%s/drm/card%s/dri_library_name",
126 sysfs
, &driverName
[1]);
127 _eglLog(_EGL_INFO
, "Opening %s", path
);
129 file
= fopen(path
, "r");
131 _eglLog(_EGL_WARNING
, "Failed to open %s", path
);
134 fgets(path
, sizeof(path
), file
);
137 strcpy(path
, "r200\n");
139 if ((length
= strlen(path
)) > 0)
140 path
[length
- 1] = '\0'; /* remove the trailing newline from sysfs */
141 strncat(path
, "_dri", sizeof(path
));
143 driver
= _eglOpenDriver(dpy
, path
);
155 * Called by eglCreateContext via drv->API.CreateContext().
158 _eglDRICreateContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
,
159 EGLContext share_list
, const EGLint
*attrib_list
)
161 driDisplay
*disp
= Lookup_driDisplay(dpy
);
162 driContext
*c
, *share
;
165 __GLcontextModes visMode
;
167 c
= (driContext
*) calloc(1, sizeof(*c
));
169 return EGL_NO_CONTEXT
;
171 if (!_eglInitContext(drv
, dpy
, &c
->Base
, config
, attrib_list
)) {
173 return EGL_NO_CONTEXT
;
176 if (share_list
!= EGL_NO_CONTEXT
) {
177 _EGLContext
*shareCtx
= _eglLookupContext(share_list
);
179 _eglError(EGL_BAD_CONTEXT
, "eglCreateContext(share_list)");
183 share
= Lookup_driContext(share_list
);
185 sharePriv
= share
->driContext
.private;
189 conf
= _eglLookupConfig(drv
, dpy
, config
);
191 _eglConfigToContextModesRec(conf
, &visMode
);
193 c
->driContext
.private = disp
->driScreen
.createNewContext(disp
, &visMode
,
194 GLX_WINDOW_BIT
, sharePriv
, &c
->driContext
);
195 if (!c
->driContext
.private) {
200 /* generate handle and insert into hash table */
201 _eglSaveContext(&c
->Base
);
203 return _eglGetContextHandle(&c
->Base
);
208 _eglDRIMakeCurrent(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
,
209 EGLSurface read
, EGLContext context
)
211 driDisplay
*disp
= Lookup_driDisplay(dpy
);
212 driContext
*ctx
= Lookup_driContext(context
);
214 __DRIid drawBuf
= (__DRIid
) draw
;
215 __DRIid readBuf
= (__DRIid
) read
;
217 b
= _eglMakeCurrent(drv
, dpy
, draw
, read
, context
);
222 ctx
->driContext
.bindContext(disp
, 0, drawBuf
, readBuf
, &ctx
->driContext
);
226 /* _mesa_make_current( NULL, NULL, NULL );*/
233 _eglDRICreatePbufferSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
,
234 const EGLint
*attrib_list
)
238 surf
= (driSurface
*) calloc(1, sizeof(*surf
));
240 return EGL_NO_SURFACE
;
243 if (!_eglInitSurface(drv
, dpy
, &surf
->Base
, EGL_PBUFFER_BIT
,
244 config
, attrib_list
)) {
246 return EGL_NO_SURFACE
;
249 /* create software-based pbuffer */
252 GLcontext
*ctx
= NULL
; /* this _should_ be OK */
254 __GLcontextModes visMode
;
255 _EGLConfig
*conf
= _eglLookupConfig(drv
, dpy
, config
);
256 assert(conf
); /* bad config should be caught earlier */
257 _eglConfigToContextModesRec(conf
, &visMode
);
260 surf
->mesa_framebuffer
= _mesa_create_framebuffer(&visMode
);
261 _mesa_add_soft_renderbuffers(surf
->mesa_framebuffer
,
262 GL_TRUE
, /* color bufs */
263 visMode
.haveDepthBuffer
,
264 visMode
.haveStencilBuffer
,
265 visMode
.haveAccumBuffer
,
266 GL_FALSE
, /* alpha */
267 GL_FALSE
/* aux */ );
269 /* set pbuffer/framebuffer size */
270 _mesa_resize_framebuffer(ctx
, surf
->mesa_framebuffer
,
271 surf
->Base
.Width
, surf
->Base
.Height
);
275 _eglSaveSurface(&surf
->Base
);
277 return surf
->Base
.Handle
;
282 _eglDRIDestroySurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
)
284 driDisplay
*disp
= Lookup_driDisplay(dpy
);
285 driSurface
*fs
= Lookup_driSurface(surface
);
287 _eglRemoveSurface(&fs
->Base
);
289 fs
->drawable
.destroyDrawable(disp
, fs
->drawable
.private);
291 if (fs
->Base
.IsBound
) {
292 fs
->Base
.DeletePending
= EGL_TRUE
;
302 _eglDRIDestroyContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLContext context
)
304 driDisplay
*disp
= Lookup_driDisplay(dpy
);
305 driContext
*fc
= Lookup_driContext(context
);
307 _eglRemoveContext(&fc
->Base
);
309 fc
->driContext
.destroyContext(disp
, 0, fc
->driContext
.private);
311 if (fc
->Base
.IsBound
) {
312 fc
->Base
.DeletePending
= EGL_TRUE
;
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
, dpy
, &surface
->Base
, EGL_SCREEN_BIT_MESA
,
343 return EGL_NO_SURFACE
;
346 _eglSaveSurface(&surface
->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 _eglRemoveSurface(&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)
1089 DRM_UNLOCK( dpy
->drmFD
, dpy
->pSAREA
, dpy
->serverContext
);
1096 * Create all the EGL screens for the given display.
1099 _eglDRICreateScreens(driDisplay
*dpy
)
1101 const int numScreens
= 1; /* XXX fix this someday */
1104 for (i
= 0; i
< numScreens
; i
++) {
1105 char path
[ NAME_MAX
];
1109 /* Create a screen */
1110 if ( !( s
= ( driScreen
* ) calloc( 1, sizeof( *s
) ) ) )
1113 snprintf( s
->fb
, NAME_MAX
, "fb%d", dpy
->minor
);
1114 _eglInitScreen( &s
->Base
);
1116 _eglAddScreen( &dpy
->Base
, &s
->Base
);
1118 /* Create the screen's mode list */
1119 snprintf( path
, sizeof( path
), "%s/graphics/%s/modes", sysfs
, s
->fb
);
1120 file
= fopen( path
, "r" );
1121 while ( fgets( path
, sizeof( path
), file
) ) {
1122 unsigned int x
, y
, r
;
1124 path
[ strlen( path
) - 1 ] = '\0'; /* strip off \n from sysfs */
1125 sscanf( path
, "%c:%ux%u-%u", &c
, &x
, &y
, &r
);
1126 _eglAddNewMode( &s
->Base
, x
, y
, r
* 1000, path
);
1131 * NOTE: we used to set the colormap here, but that didn't work reliably.
1132 * Some entries near the start of the table would get corrupted by later
1142 _eglDRIInitialize(_EGLDriver
*drv
, EGLDisplay dpy
,
1143 EGLint
*major
, EGLint
*minor
)
1145 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
1146 driDisplay
*display
;
1147 const char *driverName
= (const char *) disp
->NativeDisplay
;
1151 /* Create new driDisplay object to replace the _EGLDisplay that was
1152 * previously created.
1154 display
= calloc(1, sizeof(*display
));
1155 display
->Base
= *disp
;
1156 _eglSaveDisplay(&display
->Base
);
1162 sscanf(driverName
+ 1, "%d", &display
->minor
);
1164 drv
->Initialized
= EGL_TRUE
;
1170 _eglDRITerminate(_EGLDriver
*drv
, EGLDisplay dpy
)
1172 driDisplay
*display
= Lookup_driDisplay(dpy
);
1173 _eglCleanupDisplay(&display
->Base
);/*rename that function*/
1181 * Plug in the DRI-specific functions into the driver's dispatch table.
1182 * Also, enable some EGL extensions.
1185 _eglDRIInitDriverFallbacks(_EGLDriver
*drv
)
1187 _eglInitDriverFallbacks(drv
);
1189 drv
->API
.Initialize
= _eglDRIInitialize
;
1190 drv
->API
.Terminate
= _eglDRITerminate
;
1191 drv
->API
.CreateContext
= _eglDRICreateContext
;
1192 drv
->API
.MakeCurrent
= _eglDRIMakeCurrent
;
1193 drv
->API
.CreatePbufferSurface
= _eglDRICreatePbufferSurface
;
1194 drv
->API
.DestroySurface
= _eglDRIDestroySurface
;
1195 drv
->API
.DestroyContext
= _eglDRIDestroyContext
;
1196 drv
->API
.CreateScreenSurfaceMESA
= _eglDRICreateScreenSurfaceMESA
;
1197 drv
->API
.ShowScreenSurfaceMESA
= _eglDRIShowScreenSurfaceMESA
;
1198 drv
->API
.SwapBuffers
= _eglDRISwapBuffers
;
1200 /* enable supported extensions */
1201 drv
->Extensions
.MESA_screen_surface
= EGL_TRUE
;
1202 drv
->Extensions
.MESA_copy_context
= EGL_TRUE
;