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 (fs
->Base
.IsBound
) {
300 fs
->Base
.DeletePending
= EGL_TRUE
;
310 _eglDRIDestroyContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLContext context
)
312 driDisplay
*disp
= Lookup_driDisplay(dpy
);
313 driContext
*fc
= Lookup_driContext(context
);
315 _eglUnlinkContext(&fc
->Base
);
317 fc
->driContext
.destroyContext(disp
, 0, fc
->driContext
.private);
319 if (fc
->Base
.IsBound
) {
320 fc
->Base
.DeletePending
= EGL_TRUE
;
330 * Create a drawing surface which can be directly displayed on a screen.
333 _eglDRICreateScreenSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig cfg
,
334 const EGLint
*attrib_list
)
336 _EGLConfig
*config
= _eglLookupConfig(drv
, dpy
, cfg
);
337 driDisplay
*disp
= Lookup_driDisplay(dpy
);
339 __GLcontextModes visMode
;
342 surface
= (driSurface
*) calloc(1, sizeof(*surface
));
344 return EGL_NO_SURFACE
;
347 /* init base class, do error checking, etc. */
348 if (!_eglInitSurface(drv
, &surface
->Base
, EGL_SCREEN_BIT_MESA
,
349 config
, attrib_list
)) {
351 return EGL_NO_SURFACE
;
354 _eglLinkSurface(&surface
->Base
&disp
->Base
);
358 * XXX this is where we should allocate video memory for the surface!
362 /* convert EGLConfig to GLvisual */
363 _eglConfigToContextModesRec(config
, &visMode
);
365 drawBuf
= (__DRIid
) _eglGetSurfaceHandle(&surface
->Base
);
367 /* Create a new DRI drawable */
368 if (!disp
->driScreen
.createNewDrawable(disp
, &visMode
, drawBuf
,
369 &surface
->drawable
, GLX_WINDOW_BIT
,
370 empty_attribute_list
)) {
371 _eglUnlinkSurface(&surface
->Base
);
373 return EGL_NO_SURFACE
;
376 return surface
->Base
.Handle
;
381 * Set the fbdev colormap to a simple linear ramp.
384 _eglDRILoadColormap(driScreen
*scrn
)
386 char path
[ NAME_MAX
];
390 /* cmap attribute uses 256 lines of 16 bytes.
391 * Allocate one extra char for the \0 added by sprintf()
393 if ( !( buffer
= malloc( 256 * 16 + 1 ) ) ) {
394 _eglLog(_EGL_WARNING
, "Out of memory in _eglDRILoadColormap");
398 /* cmap attribute uses 256 lines of 16 bytes */
399 for ( i
= 0; i
< 256; i
++ ) {
400 int c
= (i
<< 8) | i
; /* expand to 16-bit value */
401 sprintf(&buffer
[i
* 16], "%02x%c%04x%04x%04x\n", i
, ' ', c
, c
, c
);
404 snprintf(path
, sizeof(path
), "%s/graphics/%s/color_map", sysfs
, scrn
->fb
);
405 if ( !( fd
= open( path
, O_RDWR
) ) ) {
406 _eglLog(_EGL_WARNING
, "Unable to open %s to set colormap", path
);
409 write( fd
, buffer
, 256 * 16 );
417 * Show the given surface on the named screen.
418 * If surface is EGL_NO_SURFACE, disable the screen's output.
419 * Called via eglShowSurfaceMESA().
422 _eglDRIShowScreenSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
,
423 EGLScreenMESA screen
,
424 EGLSurface surface
, EGLModeMESA m
)
426 driDisplay
*display
= Lookup_driDisplay(dpy
);
427 driScreen
*scrn
= Lookup_driScreen(dpy
, screen
);
428 driSurface
*surf
= Lookup_driSurface(surface
);
429 _EGLMode
*mode
= _eglLookupMode(dpy
, m
);
431 char fname
[NAME_MAX
], buffer
[1000];
434 _eglLog(_EGL_DEBUG
, "Enter _eglDRIShowScreenSurface");
436 /* This will check that surface, screen, and mode are valid.
437 * Also, it checks that the surface is large enough for the mode, etc.
439 if (!_eglShowScreenSurfaceMESA(drv
, dpy
, screen
, surface
, m
))
442 assert(surface
== EGL_NO_SURFACE
|| surf
);
443 assert(m
== EGL_NO_MODE_MESA
|| mode
);
447 * Blank/unblank screen depending on if m == EGL_NO_MODE_MESA
449 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/blank", sysfs
, scrn
->fb
);
450 file
= fopen(fname
, "r+");
452 _eglLog(_EGL_WARNING
, "kernel patch?? chown all fb sysfs attrib to allow"
453 " write - %s\n", fname
);
456 snprintf(buffer
, sizeof(buffer
), "%d",
457 (m
== EGL_NO_MODE_MESA
? VESA_POWERDOWN
: VESA_VSYNC_SUSPEND
));
461 if (m
== EGL_NO_MODE_MESA
) {
466 _eglLog(_EGL_INFO
, "Setting display mode to %d x %d, %d bpp",
467 mode
->Width
, mode
->Height
, display
->bpp
);
470 * Set the display mode
472 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/mode", sysfs
, scrn
->fb
);
473 file
= fopen(fname
, "r+");
475 _eglLog(_EGL_WARNING
, "Failed to open %s to set mode", fname
);
478 /* note: nothing happens without the \n! */
479 snprintf(buffer
, sizeof(buffer
), "%s\n", mode
->Name
);
482 _eglLog(_EGL_INFO
, "Set mode to %s in %s", mode
->Name
, fname
);
487 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/bits_per_pixel",
489 file
= fopen(fname
, "r+");
491 _eglLog(_EGL_WARNING
, "Failed to open %s to set bpp", fname
);
494 display
->bpp
= GET_CONFIG_ATTRIB(surf
->Base
.Config
, EGL_BUFFER_SIZE
);
495 display
->cpp
= display
->bpp
/ 8;
496 snprintf(buffer
, sizeof(buffer
), "%d", display
->bpp
);
503 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/blank", sysfs
, scrn
->fb
);
504 file
= fopen(fname
, "r+");
506 _eglLog(_EGL_WARNING
, "Failed to open %s", fname
);
509 snprintf(buffer
, sizeof(buffer
), "%d", VESA_NO_BLANKING
);
514 * Set fbdev buffer virtual size to surface's size.
516 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/virtual_size", sysfs
, scrn
->fb
);
517 file
= fopen(fname
, "r+");
518 snprintf(buffer
, sizeof(buffer
), "%d,%d", surf
->Base
.Width
, surf
->Base
.Height
);
521 fgets(buffer
, sizeof(buffer
), file
);
522 sscanf(buffer
, "%d,%d", &display
->virtualWidth
, &display
->virtualHeight
);
526 * round up pitch as needed
528 temp
= display
->virtualWidth
;
529 switch (display
->bpp
/ 8) {
530 case 1: temp
= (display
->virtualWidth
+ 127) & ~127; break;
531 case 2: temp
= (display
->virtualWidth
+ 31) & ~31; break;
533 case 4: temp
= (display
->virtualWidth
+ 15) & ~15; break;
535 _eglLog(_EGL_WARNING
, "Bad display->bpp = %d in _eglDRIShowScreenSurface");
537 display
->virtualWidth
= temp
;
542 if (surf
->Base
.Width
< display
->virtualWidth
||
543 surf
->Base
.Height
< display
->virtualHeight
) {
544 /* this case _should_ have been caught at the top of this function */
545 _eglLog(_EGL_WARNING
, "too small of surface in _eglDRIShowScreenSurfaceMESA "
549 display
->virtualWidth
,
550 display
->virtualHeight
);
556 /* This used to be done in the _eglDRICreateScreens routine. */
557 _eglDRILoadColormap(scrn
);
564 * Called by eglSwapBuffers via the drv->API.SwapBuffers() pointer.
566 * If the backbuffer is on a videocard, this is extraordinarily slow!
569 _eglDRISwapBuffers(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
)
571 driSurface
*drawable
= Lookup_driSurface(draw
);
573 /* this does error checking */
574 if (!_eglSwapBuffers(drv
, dpy
, draw
))
577 drawable
->drawable
.swapBuffers(NULL
, drawable
->drawable
.private);
584 _eglDRIGetDisplayInfo(driDisplay
*dpy
)
586 char path
[ NAME_MAX
];
592 snprintf( path
, sizeof( path
), "%s/graphics/fb%d/device/device", sysfs
, dpy
->minor
);
593 file
= fopen( path
, "r" );
595 _eglLog(_EGL_WARNING
, "Unable to open %s", path
);
598 fgets( path
, sizeof( path
), file
);
599 sscanf( path
, "%x", &dpy
->chipset
);
602 sprintf(path
, DRM_DEV_NAME
, DRM_DIR_NAME
, dpy
->minor
);
603 if ( ( dpy
->drmFD
= open(path
, O_RDWR
, 0) ) < 0 ) {
604 _eglLog(_EGL_WARNING
, "drmOpen failed.");
608 /* Set the interface version, asking for 1.2 */
611 sv
.drm_dd_major
= -1;
612 if ((rc
= drmSetInterfaceVersion(dpy
->drmFD
, &sv
)))
616 if (drmGetMagic(dpy
->drmFD
, &magic
))
618 if (drmAuthMagic(dpy
->drmFD
, magic
))
621 /* Map framebuffer and SAREA */
623 drm_handle_t handle
, offset
;
629 if (drmGetMap(dpy
->drmFD
, i
, &offset
, &size
, &type
, &flags
,
633 if (type
== DRM_FRAME_BUFFER
) {
634 rc
= drmMap( dpy
->drmFD
, offset
, size
, (drmAddressPtr
) &dpy
->pFB
);
636 _eglLog(_EGL_WARNING
, "drmMap DRM_FAME_BUFFER failed");
640 _eglLog(_EGL_INFO
, "Found framebuffer size: %d", dpy
->fbSize
);
642 else if (type
== DRM_SHM
) {
643 rc
= drmMap(dpy
->drmFD
, offset
, size
, (drmAddressPtr
) &dpy
->pSAREA
);
645 _eglLog(_EGL_WARNING
, "drmMap DRM_SHM failed.");
648 dpy
->SAREASize
= SAREA_MAX
;
649 _eglLog(_EGL_DEBUG
, "mapped SAREA 0x%08lx to %p, size %d",
650 (unsigned long) offset
, dpy
->pSAREA
, dpy
->SAREASize
);
655 _eglLog(_EGL_WARNING
, "failed to map framebuffer");
660 /* if this happens, make sure you're using the most recent DRM modules */
661 _eglLog(_EGL_WARNING
, "failed to map SAREA");
665 memset( dpy
->pSAREA
, 0, dpy
->SAREASize
);
671 /* Return the DRI per screen structure */
673 __eglFindDRIScreen(__DRInativeDisplay
*ndpy
, int scrn
)
675 driDisplay
*disp
= (driDisplay
*)ndpy
;
676 return &disp
->driScreen
;
681 __eglCreateContextWithConfig(__DRInativeDisplay
* ndpy
, int screen
,
682 int configID
, void* context
,
683 drm_context_t
* hHWContext
)
685 __DRIscreen
*pDRIScreen
;
686 __DRIscreenPrivate
*psp
;
688 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
689 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
692 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
694 if (drmCreateContext(psp
->fd
, hHWContext
)) {
695 _eglLog(_EGL_WARNING
, "drmCreateContext failed.");
698 *(void**)context
= (void*) *hHWContext
;
701 __DRIscreen
*pDRIScreen
;
702 __DRIscreenPrivate
*psp
;
704 pDRIScreen
= __glXFindDRIScreen(dpy
, screen
);
705 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
709 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
712 if (drmCreateContext(psp
->fd
, hHWContext
)) {
713 _eglLog(_EGL_WARNING
, "drmCreateContext failed.");
716 *(void**)contextID
= (void*) *hHWContext
;
724 __eglDestroyContext( __DRInativeDisplay
* ndpy
, int screen
, __DRIid context
)
726 __DRIscreen
*pDRIScreen
;
727 __DRIscreenPrivate
*psp
;
729 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
730 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
733 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
735 drmDestroyContext(psp
->fd
, context
);
742 __eglCreateDrawable(__DRInativeDisplay
* ndpy
, int screen
,
743 __DRIid drawable
, drm_drawable_t
* hHWDrawable
)
745 __DRIscreen
*pDRIScreen
;
746 __DRIscreenPrivate
*psp
;
748 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
749 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
752 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
754 if (drmCreateDrawable(psp
->fd
, hHWDrawable
)) {
755 _eglLog(_EGL_WARNING
, "drmCreateDrawable failed.");
764 __eglDestroyDrawable( __DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
)
766 __DRIscreen
*pDRIScreen
;
767 __DRIscreenPrivate
*psp
;
769 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
770 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
773 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
775 drmDestroyDrawable(psp
->fd
, drawable
);
781 __eglGetDrawableInfo(__DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
,
782 unsigned int* index
, unsigned int* stamp
,
783 int* X
, int* Y
, int* W
, int* H
,
784 int* numClipRects
, drm_clip_rect_t
** pClipRects
,
785 int* backX
, int* backY
,
786 int* numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
788 __DRIscreen
*pDRIScreen
;
789 __DRIscreenPrivate
*psp
;
790 driSurface
*surf
= Lookup_driSurface((EGLSurface
) drawable
);
792 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
794 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
797 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
800 *W
= surf
->Base
.Width
;
801 *H
= surf
->Base
.Height
;
805 *numBackClipRects
= 0;
806 *pBackClipRects
= NULL
;
809 *pClipRects
= malloc(sizeof(**pClipRects
));
810 **pClipRects
= (drm_clip_rect_t
){0, 0, surf
->Base
.Width
, surf
->Base
.Height
};
812 psp
->pSAREA
->drawableTable
[0].stamp
= 1;
815 GLXDrawable drawable
= (GLXDrawable
) draw
;
816 drm_clip_rect_t
* cliprect
;
817 Display
* display
= (Display
*)dpy
;
818 __DRIcontextPrivate
*pcp
= (__DRIcontextPrivate
*)CurrentContext
->driContext
.private;
823 cliprect
= (drm_clip_rect_t
*) _mesa_malloc(sizeof(drm_clip_rect_t
));
824 cliprect
->x1
= drawable
->x
;
825 cliprect
->y1
= drawable
->y
;
826 cliprect
->x2
= drawable
->x
+ drawable
->w
;
827 cliprect
->y2
= drawable
->y
+ drawable
->h
;
829 /* the drawable index is by client id */
830 *index
= display
->clientID
;
832 *stamp
= pcp
->driScreenPriv
->pSAREA
->drawableTable
[display
->clientID
].stamp
;
835 *width
= drawable
->w
;
836 *height
= drawable
->h
;
838 *pClipRects
= cliprect
;
840 *backX
= drawable
->x
;
841 *backY
= drawable
->y
;
842 *numBackClipRects
= 0;
850 * Implement \c __DRIinterfaceMethods::getProcAddress.
853 get_proc_address(const char * proc_name
)
860 * Destroy a linked list of \c __GLcontextModes structures created by
861 * \c _gl_context_modes_create.
863 * \param modes Linked list of structures to be destroyed. All structres
864 * in the list will be freed.
867 __egl_context_modes_destroy(__GLcontextModes
*modes
)
869 while ( modes
!= NULL
) {
870 __GLcontextModes
* const next
= modes
->next
;
879 * Allocate a linked list of \c __GLcontextModes structures. The fields of
880 * each structure will be initialized to "reasonable" default values. In
881 * most cases this is the default value defined by table 3.4 of the GLX
882 * 1.3 specification. This means that most values are either initialized to
883 * zero or \c GLX_DONT_CARE (which is -1). As support for additional
884 * extensions is added, the new values will be initialized to appropriate
885 * values from the extension specification.
887 * \param count Number of structures to allocate.
888 * \param minimum_size Minimum size of a structure to allocate. This allows
889 * for differences in the version of the
890 * \c __GLcontextModes stucture used in libGL and in a
892 * \returns A pointer to the first element in a linked list of \c count
893 * stuctures on success, or \c NULL on failure.
895 * \warning Use of \c minimum_size does \b not guarantee binary compatibility.
896 * The fundamental assumption is that if the \c minimum_size
897 * specified by the driver and the size of the \c __GLcontextModes
898 * structure in libGL is the same, then the meaning of each byte in
899 * the structure is the same in both places. \b Be \b careful!
900 * Basically this means that fields have to be added in libGL and
901 * then propagated to drivers. Drivers should \b never arbitrarilly
902 * extend the \c __GLcontextModes data-structure.
904 static __GLcontextModes
*
905 __egl_context_modes_create(unsigned count
, size_t minimum_size
)
907 const size_t size
= (minimum_size
> sizeof( __GLcontextModes
))
908 ? minimum_size
: sizeof( __GLcontextModes
);
909 __GLcontextModes
* base
= NULL
;
910 __GLcontextModes
** next
;
914 for ( i
= 0 ; i
< count
; i
++ ) {
915 *next
= (__GLcontextModes
*) malloc( size
);
916 if ( *next
== NULL
) {
917 __egl_context_modes_destroy( base
);
922 (void) memset( *next
, 0, size
);
923 (*next
)->visualID
= GLX_DONT_CARE
;
924 (*next
)->visualType
= GLX_DONT_CARE
;
925 (*next
)->visualRating
= GLX_NONE
;
926 (*next
)->transparentPixel
= GLX_NONE
;
927 (*next
)->transparentRed
= GLX_DONT_CARE
;
928 (*next
)->transparentGreen
= GLX_DONT_CARE
;
929 (*next
)->transparentBlue
= GLX_DONT_CARE
;
930 (*next
)->transparentAlpha
= GLX_DONT_CARE
;
931 (*next
)->transparentIndex
= GLX_DONT_CARE
;
932 (*next
)->xRenderable
= GLX_DONT_CARE
;
933 (*next
)->fbconfigID
= GLX_DONT_CARE
;
934 (*next
)->swapMethod
= GLX_SWAP_UNDEFINED_OML
;
936 next
= & ((*next
)->next
);
944 __eglWindowExists(__DRInativeDisplay
*dpy
, __DRIid draw
)
951 * Get the unadjusted system time (UST). Currently, the UST is measured in
952 * microseconds since Epoc. The actual resolution of the UST may vary from
953 * system to system, and the units may vary from release to release.
954 * Drivers should not call this function directly. They should instead use
955 * \c glXGetProcAddress to obtain a pointer to the function.
957 * \param ust Location to store the 64-bit UST
958 * \returns Zero on success or a negative errno value on failure.
960 * \sa glXGetProcAddress, PFNGLXGETUSTPROC
962 * \since Internal API version 20030317.
965 __eglGetUST(int64_t *ust
)
973 if ( gettimeofday( & tv
, NULL
) == 0 ) {
974 ust
[0] = (tv
.tv_sec
* 1000000) + tv
.tv_usec
;
983 * Determine the refresh rate of the specified drawable and display.
985 * \param dpy Display whose refresh rate is to be determined.
986 * \param drawable Drawable whose refresh rate is to be determined.
987 * \param numerator Numerator of the refresh rate.
988 * \param demoninator Denominator of the refresh rate.
989 * \return If the refresh rate for the specified display and drawable could
990 * be calculated, True is returned. Otherwise False is returned.
992 * \note This function is implemented entirely client-side. A lot of other
993 * functionality is required to export GLX_OML_sync_control, so on
994 * XFree86 this function can be called for direct-rendering contexts
995 * when GLX_OML_sync_control appears in the client extension string.
998 __eglGetMSCRate(__DRInativeDisplay
* dpy
, __DRIid drawable
,
999 int32_t * numerator
, int32_t * denominator
)
1006 * Table of functions exported by the loader to the driver.
1008 static const __DRIinterfaceMethods interface_methods
= {
1011 __egl_context_modes_create
,
1012 __egl_context_modes_destroy
,
1017 __eglCreateContextWithConfig
,
1018 __eglDestroyContext
,
1020 __eglCreateDrawable
,
1021 __eglDestroyDrawable
,
1022 __eglGetDrawableInfo
,
1030 __glXGetInternalVersion(void)
1035 static const char createNewScreenName
[] = "__driCreateNewScreen_20050727";
1039 * Do per-display initialization.
1042 _eglDRICreateDisplay(driDisplay
*dpy
, __DRIframebuffer
*framebuffer
)
1044 PFNCREATENEWSCREENFUNC createNewScreen
;
1045 int api_ver
= __glXGetInternalVersion();
1046 __DRIversion ddx_version
;
1047 __DRIversion dri_version
;
1048 __DRIversion drm_version
;
1049 drmVersionPtr version
;
1051 version
= drmGetVersion( dpy
->drmFD
);
1053 drm_version
.major
= version
->version_major
;
1054 drm_version
.minor
= version
->version_minor
;
1055 drm_version
.patch
= version
->version_patchlevel
;
1056 drmFreeVersion( version
);
1059 drm_version
.major
= -1;
1060 drm_version
.minor
= -1;
1061 drm_version
.patch
= -1;
1065 * Get device name (like "tdfx") and the ddx version numbers.
1066 * We'll check the version in each DRI driver's "createScreen"
1069 ddx_version
.major
= 4;
1070 ddx_version
.minor
= 0;
1071 ddx_version
.patch
= 0;
1074 * Get the DRI X extension version.
1076 dri_version
.major
= 4;
1077 dri_version
.minor
= 0;
1078 dri_version
.patch
= 0;
1080 createNewScreen
= ( PFNCREATENEWSCREENFUNC
) dlsym( dpy
->Base
.Driver
->LibHandle
, createNewScreenName
);
1081 if ( !createNewScreen
) {
1082 _eglLog(_EGL_WARNING
, "Couldn't find %s function in the driver.",
1083 createNewScreenName
);
1087 dpy
->driScreen
.private = createNewScreen( dpy
, 0, &dpy
->driScreen
, NULL
,
1088 &ddx_version
, &dri_version
,
1089 &drm_version
, framebuffer
,
1090 dpy
->pSAREA
, dpy
->drmFD
,
1092 & interface_methods
,
1094 if (!dpy
->driScreen
.private) {
1095 _eglLog(_EGL_WARNING
, "egldri.c: DRI create new screen failed");
1099 DRM_UNLOCK( dpy
->drmFD
, dpy
->pSAREA
, dpy
->serverContext
);
1106 * Create all the EGL screens for the given display.
1109 _eglDRICreateScreens(driDisplay
*dpy
)
1111 const int numScreens
= 1; /* XXX fix this someday */
1114 for (i
= 0; i
< numScreens
; i
++) {
1115 char path
[ NAME_MAX
];
1119 /* Create a screen */
1120 if ( !( s
= ( driScreen
* ) calloc( 1, sizeof( *s
) ) ) )
1123 snprintf( s
->fb
, NAME_MAX
, "fb%d", dpy
->minor
);
1124 _eglInitScreen( &s
->Base
);
1126 _eglAddScreen( &dpy
->Base
, &s
->Base
);
1128 /* Create the screen's mode list */
1129 snprintf( path
, sizeof( path
), "%s/graphics/%s/modes", sysfs
, s
->fb
);
1130 file
= fopen( path
, "r" );
1131 while ( fgets( path
, sizeof( path
), file
) ) {
1132 unsigned int x
, y
, r
;
1134 path
[ strlen( path
) - 1 ] = '\0'; /* strip off \n from sysfs */
1135 sscanf( path
, "%c:%ux%u-%u", &c
, &x
, &y
, &r
);
1136 _eglAddNewMode( &s
->Base
, x
, y
, r
* 1000, path
);
1141 * NOTE: we used to set the colormap here, but that didn't work reliably.
1142 * Some entries near the start of the table would get corrupted by later
1152 _eglDRIInitialize(_EGLDriver
*drv
, EGLDisplay dpy
,
1153 EGLint
*major
, EGLint
*minor
)
1155 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
1156 driDisplay
*display
;
1157 const char *driverName
= (const char *) disp
->NativeDisplay
;
1161 /* Create new driDisplay object to replace the _EGLDisplay that was
1162 * previously created.
1164 display
= calloc(1, sizeof(*display
));
1165 display
->Base
= *disp
;
1166 _eglSaveDisplay(&display
->Base
);
1172 sscanf(driverName
+ 1, "%d", &display
->minor
);
1174 drv
->Initialized
= EGL_TRUE
;
1180 _eglDRITerminate(_EGLDriver
*drv
, EGLDisplay dpy
)
1182 driDisplay
*display
= Lookup_driDisplay(dpy
);
1183 _eglCleanupDisplay(&display
->Base
);/*rename that function*/
1191 * Plug in the DRI-specific functions into the driver's dispatch table.
1192 * Also, enable some EGL extensions.
1195 _eglDRIInitDriverFallbacks(_EGLDriver
*drv
)
1197 _eglInitDriverFallbacks(drv
);
1199 drv
->API
.Initialize
= _eglDRIInitialize
;
1200 drv
->API
.Terminate
= _eglDRITerminate
;
1201 drv
->API
.CreateContext
= _eglDRICreateContext
;
1202 drv
->API
.MakeCurrent
= _eglDRIMakeCurrent
;
1203 drv
->API
.CreatePbufferSurface
= _eglDRICreatePbufferSurface
;
1204 drv
->API
.DestroySurface
= _eglDRIDestroySurface
;
1205 drv
->API
.DestroyContext
= _eglDRIDestroyContext
;
1206 drv
->API
.CreateScreenSurfaceMESA
= _eglDRICreateScreenSurfaceMESA
;
1207 drv
->API
.ShowScreenSurfaceMESA
= _eglDRIShowScreenSurfaceMESA
;
1208 drv
->API
.SwapBuffers
= _eglDRISwapBuffers
;
1210 /* enable supported extensions */
1211 drv
->Extensions
.MESA_screen_surface
= EGL_TRUE
;
1212 drv
->Extensions
.MESA_copy_context
= EGL_TRUE
;