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
= atoi(args
);
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 if (!_eglInitContext(drv
, dpy
, &c
->Base
, config
, attrib_list
)) {
176 return EGL_NO_CONTEXT
;
179 if (share_list
!= EGL_NO_CONTEXT
) {
180 _EGLContext
*shareCtx
= _eglLookupContext(share_list
);
182 _eglError(EGL_BAD_CONTEXT
, "eglCreateContext(share_list)");
186 share
= Lookup_driContext(share_list
);
188 sharePriv
= share
->driContext
.private;
192 conf
= _eglLookupConfig(drv
, dpy
, config
);
194 _eglConfigToContextModesRec(conf
, &visMode
);
196 c
->driContext
.private = disp
->driScreen
.createNewContext(disp
, &visMode
,
197 GLX_WINDOW_BIT
, sharePriv
, &c
->driContext
);
198 if (!c
->driContext
.private) {
203 /* generate handle and insert into hash table */
204 _eglSaveContext(&c
->Base
);
206 return _eglGetContextHandle(&c
->Base
);
211 _eglDRIMakeCurrent(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
,
212 EGLSurface read
, EGLContext context
)
214 driDisplay
*disp
= Lookup_driDisplay(dpy
);
215 driContext
*ctx
= Lookup_driContext(context
);
217 __DRIid drawBuf
= (__DRIid
) draw
;
218 __DRIid readBuf
= (__DRIid
) read
;
220 b
= _eglMakeCurrent(drv
, dpy
, draw
, read
, context
);
225 ctx
->driContext
.bindContext(disp
, 0, drawBuf
, readBuf
, &ctx
->driContext
);
229 /* _mesa_make_current( NULL, NULL, NULL );*/
236 _eglDRICreatePbufferSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
,
237 const EGLint
*attrib_list
)
241 surf
= (driSurface
*) calloc(1, sizeof(*surf
));
243 return EGL_NO_SURFACE
;
246 if (!_eglInitSurface(drv
, dpy
, &surf
->Base
, EGL_PBUFFER_BIT
,
247 config
, attrib_list
)) {
249 return EGL_NO_SURFACE
;
252 /* create software-based pbuffer */
255 GLcontext
*ctx
= NULL
; /* this _should_ be OK */
257 __GLcontextModes visMode
;
258 _EGLConfig
*conf
= _eglLookupConfig(drv
, dpy
, config
);
259 assert(conf
); /* bad config should be caught earlier */
260 _eglConfigToContextModesRec(conf
, &visMode
);
263 surf
->mesa_framebuffer
= _mesa_create_framebuffer(&visMode
);
264 _mesa_add_soft_renderbuffers(surf
->mesa_framebuffer
,
265 GL_TRUE
, /* color bufs */
266 visMode
.haveDepthBuffer
,
267 visMode
.haveStencilBuffer
,
268 visMode
.haveAccumBuffer
,
269 GL_FALSE
, /* alpha */
270 GL_FALSE
/* aux */ );
272 /* set pbuffer/framebuffer size */
273 _mesa_resize_framebuffer(ctx
, surf
->mesa_framebuffer
,
274 surf
->Base
.Width
, surf
->Base
.Height
);
278 _eglSaveSurface(&surf
->Base
);
280 return surf
->Base
.Handle
;
285 _eglDRIDestroySurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
)
287 driDisplay
*disp
= Lookup_driDisplay(dpy
);
288 driSurface
*fs
= Lookup_driSurface(surface
);
290 _eglRemoveSurface(&fs
->Base
);
292 fs
->drawable
.destroyDrawable(disp
, fs
->drawable
.private);
294 if (fs
->Base
.IsBound
) {
295 fs
->Base
.DeletePending
= EGL_TRUE
;
305 _eglDRIDestroyContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLContext context
)
307 driDisplay
*disp
= Lookup_driDisplay(dpy
);
308 driContext
*fc
= Lookup_driContext(context
);
310 _eglRemoveContext(&fc
->Base
);
312 fc
->driContext
.destroyContext(disp
, 0, fc
->driContext
.private);
314 if (fc
->Base
.IsBound
) {
315 fc
->Base
.DeletePending
= EGL_TRUE
;
325 * Create a drawing surface which can be directly displayed on a screen.
328 _eglDRICreateScreenSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig cfg
,
329 const EGLint
*attrib_list
)
331 _EGLConfig
*config
= _eglLookupConfig(drv
, dpy
, cfg
);
332 driDisplay
*disp
= Lookup_driDisplay(dpy
);
334 __GLcontextModes visMode
;
337 surface
= (driSurface
*) calloc(1, sizeof(*surface
));
339 return EGL_NO_SURFACE
;
342 /* init base class, do error checking, etc. */
343 if (!_eglInitSurface(drv
, dpy
, &surface
->Base
, EGL_SCREEN_BIT_MESA
,
346 return EGL_NO_SURFACE
;
349 _eglSaveSurface(&surface
->Base
);
353 * XXX this is where we should allocate video memory for the surface!
357 /* convert EGLConfig to GLvisual */
358 _eglConfigToContextModesRec(config
, &visMode
);
360 drawBuf
= (__DRIid
) _eglGetSurfaceHandle(&surface
->Base
);
362 /* Create a new DRI drawable */
363 if (!disp
->driScreen
.createNewDrawable(disp
, &visMode
, drawBuf
,
364 &surface
->drawable
, GLX_WINDOW_BIT
,
365 empty_attribute_list
)) {
366 _eglRemoveSurface(&surface
->Base
);
368 return EGL_NO_SURFACE
;
371 return surface
->Base
.Handle
;
376 * Set the fbdev colormap to a simple linear ramp.
379 _eglDRILoadColormap(driScreen
*scrn
)
381 char path
[ NAME_MAX
];
385 /* cmap attribute uses 256 lines of 16 bytes.
386 * Allocate one extra char for the \0 added by sprintf()
388 if ( !( buffer
= malloc( 256 * 16 + 1 ) ) ) {
389 _eglLog(_EGL_WARNING
, "Out of memory in _eglDRILoadColormap");
393 /* cmap attribute uses 256 lines of 16 bytes */
394 for ( i
= 0; i
< 256; i
++ ) {
395 int c
= (i
<< 8) | i
; /* expand to 16-bit value */
396 sprintf(&buffer
[i
* 16], "%02x%c%04x%04x%04x\n", i
, ' ', c
, c
, c
);
399 snprintf(path
, sizeof(path
), "%s/graphics/%s/color_map", sysfs
, scrn
->fb
);
400 if ( !( fd
= open( path
, O_RDWR
) ) ) {
401 _eglLog(_EGL_WARNING
, "Unable to open %s to set colormap", path
);
404 write( fd
, buffer
, 256 * 16 );
412 * Show the given surface on the named screen.
413 * If surface is EGL_NO_SURFACE, disable the screen's output.
414 * Called via eglShowSurfaceMESA().
417 _eglDRIShowScreenSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
,
418 EGLScreenMESA screen
,
419 EGLSurface surface
, EGLModeMESA m
)
421 driDisplay
*display
= Lookup_driDisplay(dpy
);
422 driScreen
*scrn
= Lookup_driScreen(dpy
, screen
);
423 driSurface
*surf
= Lookup_driSurface(surface
);
424 _EGLMode
*mode
= _eglLookupMode(dpy
, m
);
426 char fname
[NAME_MAX
], buffer
[1000];
429 _eglLog(_EGL_DEBUG
, "Enter _eglDRIShowScreenSurface");
431 /* This will check that surface, screen, and mode are valid.
432 * Also, it checks that the surface is large enough for the mode, etc.
434 if (!_eglShowScreenSurfaceMESA(drv
, dpy
, screen
, surface
, m
))
437 assert(surface
== EGL_NO_SURFACE
|| surf
);
438 assert(m
== EGL_NO_MODE_MESA
|| mode
);
442 * Blank/unblank screen depending on if m == EGL_NO_MODE_MESA
444 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/blank", sysfs
, scrn
->fb
);
445 file
= fopen(fname
, "r+");
447 _eglLog(_EGL_WARNING
, "kernel patch?? chown all fb sysfs attrib to allow"
448 " write - %s\n", fname
);
451 snprintf(buffer
, sizeof(buffer
), "%d",
452 (m
== EGL_NO_MODE_MESA
? VESA_POWERDOWN
: VESA_VSYNC_SUSPEND
));
456 if (m
== EGL_NO_MODE_MESA
) {
461 _eglLog(_EGL_INFO
, "Setting display mode to %d x %d, %d bpp",
462 mode
->Width
, mode
->Height
, display
->bpp
);
465 * Set the display mode
467 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/mode", sysfs
, scrn
->fb
);
468 file
= fopen(fname
, "r+");
470 _eglLog(_EGL_WARNING
, "Failed to open %s to set mode", fname
);
473 /* note: nothing happens without the \n! */
474 snprintf(buffer
, sizeof(buffer
), "%s\n", mode
->Name
);
477 _eglLog(_EGL_INFO
, "Set mode to %s in %s", mode
->Name
, fname
);
482 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/bits_per_pixel",
484 file
= fopen(fname
, "r+");
486 _eglLog(_EGL_WARNING
, "Failed to open %s to set bpp", fname
);
489 display
->bpp
= GET_CONFIG_ATTRIB(surf
->Base
.Config
, EGL_BUFFER_SIZE
);
490 display
->cpp
= display
->bpp
/ 8;
491 snprintf(buffer
, sizeof(buffer
), "%d", display
->bpp
);
498 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/blank", sysfs
, scrn
->fb
);
499 file
= fopen(fname
, "r+");
501 _eglLog(_EGL_WARNING
, "Failed to open %s", fname
);
504 snprintf(buffer
, sizeof(buffer
), "%d", VESA_NO_BLANKING
);
509 * Set fbdev buffer virtual size to surface's size.
511 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/virtual_size", sysfs
, scrn
->fb
);
512 file
= fopen(fname
, "r+");
513 snprintf(buffer
, sizeof(buffer
), "%d,%d", surf
->Base
.Width
, surf
->Base
.Height
);
516 fgets(buffer
, sizeof(buffer
), file
);
517 sscanf(buffer
, "%d,%d", &display
->virtualWidth
, &display
->virtualHeight
);
521 * round up pitch as needed
523 temp
= display
->virtualWidth
;
524 switch (display
->bpp
/ 8) {
525 case 1: temp
= (display
->virtualWidth
+ 127) & ~127; break;
526 case 2: temp
= (display
->virtualWidth
+ 31) & ~31; break;
528 case 4: temp
= (display
->virtualWidth
+ 15) & ~15; break;
530 _eglLog(_EGL_WARNING
, "Bad display->bpp = %d in _eglDRIShowScreenSurface");
532 display
->virtualWidth
= temp
;
537 if (surf
->Base
.Width
< display
->virtualWidth
||
538 surf
->Base
.Height
< display
->virtualHeight
) {
539 /* this case _should_ have been caught at the top of this function */
540 _eglLog(_EGL_WARNING
, "too small of surface in _eglDRIShowScreenSurfaceMESA "
544 display
->virtualWidth
,
545 display
->virtualHeight
);
551 /* This used to be done in the _eglDRICreateScreens routine. */
552 _eglDRILoadColormap(scrn
);
559 * Called by eglSwapBuffers via the drv->API.SwapBuffers() pointer.
561 * If the backbuffer is on a videocard, this is extraordinarily slow!
564 _eglDRISwapBuffers(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
)
566 driSurface
*drawable
= Lookup_driSurface(draw
);
568 /* this does error checking */
569 if (!_eglSwapBuffers(drv
, dpy
, draw
))
572 drawable
->drawable
.swapBuffers(NULL
, drawable
->drawable
.private);
579 _eglDRIGetDisplayInfo(driDisplay
*dpy
)
581 char path
[ NAME_MAX
];
587 snprintf( path
, sizeof( path
), "%s/graphics/fb%d/device/device", sysfs
, dpy
->minor
);
588 file
= fopen( path
, "r" );
590 _eglLog(_EGL_WARNING
, "Unable to open %s", path
);
593 fgets( path
, sizeof( path
), file
);
594 sscanf( path
, "%x", &dpy
->chipset
);
597 sprintf(path
, DRM_DEV_NAME
, DRM_DIR_NAME
, dpy
->minor
);
598 if ( ( dpy
->drmFD
= open(path
, O_RDWR
, 0) ) < 0 ) {
599 _eglLog(_EGL_WARNING
, "drmOpen failed.");
603 /* Set the interface version, asking for 1.2 */
606 sv
.drm_dd_major
= -1;
607 if ((rc
= drmSetInterfaceVersion(dpy
->drmFD
, &sv
)))
611 if (drmGetMagic(dpy
->drmFD
, &magic
))
613 if (drmAuthMagic(dpy
->drmFD
, magic
))
616 /* Map framebuffer and SAREA */
618 drm_handle_t handle
, offset
;
624 if (drmGetMap(dpy
->drmFD
, i
, &offset
, &size
, &type
, &flags
,
628 if (type
== DRM_FRAME_BUFFER
) {
629 rc
= drmMap( dpy
->drmFD
, offset
, size
, (drmAddressPtr
) &dpy
->pFB
);
631 _eglLog(_EGL_WARNING
, "drmMap DRM_FAME_BUFFER failed");
635 _eglLog(_EGL_INFO
, "Found framebuffer size: %d", dpy
->fbSize
);
637 else if (type
== DRM_SHM
) {
638 rc
= drmMap(dpy
->drmFD
, offset
, size
, (drmAddressPtr
) &dpy
->pSAREA
);
640 _eglLog(_EGL_WARNING
, "drmMap DRM_SHM failed.");
643 dpy
->SAREASize
= SAREA_MAX
;
644 _eglLog(_EGL_DEBUG
, "mapped SAREA 0x%08lx to %p, size %d",
645 (unsigned long) offset
, dpy
->pSAREA
, dpy
->SAREASize
);
650 _eglLog(_EGL_WARNING
, "failed to map framebuffer");
655 /* if this happens, make sure you're using the most recent DRM modules */
656 _eglLog(_EGL_WARNING
, "failed to map SAREA");
660 memset( dpy
->pSAREA
, 0, dpy
->SAREASize
);
666 /* Return the DRI per screen structure */
668 __eglFindDRIScreen(__DRInativeDisplay
*ndpy
, int scrn
)
670 driDisplay
*disp
= (driDisplay
*)ndpy
;
671 return &disp
->driScreen
;
676 __eglCreateContextWithConfig(__DRInativeDisplay
* ndpy
, int screen
,
677 int configID
, void* context
,
678 drm_context_t
* hHWContext
)
680 __DRIscreen
*pDRIScreen
;
681 __DRIscreenPrivate
*psp
;
683 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
684 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
687 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
689 if (drmCreateContext(psp
->fd
, hHWContext
)) {
690 _eglLog(_EGL_WARNING
, "drmCreateContext failed.");
693 *(void**)context
= (void*) *hHWContext
;
696 __DRIscreen
*pDRIScreen
;
697 __DRIscreenPrivate
*psp
;
699 pDRIScreen
= __glXFindDRIScreen(dpy
, screen
);
700 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
704 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
707 if (drmCreateContext(psp
->fd
, hHWContext
)) {
708 _eglLog(_EGL_WARNING
, "drmCreateContext failed.");
711 *(void**)contextID
= (void*) *hHWContext
;
719 __eglDestroyContext( __DRInativeDisplay
* ndpy
, int screen
, __DRIid context
)
721 __DRIscreen
*pDRIScreen
;
722 __DRIscreenPrivate
*psp
;
724 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
725 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
728 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
730 drmDestroyContext(psp
->fd
, context
);
737 __eglCreateDrawable(__DRInativeDisplay
* ndpy
, int screen
,
738 __DRIid drawable
, drm_drawable_t
* hHWDrawable
)
740 __DRIscreen
*pDRIScreen
;
741 __DRIscreenPrivate
*psp
;
743 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
744 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
747 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
749 if (drmCreateDrawable(psp
->fd
, hHWDrawable
)) {
750 _eglLog(_EGL_WARNING
, "drmCreateDrawable failed.");
759 __eglDestroyDrawable( __DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
)
761 __DRIscreen
*pDRIScreen
;
762 __DRIscreenPrivate
*psp
;
764 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
765 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
768 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
770 drmDestroyDrawable(psp
->fd
, drawable
);
776 __eglGetDrawableInfo(__DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
,
777 unsigned int* index
, unsigned int* stamp
,
778 int* X
, int* Y
, int* W
, int* H
,
779 int* numClipRects
, drm_clip_rect_t
** pClipRects
,
780 int* backX
, int* backY
,
781 int* numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
783 __DRIscreen
*pDRIScreen
;
784 __DRIscreenPrivate
*psp
;
785 driSurface
*surf
= Lookup_driSurface((EGLSurface
) drawable
);
787 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
789 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
792 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
795 *W
= surf
->Base
.Width
;
796 *H
= surf
->Base
.Height
;
800 *numBackClipRects
= 0;
801 *pBackClipRects
= NULL
;
804 *pClipRects
= malloc(sizeof(**pClipRects
));
805 **pClipRects
= (drm_clip_rect_t
){0, 0, surf
->Base
.Width
, surf
->Base
.Height
};
807 psp
->pSAREA
->drawableTable
[0].stamp
= 1;
810 GLXDrawable drawable
= (GLXDrawable
) draw
;
811 drm_clip_rect_t
* cliprect
;
812 Display
* display
= (Display
*)dpy
;
813 __DRIcontextPrivate
*pcp
= (__DRIcontextPrivate
*)CurrentContext
->driContext
.private;
818 cliprect
= (drm_clip_rect_t
*) _mesa_malloc(sizeof(drm_clip_rect_t
));
819 cliprect
->x1
= drawable
->x
;
820 cliprect
->y1
= drawable
->y
;
821 cliprect
->x2
= drawable
->x
+ drawable
->w
;
822 cliprect
->y2
= drawable
->y
+ drawable
->h
;
824 /* the drawable index is by client id */
825 *index
= display
->clientID
;
827 *stamp
= pcp
->driScreenPriv
->pSAREA
->drawableTable
[display
->clientID
].stamp
;
830 *width
= drawable
->w
;
831 *height
= drawable
->h
;
833 *pClipRects
= cliprect
;
835 *backX
= drawable
->x
;
836 *backY
= drawable
->y
;
837 *numBackClipRects
= 0;
845 * Implement \c __DRIinterfaceMethods::getProcAddress.
848 get_proc_address(const char * proc_name
)
855 * Destroy a linked list of \c __GLcontextModes structures created by
856 * \c _gl_context_modes_create.
858 * \param modes Linked list of structures to be destroyed. All structres
859 * in the list will be freed.
862 __egl_context_modes_destroy(__GLcontextModes
*modes
)
864 while ( modes
!= NULL
) {
865 __GLcontextModes
* const next
= modes
->next
;
874 * Allocate a linked list of \c __GLcontextModes structures. The fields of
875 * each structure will be initialized to "reasonable" default values. In
876 * most cases this is the default value defined by table 3.4 of the GLX
877 * 1.3 specification. This means that most values are either initialized to
878 * zero or \c GLX_DONT_CARE (which is -1). As support for additional
879 * extensions is added, the new values will be initialized to appropriate
880 * values from the extension specification.
882 * \param count Number of structures to allocate.
883 * \param minimum_size Minimum size of a structure to allocate. This allows
884 * for differences in the version of the
885 * \c __GLcontextModes stucture used in libGL and in a
887 * \returns A pointer to the first element in a linked list of \c count
888 * stuctures on success, or \c NULL on failure.
890 * \warning Use of \c minimum_size does \b not guarantee binary compatibility.
891 * The fundamental assumption is that if the \c minimum_size
892 * specified by the driver and the size of the \c __GLcontextModes
893 * structure in libGL is the same, then the meaning of each byte in
894 * the structure is the same in both places. \b Be \b careful!
895 * Basically this means that fields have to be added in libGL and
896 * then propagated to drivers. Drivers should \b never arbitrarilly
897 * extend the \c __GLcontextModes data-structure.
899 static __GLcontextModes
*
900 __egl_context_modes_create(unsigned count
, size_t minimum_size
)
902 const size_t size
= (minimum_size
> sizeof( __GLcontextModes
))
903 ? minimum_size
: sizeof( __GLcontextModes
);
904 __GLcontextModes
* base
= NULL
;
905 __GLcontextModes
** next
;
909 for ( i
= 0 ; i
< count
; i
++ ) {
910 *next
= (__GLcontextModes
*) malloc( size
);
911 if ( *next
== NULL
) {
912 __egl_context_modes_destroy( base
);
917 (void) memset( *next
, 0, size
);
918 (*next
)->visualID
= GLX_DONT_CARE
;
919 (*next
)->visualType
= GLX_DONT_CARE
;
920 (*next
)->visualRating
= GLX_NONE
;
921 (*next
)->transparentPixel
= GLX_NONE
;
922 (*next
)->transparentRed
= GLX_DONT_CARE
;
923 (*next
)->transparentGreen
= GLX_DONT_CARE
;
924 (*next
)->transparentBlue
= GLX_DONT_CARE
;
925 (*next
)->transparentAlpha
= GLX_DONT_CARE
;
926 (*next
)->transparentIndex
= GLX_DONT_CARE
;
927 (*next
)->xRenderable
= GLX_DONT_CARE
;
928 (*next
)->fbconfigID
= GLX_DONT_CARE
;
929 (*next
)->swapMethod
= GLX_SWAP_UNDEFINED_OML
;
931 next
= & ((*next
)->next
);
939 __eglWindowExists(__DRInativeDisplay
*dpy
, __DRIid draw
)
946 * Get the unadjusted system time (UST). Currently, the UST is measured in
947 * microseconds since Epoc. The actual resolution of the UST may vary from
948 * system to system, and the units may vary from release to release.
949 * Drivers should not call this function directly. They should instead use
950 * \c glXGetProcAddress to obtain a pointer to the function.
952 * \param ust Location to store the 64-bit UST
953 * \returns Zero on success or a negative errno value on failure.
955 * \sa glXGetProcAddress, PFNGLXGETUSTPROC
957 * \since Internal API version 20030317.
960 __eglGetUST(int64_t *ust
)
968 if ( gettimeofday( & tv
, NULL
) == 0 ) {
969 ust
[0] = (tv
.tv_sec
* 1000000) + tv
.tv_usec
;
978 * Determine the refresh rate of the specified drawable and display.
980 * \param dpy Display whose refresh rate is to be determined.
981 * \param drawable Drawable whose refresh rate is to be determined.
982 * \param numerator Numerator of the refresh rate.
983 * \param demoninator Denominator of the refresh rate.
984 * \return If the refresh rate for the specified display and drawable could
985 * be calculated, True is returned. Otherwise False is returned.
987 * \note This function is implemented entirely client-side. A lot of other
988 * functionality is required to export GLX_OML_sync_control, so on
989 * XFree86 this function can be called for direct-rendering contexts
990 * when GLX_OML_sync_control appears in the client extension string.
993 __eglGetMSCRate(__DRInativeDisplay
* dpy
, __DRIid drawable
,
994 int32_t * numerator
, int32_t * denominator
)
1001 * Table of functions exported by the loader to the driver.
1003 static const __DRIinterfaceMethods interface_methods
= {
1006 __egl_context_modes_create
,
1007 __egl_context_modes_destroy
,
1012 __eglCreateContextWithConfig
,
1013 __eglDestroyContext
,
1015 __eglCreateDrawable
,
1016 __eglDestroyDrawable
,
1017 __eglGetDrawableInfo
,
1025 __glXGetInternalVersion(void)
1030 static const char createNewScreenName
[] = "__driCreateNewScreen_20050727";
1034 * Do per-display initialization.
1037 _eglDRICreateDisplay(driDisplay
*dpy
, __DRIframebuffer
*framebuffer
)
1039 PFNCREATENEWSCREENFUNC createNewScreen
;
1040 int api_ver
= __glXGetInternalVersion();
1041 __DRIversion ddx_version
;
1042 __DRIversion dri_version
;
1043 __DRIversion drm_version
;
1044 drmVersionPtr version
;
1046 version
= drmGetVersion( dpy
->drmFD
);
1048 drm_version
.major
= version
->version_major
;
1049 drm_version
.minor
= version
->version_minor
;
1050 drm_version
.patch
= version
->version_patchlevel
;
1051 drmFreeVersion( version
);
1054 drm_version
.major
= -1;
1055 drm_version
.minor
= -1;
1056 drm_version
.patch
= -1;
1060 * Get device name (like "tdfx") and the ddx version numbers.
1061 * We'll check the version in each DRI driver's "createScreen"
1064 ddx_version
.major
= 4;
1065 ddx_version
.minor
= 0;
1066 ddx_version
.patch
= 0;
1069 * Get the DRI X extension version.
1071 dri_version
.major
= 4;
1072 dri_version
.minor
= 0;
1073 dri_version
.patch
= 0;
1075 createNewScreen
= ( PFNCREATENEWSCREENFUNC
) dlsym( dpy
->Base
.Driver
->LibHandle
, createNewScreenName
);
1076 if ( !createNewScreen
) {
1077 _eglLog(_EGL_WARNING
, "Couldn't find %s function in the driver.",
1078 createNewScreenName
);
1082 dpy
->driScreen
.private = createNewScreen( dpy
, 0, &dpy
->driScreen
, NULL
,
1083 &ddx_version
, &dri_version
,
1084 &drm_version
, framebuffer
,
1085 dpy
->pSAREA
, dpy
->drmFD
,
1087 & interface_methods
,
1089 if (!dpy
->driScreen
.private)
1092 DRM_UNLOCK( dpy
->drmFD
, dpy
->pSAREA
, dpy
->serverContext
);
1099 * Create all the EGL screens for the given display.
1102 _eglDRICreateScreens(driDisplay
*dpy
)
1104 const int numScreens
= 1; /* XXX fix this someday */
1107 for (i
= 0; i
< numScreens
; i
++) {
1108 char path
[ NAME_MAX
];
1112 /* Create a screen */
1113 if ( !( s
= ( driScreen
* ) calloc( 1, sizeof( *s
) ) ) )
1116 snprintf( s
->fb
, NAME_MAX
, "fb%d", dpy
->minor
);
1117 _eglInitScreen( &s
->Base
);
1119 _eglAddScreen( &dpy
->Base
, &s
->Base
);
1121 /* Create the screen's mode list */
1122 snprintf( path
, sizeof( path
), "%s/graphics/%s/modes", sysfs
, s
->fb
);
1123 file
= fopen( path
, "r" );
1124 while ( fgets( path
, sizeof( path
), file
) ) {
1125 unsigned int x
, y
, r
;
1127 path
[ strlen( path
) - 1 ] = '\0'; /* strip off \n from sysfs */
1128 sscanf( path
, "%c:%ux%u-%u", &c
, &x
, &y
, &r
);
1129 _eglAddNewMode( &s
->Base
, x
, y
, r
* 1000, path
);
1134 * NOTE: we used to set the colormap here, but that didn't work reliably.
1135 * Some entries near the start of the table would get corrupted by later
1145 _eglDRIInitialize(_EGLDriver
*drv
, EGLDisplay dpy
,
1146 EGLint
*major
, EGLint
*minor
)
1148 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
1149 driDisplay
*display
;
1150 const char *driverName
= (const char *) disp
->NativeDisplay
;
1154 /* Create new driDisplay object to replace the _EGLDisplay that was
1155 * previously created.
1157 display
= calloc(1, sizeof(*display
));
1158 display
->Base
= *disp
;
1159 _eglSaveDisplay(&display
->Base
);
1165 sscanf(driverName
+ 1, "%d", &display
->minor
);
1167 drv
->Initialized
= EGL_TRUE
;
1173 _eglDRITerminate(_EGLDriver
*drv
, EGLDisplay dpy
)
1175 driDisplay
*display
= Lookup_driDisplay(dpy
);
1176 _eglCleanupDisplay(&display
->Base
);/*rename that function*/
1184 * Plug in the DRI-specific functions into the driver's dispatch table.
1185 * Also, enable some EGL extensions.
1188 _eglDRIInitDriverFallbacks(_EGLDriver
*drv
)
1190 _eglInitDriverFallbacks(drv
);
1192 drv
->API
.Initialize
= _eglDRIInitialize
;
1193 drv
->API
.Terminate
= _eglDRITerminate
;
1194 drv
->API
.CreateContext
= _eglDRICreateContext
;
1195 drv
->API
.MakeCurrent
= _eglDRIMakeCurrent
;
1196 drv
->API
.CreatePbufferSurface
= _eglDRICreatePbufferSurface
;
1197 drv
->API
.DestroySurface
= _eglDRIDestroySurface
;
1198 drv
->API
.DestroyContext
= _eglDRIDestroyContext
;
1199 drv
->API
.CreateScreenSurfaceMESA
= _eglDRICreateScreenSurfaceMESA
;
1200 drv
->API
.ShowScreenSurfaceMESA
= _eglDRIShowScreenSurfaceMESA
;
1201 drv
->API
.SwapBuffers
= _eglDRISwapBuffers
;
1203 /* enable supported extensions */
1204 drv
->Extensions
.MESA_screen_surface
= EGL_TRUE
;
1205 drv
->Extensions
.MESA_copy_context
= EGL_TRUE
;