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 * Show the given surface on the named screen.
310 * If surface is EGL_NO_SURFACE, disable the screen's output.
311 * Called via eglShowSurfaceMESA().
314 _eglDRIShowSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLScreenMESA screen
,
315 EGLSurface surface
, EGLModeMESA m
)
317 driDisplay
*display
= Lookup_driDisplay(dpy
);
318 driScreen
*scrn
= Lookup_driScreen(dpy
, screen
);
319 driSurface
*surf
= Lookup_driSurface(surface
);
320 _EGLMode
*mode
= _eglLookupMode(dpy
, m
);
322 char fname
[NAME_MAX
], buffer
[1000];
325 /* This will check that surface, screen, and mode are valid.
326 * Also, it checks that the surface is large enough for the mode, etc.
328 if (!_eglShowSurfaceMESA(drv
, dpy
, screen
, surface
, m
))
331 assert(surface
== EGL_NO_SURFACE
|| surf
);
332 assert(m
== EGL_NO_MODE_MESA
|| mode
);
336 * Blank/unblank screen depending on if m == EGL_NO_MODE_MESA
338 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/blank", sysfs
, scrn
->fb
);
339 file
= fopen(fname
, "r+");
341 _eglLog(_EGL_WARNING
, "kernel patch?? chown all fb sysfs attrib to allow"
342 " write - %s\n", fname
);
345 snprintf(buffer
, sizeof(buffer
), "%d",
346 (m
== EGL_NO_MODE_MESA
? VESA_POWERDOWN
: VESA_VSYNC_SUSPEND
));
350 if (m
== EGL_NO_MODE_MESA
) {
355 _eglLog(_EGL_INFO
, "Setting display mode to %d x %d, %d bpp",
356 mode
->Width
, mode
->Height
, display
->bpp
);
359 * Set the display mode
361 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/mode", sysfs
, scrn
->fb
);
362 file
= fopen(fname
, "r+");
364 _eglLog(_EGL_WARNING
, "Failed to open %s to set mode", fname
);
367 /* note: nothing happens without the \n! */
368 snprintf(buffer
, sizeof(buffer
), "%s\n", mode
->Name
);
371 _eglLog(_EGL_INFO
, "Set mode to %s in %s", mode
->Name
, fname
);
376 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/bits_per_pixel",
378 file
= fopen(fname
, "r+");
380 _eglLog(_EGL_WARNING
, "Failed to open %s to set bpp", fname
);
383 display
->bpp
= GET_CONFIG_ATTRIB(surf
->Base
.Config
, EGL_BUFFER_SIZE
);
384 display
->cpp
= display
->bpp
/ 8;
385 snprintf(buffer
, sizeof(buffer
), "%d", display
->bpp
);
392 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/blank", sysfs
, scrn
->fb
);
393 file
= fopen(fname
, "r+");
395 _eglLog(_EGL_WARNING
, "Failed to open %s", fname
);
398 snprintf(buffer
, sizeof(buffer
), "%d", VESA_NO_BLANKING
);
403 * Set fbdev buffer virtual size to surface's size.
405 snprintf(fname
, sizeof(fname
), "%s/graphics/%s/virtual_size", sysfs
, scrn
->fb
);
406 file
= fopen(fname
, "r+");
407 snprintf(buffer
, sizeof(buffer
), "%d,%d", surf
->Base
.Width
, surf
->Base
.Height
);
410 fgets(buffer
, sizeof(buffer
), file
);
411 sscanf(buffer
, "%d,%d", &display
->virtualWidth
, &display
->virtualHeight
);
415 * round up pitch as needed
417 temp
= display
->virtualWidth
;
418 switch (display
->bpp
/ 8) {
419 case 1: temp
= (display
->virtualWidth
+ 127) & ~127; break;
420 case 2: temp
= (display
->virtualWidth
+ 31) & ~31; break;
422 case 4: temp
= (display
->virtualWidth
+ 15) & ~15; break;
424 _eglLog(_EGL_WARNING
, "Bad display->bpp = %d in _eglDRIShowSurface");
426 display
->virtualWidth
= temp
;
431 if (surf
->Base
.Width
< display
->virtualWidth
||
432 surf
->Base
.Height
< display
->virtualHeight
) {
433 /* this case _should_ have been caught at the top of this function */
434 _eglLog(_EGL_WARNING
, "too small of surface in _eglDRIShowSurfaceMESA "
438 display
->virtualWidth
,
439 display
->virtualHeight
);
450 * Called by eglSwapBuffers via the drv->API.SwapBuffers() pointer.
452 * If the backbuffer is on a videocard, this is extraordinarily slow!
455 _eglDRISwapBuffers(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
)
457 driSurface
*drawable
= Lookup_driSurface(draw
);
459 /* this does error checking */
460 if (!_eglSwapBuffers(drv
, dpy
, draw
))
463 drawable
->drawable
.swapBuffers(NULL
, drawable
->drawable
.private);
470 _eglDRIGetDisplayInfo(driDisplay
*dpy
)
472 char path
[ NAME_MAX
];
478 drm_handle_t handle
, offset
;
483 snprintf( path
, sizeof( path
), "%s/graphics/fb%d/device/device", sysfs
, dpy
->minor
);
484 file
= fopen( path
, "r" );
486 _eglLog(_EGL_WARNING
, "Unable to open %s", path
);
489 fgets( path
, sizeof( path
), file
);
490 sscanf( path
, "%x", &dpy
->chipset
);
493 sprintf(path
, DRM_DEV_NAME
, DRM_DIR_NAME
, dpy
->minor
);
494 if ( ( dpy
->drmFD
= open(path
, O_RDWR
, 0) ) < 0 ) {
495 _eglLog(_EGL_WARNING
, "drmOpen failed.");
499 /* Set the interface version, asking for 1.2 */
502 sv
.drm_dd_major
= -1;
503 if ((rc
= drmSetInterfaceVersion(dpy
->drmFD
, &sv
)))
507 if (drmGetMagic(dpy
->drmFD
, &magic
))
509 if (drmAuthMagic(dpy
->drmFD
, magic
))
512 for ( i
= 0;; i
++ ) {
513 if ( ( rc
= drmGetMap( dpy
->drmFD
, i
, &offset
, &size
, &type
, &flags
, &handle
, &mtrr
) ) != 0 ) {
514 _eglLog(_EGL_WARNING
, "drmGetMap failed (%s)", strerror(errno
));
517 if ( type
== DRM_FRAME_BUFFER
) {
518 if ( ( rc
= drmMap( dpy
->drmFD
, offset
, size
, ( drmAddressPtr
) & dpy
->pFB
) ) < 0 ) {
519 _eglLog(_EGL_WARNING
, "drmMap failed");
525 _eglLog(_EGL_INFO
, "Map %d offset=0x%x", i
, (int) offset
);
528 _eglLog(_EGL_WARNING
, "failed to map framebuffer");
532 dpy
->SAREASize
= SAREA_MAX
;
534 for ( i
= 0;; i
++ ) {
535 if ( drmGetMap( dpy
->drmFD
, i
, &offset
, &size
, &type
, &flags
, &handle
, &mtrr
) != 0 )
537 if ( type
== DRM_SHM
) {
538 if ( drmMap( dpy
->drmFD
, offset
, size
, ( drmAddressPtr
) ( &dpy
->pSAREA
) ) < 0 ) {
539 _eglLog(_EGL_WARNING
, "drmMap failed.");
548 memset( dpy
->pSAREA
, 0, dpy
->SAREASize
);
550 _eglLog(_EGL_INFO
, "Found framebuffer size: %d", dpy
->fbSize
);
551 _eglLog(_EGL_DEBUG
, "mapped SAREA 0x%08lx to %p, size %d",
552 (unsigned long) offset
, dpy
->pSAREA
, dpy
->SAREASize
);
558 /* Return the DRI per screen structure */
560 __eglFindDRIScreen(__DRInativeDisplay
*ndpy
, int scrn
)
562 driDisplay
*disp
= (driDisplay
*)ndpy
;
563 return &disp
->driScreen
;
568 __eglCreateContextWithConfig(__DRInativeDisplay
* ndpy
, int screen
,
569 int configID
, void* context
,
570 drm_context_t
* hHWContext
)
572 __DRIscreen
*pDRIScreen
;
573 __DRIscreenPrivate
*psp
;
575 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
576 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
579 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
581 if (drmCreateContext(psp
->fd
, hHWContext
)) {
582 _eglLog(_EGL_WARNING
, "drmCreateContext failed.");
585 *(void**)context
= (void*) *hHWContext
;
588 __DRIscreen
*pDRIScreen
;
589 __DRIscreenPrivate
*psp
;
591 pDRIScreen
= __glXFindDRIScreen(dpy
, screen
);
592 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
596 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
599 if (drmCreateContext(psp
->fd
, hHWContext
)) {
600 _eglLog(_EGL_WARNING
, "drmCreateContext failed.");
603 *(void**)contextID
= (void*) *hHWContext
;
611 __eglDestroyContext( __DRInativeDisplay
* ndpy
, int screen
, __DRIid context
)
613 __DRIscreen
*pDRIScreen
;
614 __DRIscreenPrivate
*psp
;
616 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
617 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
620 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
622 drmDestroyContext(psp
->fd
, context
);
629 __eglCreateDrawable(__DRInativeDisplay
* ndpy
, int screen
,
630 __DRIid drawable
, drm_drawable_t
* hHWDrawable
)
632 __DRIscreen
*pDRIScreen
;
633 __DRIscreenPrivate
*psp
;
635 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
636 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
639 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
641 if (drmCreateDrawable(psp
->fd
, hHWDrawable
)) {
642 _eglLog(_EGL_WARNING
, "drmCreateDrawable failed.");
651 __eglDestroyDrawable( __DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
)
653 __DRIscreen
*pDRIScreen
;
654 __DRIscreenPrivate
*psp
;
656 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
657 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
660 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
662 drmDestroyDrawable(psp
->fd
, drawable
);
668 __eglGetDrawableInfo(__DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
,
669 unsigned int* index
, unsigned int* stamp
,
670 int* X
, int* Y
, int* W
, int* H
,
671 int* numClipRects
, drm_clip_rect_t
** pClipRects
,
672 int* backX
, int* backY
,
673 int* numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
675 driSurface
*surf
= Lookup_driSurface(drawable
);
679 *W
= surf
->Base
.Width
;
680 *H
= surf
->Base
.Height
;
683 *pClipRects
= malloc(sizeof(**pClipRects
));
684 **pClipRects
= (drm_clip_rect_t
){0, 0, surf
->Base
.Width
, surf
->Base
.Height
};
687 GLXDrawable drawable
= (GLXDrawable
) draw
;
688 drm_clip_rect_t
* cliprect
;
689 Display
* display
= (Display
*)dpy
;
690 __DRIcontextPrivate
*pcp
= (__DRIcontextPrivate
*)CurrentContext
->driContext
.private;
695 cliprect
= (drm_clip_rect_t
*) _mesa_malloc(sizeof(drm_clip_rect_t
));
696 cliprect
->x1
= drawable
->x
;
697 cliprect
->y1
= drawable
->y
;
698 cliprect
->x2
= drawable
->x
+ drawable
->w
;
699 cliprect
->y2
= drawable
->y
+ drawable
->h
;
701 /* the drawable index is by client id */
702 *index
= display
->clientID
;
704 *stamp
= pcp
->driScreenPriv
->pSAREA
->drawableTable
[display
->clientID
].stamp
;
707 *width
= drawable
->w
;
708 *height
= drawable
->h
;
710 *pClipRects
= cliprect
;
712 *backX
= drawable
->x
;
713 *backY
= drawable
->y
;
714 *numBackClipRects
= 0;
722 * Implement \c __DRIinterfaceMethods::getProcAddress.
725 get_proc_address(const char * proc_name
)
732 * Destroy a linked list of \c __GLcontextModes structures created by
733 * \c _gl_context_modes_create.
735 * \param modes Linked list of structures to be destroyed. All structres
736 * in the list will be freed.
739 __egl_context_modes_destroy(__GLcontextModes
*modes
)
741 while ( modes
!= NULL
) {
742 __GLcontextModes
* const next
= modes
->next
;
751 * Allocate a linked list of \c __GLcontextModes structures. The fields of
752 * each structure will be initialized to "reasonable" default values. In
753 * most cases this is the default value defined by table 3.4 of the GLX
754 * 1.3 specification. This means that most values are either initialized to
755 * zero or \c GLX_DONT_CARE (which is -1). As support for additional
756 * extensions is added, the new values will be initialized to appropriate
757 * values from the extension specification.
759 * \param count Number of structures to allocate.
760 * \param minimum_size Minimum size of a structure to allocate. This allows
761 * for differences in the version of the
762 * \c __GLcontextModes stucture used in libGL and in a
764 * \returns A pointer to the first element in a linked list of \c count
765 * stuctures on success, or \c NULL on failure.
767 * \warning Use of \c minimum_size does \b not guarantee binary compatibility.
768 * The fundamental assumption is that if the \c minimum_size
769 * specified by the driver and the size of the \c __GLcontextModes
770 * structure in libGL is the same, then the meaning of each byte in
771 * the structure is the same in both places. \b Be \b careful!
772 * Basically this means that fields have to be added in libGL and
773 * then propagated to drivers. Drivers should \b never arbitrarilly
774 * extend the \c __GLcontextModes data-structure.
776 static __GLcontextModes
*
777 __egl_context_modes_create(unsigned count
, size_t minimum_size
)
779 const size_t size
= (minimum_size
> sizeof( __GLcontextModes
))
780 ? minimum_size
: sizeof( __GLcontextModes
);
781 __GLcontextModes
* base
= NULL
;
782 __GLcontextModes
** next
;
786 for ( i
= 0 ; i
< count
; i
++ ) {
787 *next
= (__GLcontextModes
*) malloc( size
);
788 if ( *next
== NULL
) {
789 __egl_context_modes_destroy( base
);
794 (void) memset( *next
, 0, size
);
795 (*next
)->visualID
= GLX_DONT_CARE
;
796 (*next
)->visualType
= GLX_DONT_CARE
;
797 (*next
)->visualRating
= GLX_NONE
;
798 (*next
)->transparentPixel
= GLX_NONE
;
799 (*next
)->transparentRed
= GLX_DONT_CARE
;
800 (*next
)->transparentGreen
= GLX_DONT_CARE
;
801 (*next
)->transparentBlue
= GLX_DONT_CARE
;
802 (*next
)->transparentAlpha
= GLX_DONT_CARE
;
803 (*next
)->transparentIndex
= GLX_DONT_CARE
;
804 (*next
)->xRenderable
= GLX_DONT_CARE
;
805 (*next
)->fbconfigID
= GLX_DONT_CARE
;
806 (*next
)->swapMethod
= GLX_SWAP_UNDEFINED_OML
;
808 next
= & ((*next
)->next
);
816 __eglWindowExists(__DRInativeDisplay
*dpy
, __DRIid draw
)
823 * Get the unadjusted system time (UST). Currently, the UST is measured in
824 * microseconds since Epoc. The actual resolution of the UST may vary from
825 * system to system, and the units may vary from release to release.
826 * Drivers should not call this function directly. They should instead use
827 * \c glXGetProcAddress to obtain a pointer to the function.
829 * \param ust Location to store the 64-bit UST
830 * \returns Zero on success or a negative errno value on failure.
832 * \sa glXGetProcAddress, PFNGLXGETUSTPROC
834 * \since Internal API version 20030317.
837 __eglGetUST(int64_t *ust
)
845 if ( gettimeofday( & tv
, NULL
) == 0 ) {
846 ust
[0] = (tv
.tv_sec
* 1000000) + tv
.tv_usec
;
855 * Determine the refresh rate of the specified drawable and display.
857 * \param dpy Display whose refresh rate is to be determined.
858 * \param drawable Drawable whose refresh rate is to be determined.
859 * \param numerator Numerator of the refresh rate.
860 * \param demoninator Denominator of the refresh rate.
861 * \return If the refresh rate for the specified display and drawable could
862 * be calculated, True is returned. Otherwise False is returned.
864 * \note This function is implemented entirely client-side. A lot of other
865 * functionality is required to export GLX_OML_sync_control, so on
866 * XFree86 this function can be called for direct-rendering contexts
867 * when GLX_OML_sync_control appears in the client extension string.
870 __eglGetMSCRate(__DRInativeDisplay
* dpy
, __DRIid drawable
,
871 int32_t * numerator
, int32_t * denominator
)
878 * Table of functions exported by the loader to the driver.
880 static const __DRIinterfaceMethods interface_methods
= {
883 __egl_context_modes_create
,
884 __egl_context_modes_destroy
,
889 __eglCreateContextWithConfig
,
893 __eglDestroyDrawable
,
894 __eglGetDrawableInfo
,
902 __glXGetInternalVersion(void)
907 static const char createNewScreenName
[] = "__driCreateNewScreen_20050727";
911 * Do per-display initialization.
914 _eglDRICreateDisplay(driDisplay
*dpy
, __DRIframebuffer
*framebuffer
)
916 PFNCREATENEWSCREENFUNC createNewScreen
;
917 int api_ver
= __glXGetInternalVersion();
918 __DRIversion ddx_version
;
919 __DRIversion dri_version
;
920 __DRIversion drm_version
;
921 drmVersionPtr version
;
923 version
= drmGetVersion( dpy
->drmFD
);
925 drm_version
.major
= version
->version_major
;
926 drm_version
.minor
= version
->version_minor
;
927 drm_version
.patch
= version
->version_patchlevel
;
928 drmFreeVersion( version
);
931 drm_version
.major
= -1;
932 drm_version
.minor
= -1;
933 drm_version
.patch
= -1;
937 * Get device name (like "tdfx") and the ddx version numbers.
938 * We'll check the version in each DRI driver's "createScreen"
941 ddx_version
.major
= 4;
942 ddx_version
.minor
= 0;
943 ddx_version
.patch
= 0;
946 * Get the DRI X extension version.
948 dri_version
.major
= 4;
949 dri_version
.minor
= 0;
950 dri_version
.patch
= 0;
952 createNewScreen
= ( PFNCREATENEWSCREENFUNC
) dlsym( dpy
->Base
.Driver
->LibHandle
, createNewScreenName
);
953 if ( !createNewScreen
) {
954 _eglLog(_EGL_WARNING
, "Couldn't find %s function in the driver.",
955 createNewScreenName
);
959 dpy
->driScreen
.private = createNewScreen( dpy
, 0, &dpy
->driScreen
, NULL
,
960 &ddx_version
, &dri_version
,
961 &drm_version
, framebuffer
,
962 dpy
->pSAREA
, dpy
->drmFD
,
966 if (!dpy
->driScreen
.private)
969 DRM_UNLOCK( dpy
->drmFD
, dpy
->pSAREA
, dpy
->serverContext
);
976 * Create all the EGL screens for the given display.
979 _eglDRICreateScreens(driDisplay
*dpy
)
981 const int numScreens
= 1; /* XXX fix this someday */
984 for (i
= 0; i
< numScreens
; i
++) {
985 char path
[ NAME_MAX
];
989 /* Create a screen */
990 if ( !( s
= ( driScreen
* ) calloc( 1, sizeof( *s
) ) ) )
993 snprintf( s
->fb
, NAME_MAX
, "fb%d", dpy
->minor
);
994 _eglInitScreen( &s
->Base
);
996 _eglAddScreen( &dpy
->Base
, &s
->Base
);
998 /* Create the screen's mode list */
999 snprintf( path
, sizeof( path
), "%s/graphics/%s/modes", sysfs
, s
->fb
);
1000 file
= fopen( path
, "r" );
1001 while ( fgets( path
, sizeof( path
), file
) ) {
1002 unsigned int x
, y
, r
;
1004 path
[ strlen( path
) - 1 ] = '\0'; /* strip off \n from sysfs */
1005 sscanf( path
, "%c:%ux%u-%u", &c
, &x
, &y
, &r
);
1006 _eglAddMode( &s
->Base
, x
, y
, r
* 1000, path
);
1011 * Initialize the colormap. XXX is this per-screen?
1017 /* cmap attribute uses 256 lines of 16 bytes */
1018 if ( !( buffer
= malloc( 256 * 16 ) ) )
1021 /* cmap attribute uses 256 lines of 16 bytes */
1022 for ( i
= 0; i
< 256; i
++ )
1023 sprintf( &buffer
[ i
* 16 ], "%02x%c%4x%4x%4x\n",
1024 i
, ' ', 256 * i
, 256 * i
, 256 * i
);
1026 snprintf(path
, sizeof(path
), "%s/graphics/%s/color_map", sysfs
,s
->fb
);
1027 if ( !( fd
= open( path
, O_RDWR
) ) )
1029 write( fd
, buffer
, 256 * 16 );
1041 _eglDRIInitialize(_EGLDriver
*drv
, EGLDisplay dpy
,
1042 EGLint
*major
, EGLint
*minor
)
1044 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
1045 driDisplay
*display
;
1049 /* Create new driDisplay object to replace the _EGLDisplay that was
1050 * previously created.
1052 display
= calloc(1, sizeof(*display
));
1053 display
->Base
= *disp
;
1054 _eglHashInsert(_eglGlobal
.Displays
, disp
->Handle
, display
);
1060 sscanf(&disp
->Name
[1], "%d", &display
->minor
);
1062 drv
->Initialized
= EGL_TRUE
;
1068 _eglDRITerminate(_EGLDriver
*drv
, EGLDisplay dpy
)
1070 driDisplay
*display
= Lookup_driDisplay(dpy
);
1071 _eglCleanupDisplay(&display
->Base
);/*rename that function*/
1079 * Plug in the DRI-specific functions into the driver's dispatch table.
1080 * Also, enable some EGL extensions.
1083 _eglDRIInitDriverFallbacks(_EGLDriver
*drv
)
1085 _eglInitDriverFallbacks(drv
);
1087 drv
->API
.Initialize
= _eglDRIInitialize
;
1088 drv
->API
.Terminate
= _eglDRITerminate
;
1089 drv
->API
.CreateContext
= _eglDRICreateContext
;
1090 drv
->API
.MakeCurrent
= _eglDRIMakeCurrent
;
1091 drv
->API
.CreatePbufferSurface
= _eglDRICreatePbufferSurface
;
1092 drv
->API
.DestroySurface
= _eglDRIDestroySurface
;
1093 drv
->API
.DestroyContext
= _eglDRIDestroyContext
;
1094 drv
->API
.CreateScreenSurfaceMESA
= _eglDRICreateScreenSurfaceMESA
;
1095 drv
->API
.ShowSurfaceMESA
= _eglDRIShowSurfaceMESA
;
1096 drv
->API
.SwapBuffers
= _eglDRISwapBuffers
;
1098 /* enable supported extensions */
1099 drv
->MESA_screen_surface
= EGL_TRUE
;
1100 drv
->MESA_copy_context
= EGL_TRUE
;