2 * Generic EGL driver for DRI.
4 * This file contains all the code needed to interface DRI-based drivers
7 * There's a lot of dependencies on fbdev and the /sys/ filesystem.
22 #include "egldriver.h"
23 #include "egldisplay.h"
24 #include "eglcontext.h"
25 #include "eglconfig.h"
26 #include "eglsurface.h"
27 #include "eglscreen.h"
28 #include "eglglobals.h"
34 const char *sysfs
= "/sys/class";
36 static const int empty_attribute_list
[1] = { None
};
40 * The bootstrap function.
41 * Return a new driDriver object and plug in API functions.
42 * This function, in turn, loads a specific DRI driver (ex: r200_dri.so).
45 _eglMain(_EGLDisplay
*dpy
)
49 struct dirent
*dirent
;
54 _EGLDriver
*driver
= NULL
;;
56 snprintf(path
, sizeof(path
), "%s/drm", sysfs
);
57 if (!(dir
= opendir(path
))) {
58 _eglLog(_EGL_WARNING
, "%s DRM devices not found.", path
);
61 while ((dirent
= readdir(dir
))) {
63 if (strncmp(&dirent
->d_name
[0], "card", 4) != 0)
65 if (strcmp(&dirent
->d_name
[4], &dpy
->Name
[1]) != 0)
68 snprintf(path
, sizeof(path
), "%s/drm/card%s/dri_library_name", sysfs
, &dpy
->Name
[1]);
69 _eglLog(_EGL_INFO
, "Opening %s", path
);
71 file
= fopen(path
, "r");
73 _eglLog(_EGL_WARNING
, "Failed to open %s", path
);
76 fgets(path
, sizeof(path
), file
);
79 strcpy(path
, "r200\n");
81 if ((length
= strlen(path
)) > 0)
82 path
[length
- 1] = '\0'; /* remove the trailing newline from sysfs */
83 strncat(path
, "_dri", sizeof(path
));
85 driver
= _eglOpenDriver(dpy
, path
);
96 * Called by eglCreateContext via drv->API.CreateContext().
99 _eglDRICreateContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
,
100 EGLContext share_list
, const EGLint
*attrib_list
)
102 driDisplay
*disp
= Lookup_driDisplay(dpy
);
103 driContext
*c
, *share
;
106 __GLcontextModes visMode
;
108 c
= (driContext
*) calloc(1, sizeof(*c
));
110 return EGL_NO_CONTEXT
;
112 if (!_eglInitContext(drv
, dpy
, &c
->Base
, config
, attrib_list
)) {
114 return EGL_NO_CONTEXT
;
117 if (share_list
!= EGL_NO_CONTEXT
) {
118 _EGLContext
*shareCtx
= _eglLookupContext(share_list
);
120 _eglError(EGL_BAD_CONTEXT
, "eglCreateContext(share_list)");
124 share
= Lookup_driContext(share_list
);
126 sharePriv
= share
->driContext
.private;
130 conf
= _eglLookupConfig(drv
, dpy
, config
);
132 _eglConfigToContextModesRec(conf
, &visMode
);
134 c
->driContext
.private = disp
->driScreen
.createNewContext(disp
, &visMode
,
135 GLX_WINDOW_BIT
, sharePriv
, &c
->driContext
);
136 if (!c
->driContext
.private) {
141 /* generate handle and insert into hash table */
142 _eglSaveContext(&c
->Base
);
144 return c
->Base
.Handle
;
149 _eglDRIMakeCurrent(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
,
150 EGLSurface read
, EGLContext context
)
152 driDisplay
*disp
= Lookup_driDisplay(dpy
);
153 driContext
*ctx
= Lookup_driContext(context
);
156 b
= _eglMakeCurrent(drv
, dpy
, draw
, read
, context
);
161 ctx
->driContext
.bindContext(disp
, 0, read
, draw
, &ctx
->driContext
);
165 /* _mesa_make_current( NULL, NULL, NULL );*/
172 _eglDRICreatePbufferSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
,
173 const EGLint
*attrib_list
)
177 surf
= (driSurface
*) calloc(1, sizeof(*surf
));
179 return EGL_NO_SURFACE
;
182 if (!_eglInitSurface(drv
, dpy
, &surf
->Base
, EGL_PBUFFER_BIT
,
183 config
, attrib_list
)) {
185 return EGL_NO_SURFACE
;
188 /* create software-based pbuffer */
191 GLcontext
*ctx
= NULL
; /* this _should_ be OK */
194 _EGLConfig
*conf
= _eglLookupConfig(drv
, dpy
, config
);
195 assert(conf
); /* bad config should be caught earlier */
196 _eglConfigToContextModesRec(conf
, &visMode
);
199 surf
->mesa_framebuffer
= _mesa_create_framebuffer(&visMode
);
200 _mesa_add_soft_renderbuffers(surf
->mesa_framebuffer
,
201 GL_TRUE
, /* color bufs */
202 visMode
.haveDepthBuffer
,
203 visMode
.haveStencilBuffer
,
204 visMode
.haveAccumBuffer
,
205 GL_FALSE
, /* alpha */
206 GL_FALSE
/* aux */ );
208 /* set pbuffer/framebuffer size */
209 _mesa_resize_framebuffer(ctx
, surf
->mesa_framebuffer
,
210 surf
->Base
.Width
, surf
->Base
.Height
);
214 _eglSaveSurface(&surf
->Base
);
216 return surf
->Base
.Handle
;
221 _eglDRIDestroySurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
)
223 driDisplay
*disp
= Lookup_driDisplay(dpy
);
224 driSurface
*fs
= Lookup_driSurface(surface
);
226 _eglRemoveSurface(&fs
->Base
);
228 fs
->drawable
.destroyDrawable(disp
, fs
->drawable
.private);
230 if (fs
->Base
.IsBound
) {
231 fs
->Base
.DeletePending
= EGL_TRUE
;
241 _eglDRIDestroyContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLContext context
)
243 driDisplay
*disp
= Lookup_driDisplay(dpy
);
244 driContext
*fc
= Lookup_driContext(context
);
246 _eglRemoveContext(&fc
->Base
);
248 fc
->driContext
.destroyContext(disp
, 0, fc
->driContext
.private);
250 if (fc
->Base
.IsBound
) {
251 fc
->Base
.DeletePending
= EGL_TRUE
;
261 * Create a drawing surface which can be directly displayed on a screen.
264 _eglDRICreateScreenSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig cfg
,
265 const EGLint
*attrib_list
)
267 _EGLConfig
*config
= _eglLookupConfig(drv
, dpy
, cfg
);
268 driDisplay
*disp
= Lookup_driDisplay(dpy
);
272 surface
= (driSurface
*) calloc(1, sizeof(*surface
));
274 return EGL_NO_SURFACE
;
277 /* init base class, do error checking, etc. */
278 if (!_eglInitSurface(drv
, dpy
, &surface
->Base
, EGL_SCREEN_BIT_MESA
,
281 return EGL_NO_SURFACE
;
284 _eglSaveSurface(&surface
->Base
);
288 * XXX this is where we should allocate video memory for the surface!
292 /* convert EGLConfig to GLvisual */
293 _eglConfigToContextModesRec(config
, &visMode
);
295 /* Create a new DRI drawable */
296 if (!disp
->driScreen
.createNewDrawable(disp
, &visMode
, surface
->Base
.Handle
,
297 &surface
->drawable
, GLX_WINDOW_BIT
,
298 empty_attribute_list
)) {
299 _eglRemoveSurface(&surface
->Base
);
301 return EGL_NO_SURFACE
;
304 return surface
->Base
.Handle
;
309 * Set the fbdev colormap to a simple linear ramp.
312 _eglDRILoadColormap(driScreen
*scrn
)
314 char path
[ NAME_MAX
];
318 /* cmap attribute uses 256 lines of 16 bytes.
319 * Allocate one extra char for the \0 added by sprintf()
321 if ( !( buffer
= malloc( 256 * 16 + 1 ) ) ) {
322 _eglLog(_EGL_WARNING
, "Out of memory in _eglDRILoadColormap");
326 /* cmap attribute uses 256 lines of 16 bytes */
327 for ( i
= 0; i
< 256; i
++ ) {
328 int c
= (i
<< 8) | i
; /* expand to 16-bit value */
329 sprintf(&buffer
[i
* 16], "%02x%c%04x%04x%04x\n", i
, ' ', c
, c
, c
);
332 snprintf(path
, sizeof(path
), "%s/graphics/%s/color_map", sysfs
, scrn
->fb
);
333 if ( !( fd
= open( path
, O_RDWR
) ) ) {
334 _eglLog(_EGL_WARNING
, "Unable to open %s to set colormap", path
);
337 write( fd
, buffer
, 256 * 16 );
345 * Show the given surface on the named screen.
346 * If surface is EGL_NO_SURFACE, disable the screen's output.
347 * Called via eglShowSurfaceMESA().
350 _eglDRIShowScreenSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
,
351 EGLScreenMESA screen
,
352 EGLSurface surface
, EGLModeMESA m
)
354 driDisplay
*display
= Lookup_driDisplay(dpy
);
355 driScreen
*scrn
= Lookup_driScreen(dpy
, screen
);
356 driSurface
*surf
= Lookup_driSurface(surface
);
357 _EGLMode
*mode
= _eglLookupMode(dpy
, m
);
359 char fname
[NAME_MAX
], buffer
[1000];
362 _eglLog(_EGL_DEBUG
, "Enter _eglDRIShowScreenSurface");
364 /* This will check that surface, screen, and mode are valid.
365 * Also, it checks that the surface is large enough for the mode, etc.
367 if (!_eglShowScreenSurfaceMESA(drv
, dpy
, screen
, surface
, m
))
370 assert(surface
== EGL_NO_SURFACE
|| surf
);
371 assert(m
== EGL_NO_MODE_MESA
|| mode
);
375 * Blank/unblank screen depending on if m == EGL_NO_MODE_MESA
377 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/blank", sysfs
, scrn
->fb
);
378 file
= fopen(fname
, "r+");
380 _eglLog(_EGL_WARNING
, "kernel patch?? chown all fb sysfs attrib to allow"
381 " write - %s\n", fname
);
384 snprintf(buffer
, sizeof(buffer
), "%d",
385 (m
== EGL_NO_MODE_MESA
? VESA_POWERDOWN
: VESA_VSYNC_SUSPEND
));
389 if (m
== EGL_NO_MODE_MESA
) {
394 _eglLog(_EGL_INFO
, "Setting display mode to %d x %d, %d bpp",
395 mode
->Width
, mode
->Height
, display
->bpp
);
398 * Set the display mode
400 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/mode", sysfs
, scrn
->fb
);
401 file
= fopen(fname
, "r+");
403 _eglLog(_EGL_WARNING
, "Failed to open %s to set mode", fname
);
406 /* note: nothing happens without the \n! */
407 snprintf(buffer
, sizeof(buffer
), "%s\n", mode
->Name
);
410 _eglLog(_EGL_INFO
, "Set mode to %s in %s", mode
->Name
, fname
);
415 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/bits_per_pixel",
417 file
= fopen(fname
, "r+");
419 _eglLog(_EGL_WARNING
, "Failed to open %s to set bpp", fname
);
422 display
->bpp
= GET_CONFIG_ATTRIB(surf
->Base
.Config
, EGL_BUFFER_SIZE
);
423 display
->cpp
= display
->bpp
/ 8;
424 snprintf(buffer
, sizeof(buffer
), "%d", display
->bpp
);
431 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/blank", sysfs
, scrn
->fb
);
432 file
= fopen(fname
, "r+");
434 _eglLog(_EGL_WARNING
, "Failed to open %s", fname
);
437 snprintf(buffer
, sizeof(buffer
), "%d", VESA_NO_BLANKING
);
442 * Set fbdev buffer virtual size to surface's size.
444 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/virtual_size", sysfs
, scrn
->fb
);
445 file
= fopen(fname
, "r+");
446 snprintf(buffer
, sizeof(buffer
), "%d,%d", surf
->Base
.Width
, surf
->Base
.Height
);
449 fgets(buffer
, sizeof(buffer
), file
);
450 sscanf(buffer
, "%d,%d", &display
->virtualWidth
, &display
->virtualHeight
);
454 * round up pitch as needed
456 temp
= display
->virtualWidth
;
457 switch (display
->bpp
/ 8) {
458 case 1: temp
= (display
->virtualWidth
+ 127) & ~127; break;
459 case 2: temp
= (display
->virtualWidth
+ 31) & ~31; break;
461 case 4: temp
= (display
->virtualWidth
+ 15) & ~15; break;
463 _eglLog(_EGL_WARNING
, "Bad display->bpp = %d in _eglDRIShowScreenSurface");
465 display
->virtualWidth
= temp
;
470 if (surf
->Base
.Width
< display
->virtualWidth
||
471 surf
->Base
.Height
< display
->virtualHeight
) {
472 /* this case _should_ have been caught at the top of this function */
473 _eglLog(_EGL_WARNING
, "too small of surface in _eglDRIShowScreenSurfaceMESA "
477 display
->virtualWidth
,
478 display
->virtualHeight
);
484 /* This used to be done in the _eglDRICreateScreens routine. */
485 _eglDRILoadColormap(scrn
);
492 * Called by eglSwapBuffers via the drv->API.SwapBuffers() pointer.
494 * If the backbuffer is on a videocard, this is extraordinarily slow!
497 _eglDRISwapBuffers(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
)
499 driSurface
*drawable
= Lookup_driSurface(draw
);
501 /* this does error checking */
502 if (!_eglSwapBuffers(drv
, dpy
, draw
))
505 drawable
->drawable
.swapBuffers(NULL
, drawable
->drawable
.private);
512 _eglDRIGetDisplayInfo(driDisplay
*dpy
)
514 char path
[ NAME_MAX
];
520 snprintf( path
, sizeof( path
), "%s/graphics/fb%d/device/device", sysfs
, dpy
->minor
);
521 file
= fopen( path
, "r" );
523 _eglLog(_EGL_WARNING
, "Unable to open %s", path
);
526 fgets( path
, sizeof( path
), file
);
527 sscanf( path
, "%x", &dpy
->chipset
);
530 sprintf(path
, DRM_DEV_NAME
, DRM_DIR_NAME
, dpy
->minor
);
531 if ( ( dpy
->drmFD
= open(path
, O_RDWR
, 0) ) < 0 ) {
532 _eglLog(_EGL_WARNING
, "drmOpen failed.");
536 /* Set the interface version, asking for 1.2 */
539 sv
.drm_dd_major
= -1;
540 if ((rc
= drmSetInterfaceVersion(dpy
->drmFD
, &sv
)))
544 if (drmGetMagic(dpy
->drmFD
, &magic
))
546 if (drmAuthMagic(dpy
->drmFD
, magic
))
549 /* Map framebuffer and SAREA */
551 drm_handle_t handle
, offset
;
557 if (drmGetMap(dpy
->drmFD
, i
, &offset
, &size
, &type
, &flags
,
561 if (type
== DRM_FRAME_BUFFER
) {
562 rc
= drmMap( dpy
->drmFD
, offset
, size
, (drmAddressPtr
) &dpy
->pFB
);
564 _eglLog(_EGL_WARNING
, "drmMap DRM_FAME_BUFFER failed");
568 _eglLog(_EGL_INFO
, "Found framebuffer size: %d", dpy
->fbSize
);
570 else if (type
== DRM_SHM
) {
571 rc
= drmMap(dpy
->drmFD
, offset
, size
, (drmAddressPtr
) &dpy
->pSAREA
);
573 _eglLog(_EGL_WARNING
, "drmMap DRM_SHM failed.");
576 dpy
->SAREASize
= SAREA_MAX
;
577 _eglLog(_EGL_DEBUG
, "mapped SAREA 0x%08lx to %p, size %d",
578 (unsigned long) offset
, dpy
->pSAREA
, dpy
->SAREASize
);
583 _eglLog(_EGL_WARNING
, "failed to map framebuffer");
588 /* if this happens, make sure you're using the most recent DRM modules */
589 _eglLog(_EGL_WARNING
, "failed to map SAREA");
593 memset( dpy
->pSAREA
, 0, dpy
->SAREASize
);
599 /* Return the DRI per screen structure */
601 __eglFindDRIScreen(__DRInativeDisplay
*ndpy
, int scrn
)
603 driDisplay
*disp
= (driDisplay
*)ndpy
;
604 return &disp
->driScreen
;
609 __eglCreateContextWithConfig(__DRInativeDisplay
* ndpy
, int screen
,
610 int configID
, void* context
,
611 drm_context_t
* hHWContext
)
613 __DRIscreen
*pDRIScreen
;
614 __DRIscreenPrivate
*psp
;
616 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
617 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
620 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
622 if (drmCreateContext(psp
->fd
, hHWContext
)) {
623 _eglLog(_EGL_WARNING
, "drmCreateContext failed.");
626 *(void**)context
= (void*) *hHWContext
;
629 __DRIscreen
*pDRIScreen
;
630 __DRIscreenPrivate
*psp
;
632 pDRIScreen
= __glXFindDRIScreen(dpy
, screen
);
633 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
637 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
640 if (drmCreateContext(psp
->fd
, hHWContext
)) {
641 _eglLog(_EGL_WARNING
, "drmCreateContext failed.");
644 *(void**)contextID
= (void*) *hHWContext
;
652 __eglDestroyContext( __DRInativeDisplay
* ndpy
, int screen
, __DRIid context
)
654 __DRIscreen
*pDRIScreen
;
655 __DRIscreenPrivate
*psp
;
657 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
658 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
661 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
663 drmDestroyContext(psp
->fd
, context
);
670 __eglCreateDrawable(__DRInativeDisplay
* ndpy
, int screen
,
671 __DRIid drawable
, drm_drawable_t
* hHWDrawable
)
673 __DRIscreen
*pDRIScreen
;
674 __DRIscreenPrivate
*psp
;
676 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
677 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
680 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
682 if (drmCreateDrawable(psp
->fd
, hHWDrawable
)) {
683 _eglLog(_EGL_WARNING
, "drmCreateDrawable failed.");
692 __eglDestroyDrawable( __DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
)
694 __DRIscreen
*pDRIScreen
;
695 __DRIscreenPrivate
*psp
;
697 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
698 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
701 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
703 drmDestroyDrawable(psp
->fd
, drawable
);
709 __eglGetDrawableInfo(__DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
,
710 unsigned int* index
, unsigned int* stamp
,
711 int* X
, int* Y
, int* W
, int* H
,
712 int* numClipRects
, drm_clip_rect_t
** pClipRects
,
713 int* backX
, int* backY
,
714 int* numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
716 __DRIscreen
*pDRIScreen
;
717 __DRIscreenPrivate
*psp
;
718 driSurface
*surf
= Lookup_driSurface(drawable
);
720 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
722 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
725 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
728 *W
= surf
->Base
.Width
;
729 *H
= surf
->Base
.Height
;
733 *numBackClipRects
= 0;
734 *pBackClipRects
= NULL
;
737 *pClipRects
= malloc(sizeof(**pClipRects
));
738 **pClipRects
= (drm_clip_rect_t
){0, 0, surf
->Base
.Width
, surf
->Base
.Height
};
740 psp
->pSAREA
->drawableTable
[0].stamp
= 1;
743 GLXDrawable drawable
= (GLXDrawable
) draw
;
744 drm_clip_rect_t
* cliprect
;
745 Display
* display
= (Display
*)dpy
;
746 __DRIcontextPrivate
*pcp
= (__DRIcontextPrivate
*)CurrentContext
->driContext
.private;
751 cliprect
= (drm_clip_rect_t
*) _mesa_malloc(sizeof(drm_clip_rect_t
));
752 cliprect
->x1
= drawable
->x
;
753 cliprect
->y1
= drawable
->y
;
754 cliprect
->x2
= drawable
->x
+ drawable
->w
;
755 cliprect
->y2
= drawable
->y
+ drawable
->h
;
757 /* the drawable index is by client id */
758 *index
= display
->clientID
;
760 *stamp
= pcp
->driScreenPriv
->pSAREA
->drawableTable
[display
->clientID
].stamp
;
763 *width
= drawable
->w
;
764 *height
= drawable
->h
;
766 *pClipRects
= cliprect
;
768 *backX
= drawable
->x
;
769 *backY
= drawable
->y
;
770 *numBackClipRects
= 0;
778 * Implement \c __DRIinterfaceMethods::getProcAddress.
781 get_proc_address(const char * proc_name
)
788 * Destroy a linked list of \c __GLcontextModes structures created by
789 * \c _gl_context_modes_create.
791 * \param modes Linked list of structures to be destroyed. All structres
792 * in the list will be freed.
795 __egl_context_modes_destroy(__GLcontextModes
*modes
)
797 while ( modes
!= NULL
) {
798 __GLcontextModes
* const next
= modes
->next
;
807 * Allocate a linked list of \c __GLcontextModes structures. The fields of
808 * each structure will be initialized to "reasonable" default values. In
809 * most cases this is the default value defined by table 3.4 of the GLX
810 * 1.3 specification. This means that most values are either initialized to
811 * zero or \c GLX_DONT_CARE (which is -1). As support for additional
812 * extensions is added, the new values will be initialized to appropriate
813 * values from the extension specification.
815 * \param count Number of structures to allocate.
816 * \param minimum_size Minimum size of a structure to allocate. This allows
817 * for differences in the version of the
818 * \c __GLcontextModes stucture used in libGL and in a
820 * \returns A pointer to the first element in a linked list of \c count
821 * stuctures on success, or \c NULL on failure.
823 * \warning Use of \c minimum_size does \b not guarantee binary compatibility.
824 * The fundamental assumption is that if the \c minimum_size
825 * specified by the driver and the size of the \c __GLcontextModes
826 * structure in libGL is the same, then the meaning of each byte in
827 * the structure is the same in both places. \b Be \b careful!
828 * Basically this means that fields have to be added in libGL and
829 * then propagated to drivers. Drivers should \b never arbitrarilly
830 * extend the \c __GLcontextModes data-structure.
832 static __GLcontextModes
*
833 __egl_context_modes_create(unsigned count
, size_t minimum_size
)
835 const size_t size
= (minimum_size
> sizeof( __GLcontextModes
))
836 ? minimum_size
: sizeof( __GLcontextModes
);
837 __GLcontextModes
* base
= NULL
;
838 __GLcontextModes
** next
;
842 for ( i
= 0 ; i
< count
; i
++ ) {
843 *next
= (__GLcontextModes
*) malloc( size
);
844 if ( *next
== NULL
) {
845 __egl_context_modes_destroy( base
);
850 (void) memset( *next
, 0, size
);
851 (*next
)->visualID
= GLX_DONT_CARE
;
852 (*next
)->visualType
= GLX_DONT_CARE
;
853 (*next
)->visualRating
= GLX_NONE
;
854 (*next
)->transparentPixel
= GLX_NONE
;
855 (*next
)->transparentRed
= GLX_DONT_CARE
;
856 (*next
)->transparentGreen
= GLX_DONT_CARE
;
857 (*next
)->transparentBlue
= GLX_DONT_CARE
;
858 (*next
)->transparentAlpha
= GLX_DONT_CARE
;
859 (*next
)->transparentIndex
= GLX_DONT_CARE
;
860 (*next
)->xRenderable
= GLX_DONT_CARE
;
861 (*next
)->fbconfigID
= GLX_DONT_CARE
;
862 (*next
)->swapMethod
= GLX_SWAP_UNDEFINED_OML
;
864 next
= & ((*next
)->next
);
872 __eglWindowExists(__DRInativeDisplay
*dpy
, __DRIid draw
)
879 * Get the unadjusted system time (UST). Currently, the UST is measured in
880 * microseconds since Epoc. The actual resolution of the UST may vary from
881 * system to system, and the units may vary from release to release.
882 * Drivers should not call this function directly. They should instead use
883 * \c glXGetProcAddress to obtain a pointer to the function.
885 * \param ust Location to store the 64-bit UST
886 * \returns Zero on success or a negative errno value on failure.
888 * \sa glXGetProcAddress, PFNGLXGETUSTPROC
890 * \since Internal API version 20030317.
893 __eglGetUST(int64_t *ust
)
901 if ( gettimeofday( & tv
, NULL
) == 0 ) {
902 ust
[0] = (tv
.tv_sec
* 1000000) + tv
.tv_usec
;
911 * Determine the refresh rate of the specified drawable and display.
913 * \param dpy Display whose refresh rate is to be determined.
914 * \param drawable Drawable whose refresh rate is to be determined.
915 * \param numerator Numerator of the refresh rate.
916 * \param demoninator Denominator of the refresh rate.
917 * \return If the refresh rate for the specified display and drawable could
918 * be calculated, True is returned. Otherwise False is returned.
920 * \note This function is implemented entirely client-side. A lot of other
921 * functionality is required to export GLX_OML_sync_control, so on
922 * XFree86 this function can be called for direct-rendering contexts
923 * when GLX_OML_sync_control appears in the client extension string.
926 __eglGetMSCRate(__DRInativeDisplay
* dpy
, __DRIid drawable
,
927 int32_t * numerator
, int32_t * denominator
)
934 * Table of functions exported by the loader to the driver.
936 static const __DRIinterfaceMethods interface_methods
= {
939 __egl_context_modes_create
,
940 __egl_context_modes_destroy
,
945 __eglCreateContextWithConfig
,
949 __eglDestroyDrawable
,
950 __eglGetDrawableInfo
,
958 __glXGetInternalVersion(void)
963 static const char createNewScreenName
[] = "__driCreateNewScreen_20050727";
967 * Do per-display initialization.
970 _eglDRICreateDisplay(driDisplay
*dpy
, __DRIframebuffer
*framebuffer
)
972 PFNCREATENEWSCREENFUNC createNewScreen
;
973 int api_ver
= __glXGetInternalVersion();
974 __DRIversion ddx_version
;
975 __DRIversion dri_version
;
976 __DRIversion drm_version
;
977 drmVersionPtr version
;
979 version
= drmGetVersion( dpy
->drmFD
);
981 drm_version
.major
= version
->version_major
;
982 drm_version
.minor
= version
->version_minor
;
983 drm_version
.patch
= version
->version_patchlevel
;
984 drmFreeVersion( version
);
987 drm_version
.major
= -1;
988 drm_version
.minor
= -1;
989 drm_version
.patch
= -1;
993 * Get device name (like "tdfx") and the ddx version numbers.
994 * We'll check the version in each DRI driver's "createScreen"
997 ddx_version
.major
= 4;
998 ddx_version
.minor
= 0;
999 ddx_version
.patch
= 0;
1002 * Get the DRI X extension version.
1004 dri_version
.major
= 4;
1005 dri_version
.minor
= 0;
1006 dri_version
.patch
= 0;
1008 createNewScreen
= ( PFNCREATENEWSCREENFUNC
) dlsym( dpy
->Base
.Driver
->LibHandle
, createNewScreenName
);
1009 if ( !createNewScreen
) {
1010 _eglLog(_EGL_WARNING
, "Couldn't find %s function in the driver.",
1011 createNewScreenName
);
1015 dpy
->driScreen
.private = createNewScreen( dpy
, 0, &dpy
->driScreen
, NULL
,
1016 &ddx_version
, &dri_version
,
1017 &drm_version
, framebuffer
,
1018 dpy
->pSAREA
, dpy
->drmFD
,
1020 & interface_methods
,
1022 if (!dpy
->driScreen
.private)
1025 DRM_UNLOCK( dpy
->drmFD
, dpy
->pSAREA
, dpy
->serverContext
);
1032 * Create all the EGL screens for the given display.
1035 _eglDRICreateScreens(driDisplay
*dpy
)
1037 const int numScreens
= 1; /* XXX fix this someday */
1040 for (i
= 0; i
< numScreens
; i
++) {
1041 char path
[ NAME_MAX
];
1045 /* Create a screen */
1046 if ( !( s
= ( driScreen
* ) calloc( 1, sizeof( *s
) ) ) )
1049 snprintf( s
->fb
, NAME_MAX
, "fb%d", dpy
->minor
);
1050 _eglInitScreen( &s
->Base
);
1052 _eglAddScreen( &dpy
->Base
, &s
->Base
);
1054 /* Create the screen's mode list */
1055 snprintf( path
, sizeof( path
), "%s/graphics/%s/modes", sysfs
, s
->fb
);
1056 file
= fopen( path
, "r" );
1057 while ( fgets( path
, sizeof( path
), file
) ) {
1058 unsigned int x
, y
, r
;
1060 path
[ strlen( path
) - 1 ] = '\0'; /* strip off \n from sysfs */
1061 sscanf( path
, "%c:%ux%u-%u", &c
, &x
, &y
, &r
);
1062 _eglAddNewMode( &s
->Base
, x
, y
, r
* 1000, path
);
1067 * NOTE: we used to set the colormap here, but that didn't work reliably.
1068 * Some entries near the start of the table would get corrupted by later
1078 _eglDRIInitialize(_EGLDriver
*drv
, EGLDisplay dpy
,
1079 EGLint
*major
, EGLint
*minor
)
1081 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
1082 driDisplay
*display
;
1086 /* Create new driDisplay object to replace the _EGLDisplay that was
1087 * previously created.
1089 display
= calloc(1, sizeof(*display
));
1090 display
->Base
= *disp
;
1091 _eglHashInsert(_eglGlobal
.Displays
, disp
->Handle
, display
);
1097 sscanf(&disp
->Name
[1], "%d", &display
->minor
);
1099 drv
->Initialized
= EGL_TRUE
;
1105 _eglDRITerminate(_EGLDriver
*drv
, EGLDisplay dpy
)
1107 driDisplay
*display
= Lookup_driDisplay(dpy
);
1108 _eglCleanupDisplay(&display
->Base
);/*rename that function*/
1116 * Plug in the DRI-specific functions into the driver's dispatch table.
1117 * Also, enable some EGL extensions.
1120 _eglDRIInitDriverFallbacks(_EGLDriver
*drv
)
1122 _eglInitDriverFallbacks(drv
);
1124 drv
->API
.Initialize
= _eglDRIInitialize
;
1125 drv
->API
.Terminate
= _eglDRITerminate
;
1126 drv
->API
.CreateContext
= _eglDRICreateContext
;
1127 drv
->API
.MakeCurrent
= _eglDRIMakeCurrent
;
1128 drv
->API
.CreatePbufferSurface
= _eglDRICreatePbufferSurface
;
1129 drv
->API
.DestroySurface
= _eglDRIDestroySurface
;
1130 drv
->API
.DestroyContext
= _eglDRIDestroyContext
;
1131 drv
->API
.CreateScreenSurfaceMESA
= _eglDRICreateScreenSurfaceMESA
;
1132 drv
->API
.ShowScreenSurfaceMESA
= _eglDRIShowScreenSurfaceMESA
;
1133 drv
->API
.SwapBuffers
= _eglDRISwapBuffers
;
1135 /* enable supported extensions */
1136 drv
->Extensions
.MESA_screen_surface
= EGL_TRUE
;
1137 drv
->Extensions
.MESA_copy_context
= EGL_TRUE
;