2 * Generic EGL driver for DRI
15 #include "egldriver.h"
16 #include "egldisplay.h"
17 #include "eglcontext.h"
18 #include "eglconfig.h"
19 #include "eglsurface.h"
20 #include "eglscreen.h"
21 #include "eglglobals.h"
26 const char *sysfs
= "/sys/class";
28 static const int empty_attribute_list
[1] = { None
};
31 * The bootstrap function. Return a new driDriver object and
32 * plug in API functions.
35 _eglMain(_EGLDisplay
*dpy
)
39 struct dirent
*dirent
;
42 _EGLDriver
*driver
= NULL
;;
44 snprintf(path
, sizeof(path
), "%s/drm", sysfs
);
45 if (!(dir
= opendir(path
))) {
46 printf("EGL - %s DRM devices not found.", path
);
49 while ((dirent
= readdir(dir
))) {
51 if (strncmp(&dirent
->d_name
[0], "card", 4) != 0)
53 if (strcmp(&dirent
->d_name
[4], &dpy
->Name
[1]) != 0)
56 snprintf(path
, sizeof(path
), "%s/drm/card%s/dri_library_name", sysfs
, &dpy
->Name
[1]);
57 file
= fopen(path
, "r");
58 fgets(path
, sizeof(path
), file
);
61 if ((length
= strlen(path
)) > 0)
62 path
[length
- 1] = '\0'; /* remove the trailing newline from sysfs */
63 strncat(path
, "_dri", sizeof(path
));
65 driver
= _eglOpenDriver(dpy
, path
);
76 _eglDRICreateContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, EGLContext share_list
, const EGLint
*attrib_list
)
80 driDisplay
*disp
= Lookup_driDisplay(dpy
);
81 driContext
*share
= Lookup_driContext(share_list
);
83 __GLcontextModes mode
;
86 conf
= _eglLookupConfig(drv
, dpy
, config
);
88 _eglError(EGL_BAD_CONFIG
, "eglCreateContext");
89 return EGL_NO_CONTEXT
;
92 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
93 switch (attrib_list
[i
]) {
94 /* no attribs defined for now */
96 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreateContext");
97 return EGL_NO_CONTEXT
;
101 c
= (driContext
*) calloc(1, sizeof(*c
));
103 return EGL_NO_CONTEXT
;
105 _eglInitContext(&c
->Base
);
106 c
->Base
.Display
= &disp
->Base
;
107 c
->Base
.Config
= conf
;
108 c
->Base
.DrawSurface
= EGL_NO_SURFACE
;
109 c
->Base
.ReadSurface
= EGL_NO_SURFACE
;
111 _eglConfigToContextModesRec(conf
, &mode
);
114 sharePriv
= share
->driContext
.private;
118 c
->driContext
.private = disp
->driScreen
.createNewContext(disp
, &mode
,
119 GLX_WINDOW_BIT
, sharePriv
, &c
->driContext
);
121 if (!c
->driContext
.private) {
126 /* generate handle and insert into hash table */
127 _eglSaveContext(&c
->Base
);
128 assert(c
->Base
.Handle
);
130 return c
->Base
.Handle
;
135 _eglDRIMakeCurrent(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
, EGLSurface read
, EGLContext context
)
137 driDisplay
*disp
= Lookup_driDisplay(dpy
);
138 driContext
*ctx
= Lookup_driContext(context
);
141 b
= _eglMakeCurrent(drv
, dpy
, draw
, read
, context
);
146 ctx
->driContext
.bindContext(disp
, 0, read
, draw
, &ctx
->driContext
);
148 // _mesa_make_current( NULL, NULL, NULL );
155 _eglDRICreateWindowSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, NativeWindowType window
, const EGLint
*attrib_list
)
158 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
159 switch (attrib_list
[i
]) {
160 /* no attribs at this time */
162 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreateWindowSurface");
163 return EGL_NO_SURFACE
;
166 printf("eglCreateWindowSurface()\n");
169 return EGL_NO_SURFACE
;
174 _eglDRICreatePixmapSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, NativePixmapType pixmap
, const EGLint
*attrib_list
)
179 conf
= _eglLookupConfig(drv
, dpy
, config
);
181 _eglError(EGL_BAD_CONFIG
, "eglCreatePixmapSurface");
182 return EGL_NO_SURFACE
;
185 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
186 switch (attrib_list
[i
]) {
187 /* no attribs at this time */
189 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreatePixmapSurface");
190 return EGL_NO_SURFACE
;
194 if (conf
->Attrib
[EGL_SURFACE_TYPE
- FIRST_ATTRIB
] == 0) {
195 _eglError(EGL_BAD_MATCH
, "eglCreatePixmapSurface");
196 return EGL_NO_SURFACE
;
199 printf("eglCreatePixmapSurface()\n");
200 return EGL_NO_SURFACE
;
205 _eglDRICreatePbufferSurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig config
, const EGLint
*attrib_list
)
209 surf
= (driSurface
*) calloc(1, sizeof(*surf
));
211 return EGL_NO_SURFACE
;
214 if (_eglInitPbufferSurface(&surf
->Base
, drv
, dpy
, config
, attrib_list
) == EGL_NO_SURFACE
) {
216 return EGL_NO_SURFACE
;
219 /* create software-based pbuffer */
221 // GLcontext *ctx = NULL; /* this _should_ be OK */
223 _EGLConfig
*conf
= _eglLookupConfig(drv
, dpy
, config
);
224 assert(conf
); /* bad config should be caught earlier */
225 _eglConfigToContextModesRec(conf
, &vis
);
228 surf
->mesa_framebuffer
= _mesa_create_framebuffer(&vis
);
229 _mesa_add_soft_renderbuffers(surf
->mesa_framebuffer
,
230 GL_TRUE
, /* color bufs */
232 vis
.haveStencilBuffer
,
234 GL_FALSE
, /* alpha */
235 GL_FALSE
/* aux */ );
237 /* set pbuffer/framebuffer size */
238 _mesa_resize_framebuffer(ctx
, surf
->mesa_framebuffer
,
239 surf
->Base
.Width
, surf
->Base
.Height
);
243 return surf
->Base
.Handle
;
248 _eglDRIDestroySurface(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface surface
)
250 driDisplay
*disp
= Lookup_driDisplay(dpy
);
251 driSurface
*fs
= Lookup_driSurface(surface
);
252 _eglRemoveSurface(&fs
->Base
);
254 fs
->drawable
.destroyDrawable(disp
, fs
->drawable
.private);
256 if (fs
->Base
.IsBound
) {
257 fs
->Base
.DeletePending
= EGL_TRUE
;
267 _eglDRIDestroyContext(_EGLDriver
*drv
, EGLDisplay dpy
, EGLContext context
)
269 driDisplay
*disp
= Lookup_driDisplay(dpy
);
270 driContext
*fc
= Lookup_driContext(context
);
272 _eglRemoveContext(&fc
->Base
);
274 fc
->driContext
.destroyContext(disp
, 0, fc
->driContext
.private);
276 if (fc
->Base
.IsBound
) {
277 fc
->Base
.DeletePending
= EGL_TRUE
;
286 * Create a drawing surface which can be directly displayed on a screen.
289 _eglDRICreateScreenSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLConfig cfg
,
290 const EGLint
*attrib_list
)
292 _EGLConfig
*config
= _eglLookupConfig(drv
, dpy
, cfg
);
293 driDisplay
*disp
= Lookup_driDisplay(dpy
);
298 surface
= (driSurface
*) malloc(sizeof(*surface
));
300 return EGL_NO_SURFACE
;
303 /* init base class, error check, etc. */
304 surf
= _eglInitScreenSurface(&surface
->Base
, drv
, dpy
, cfg
, attrib_list
);
305 if (surf
== EGL_NO_SURFACE
) {
307 return EGL_NO_SURFACE
;
310 /* convert EGLConfig to GLvisual */
311 _eglConfigToContextModesRec(config
, &vis
);
313 /* Create a new drawable */
314 if (!disp
->driScreen
.createNewDrawable(disp
, &vis
, surf
, &surface
->drawable
,
315 GLX_WINDOW_BIT
, empty_attribute_list
)) {
317 _eglRemoveSurface(&surface
->Base
);
318 return EGL_NO_SURFACE
;
325 * Show the given surface on the named screen.
326 * If surface is EGL_NO_SURFACE, disable the screen's output.
329 _eglDRIShowSurfaceMESA(_EGLDriver
*drv
, EGLDisplay dpy
, EGLScreenMESA screen
,
330 EGLSurface surface
, EGLModeMESA m
)
332 driDisplay
*display
= Lookup_driDisplay(dpy
);
333 driScreen
*scrn
= Lookup_driScreen(dpy
, screen
);
334 driSurface
*surf
= Lookup_driSurface(surface
);
336 char buffer
[NAME_MAX
];
337 _EGLMode
*mode
= _eglLookupMode(dpy
, m
);
338 int width
, height
, temp
;
340 _eglQuerySurface(drv
, dpy
, surface
, EGL_WIDTH
, &width
);
341 _eglQuerySurface(drv
, dpy
, surface
, EGL_HEIGHT
, &height
);
343 if (!_eglShowSurfaceMESA(drv
, dpy
, screen
, surface
, m
))
346 snprintf(buffer
, sizeof(buffer
), "%s/graphics/%s/blank", sysfs
, scrn
->fb
);
348 file
= fopen(buffer
, "r+");
351 printf("kernel patch?? chown all fb sysfs attrib to allow write - %s\n", buffer
);
352 _eglError(EGL_BAD_SURFACE
, "eglShowSurfaceMESA");
355 snprintf(buffer
, sizeof(buffer
), "%d", (m
== EGL_NO_MODE_MESA
? VESA_POWERDOWN
: VESA_VSYNC_SUSPEND
));
359 if (m
== EGL_NO_MODE_MESA
)
362 snprintf(buffer
, sizeof(buffer
), "%s/graphics/%s/mode", sysfs
, scrn
->fb
);
364 file
= fopen(buffer
, "r+");
367 fputs(mode
->Name
, file
);
370 snprintf(buffer
, sizeof(buffer
), "%s/graphics/%s/bits_per_pixel", sysfs
, scrn
->fb
);
372 file
= fopen(buffer
, "r+");
375 display
->bpp
= GET_CONFIG_ATTRIB(surf
->Base
.Config
, EGL_BUFFER_SIZE
);
376 display
->cpp
= display
->bpp
/ 8;
377 snprintf(buffer
, sizeof(buffer
), "%d", display
->bpp
);
381 snprintf(buffer
, sizeof(buffer
), "%s/graphics/%s/blank", sysfs
, scrn
->fb
);
383 file
= fopen(buffer
, "r+");
387 snprintf(buffer
, sizeof(buffer
), "%d", VESA_NO_BLANKING
);
391 snprintf(buffer
, sizeof(buffer
), "%s/graphics/%s/virtual_size", sysfs
, scrn
->fb
);
392 file
= fopen(buffer
, "r+");
393 snprintf(buffer
, sizeof(buffer
), "%d,%d", width
, height
);
396 fgets(buffer
, sizeof(buffer
), file
);
397 sscanf(buffer
, "%d,%d", &display
->virtualWidth
, &display
->virtualHeight
);
400 temp
= display
->virtualWidth
;
401 switch (display
->bpp
/ 8) {
402 case 1: temp
= (display
->virtualWidth
+ 127) & ~127; break;
403 case 2: temp
= (display
->virtualWidth
+ 31) & ~31; break;
405 case 4: temp
= (display
->virtualWidth
+ 15) & ~15; break;
407 display
->virtualWidth
= temp
;
409 if ((width
!= display
->virtualWidth
) || (height
!= display
->virtualHeight
))
416 /* If the backbuffer is on a videocard, this is extraordinarily slow!
419 _eglDRISwapBuffers(_EGLDriver
*drv
, EGLDisplay dpy
, EGLSurface draw
)
421 driSurface
*drawable
= Lookup_driSurface(draw
);
423 if (!_eglSwapBuffers(drv
, dpy
, draw
))
426 drawable
->drawable
.swapBuffers(NULL
, drawable
->drawable
.private);
433 _eglDRIGetDisplayInfo( driDisplay
*dpy
) {
434 char path
[ NAME_MAX
];
440 drm_handle_t handle
, offset
;
445 snprintf( path
, sizeof( path
), "%s/graphics/fb%d/device/device", sysfs
, dpy
->minor
);
446 file
= fopen( path
, "r" );
447 fgets( path
, sizeof( path
), file
);
448 sscanf( path
, "%x", &dpy
->chipset
);
451 sprintf(path
, DRM_DEV_NAME
, DRM_DIR_NAME
, dpy
->minor
);
452 if ( ( dpy
->drmFD
= open(path
, O_RDWR
, 0) ) < 0 ) {
453 fprintf( stderr
, "[drm] drmOpen failed\n" );
457 /* Set the interface version, asking for 1.2 */
460 sv
.drm_dd_major
= -1;
461 if ((rc
= drmSetInterfaceVersion(dpy
->drmFD
, &sv
)))
465 if (drmGetMagic(dpy
->drmFD
, &magic
))
467 if (drmAuthMagic(dpy
->drmFD
, magic
))
470 for ( i
= 0;; i
++ ) {
471 if ( ( rc
= drmGetMap( dpy
->drmFD
, i
, &offset
, &size
, &type
, &flags
, &handle
, &mtrr
) ) != 0 )
473 if ( type
== DRM_FRAME_BUFFER
) {
474 if ( ( rc
= drmMap( dpy
->drmFD
, offset
, size
, ( drmAddressPtr
) & dpy
->pFB
) ) < 0 )
483 dpy
->SAREASize
= SAREA_MAX
;
485 for ( i
= 0;; i
++ ) {
486 if ( drmGetMap( dpy
->drmFD
, i
, &offset
, &size
, &type
, &flags
, &handle
, &mtrr
) != 0 )
488 if ( type
== DRM_SHM
) {
489 if ( drmMap( dpy
->drmFD
, offset
, size
, ( drmAddressPtr
) ( &dpy
->pSAREA
) ) < 0 ) {
490 fprintf( stderr
, "[drm] drmMap failed\n" );
499 memset( dpy
->pSAREA
, 0, dpy
->SAREASize
);
500 fprintf( stderr
, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
501 offset
, dpy
->pSAREA
, dpy
->SAREASize
);
506 /* Return the DRI per screen structure */
507 static __DRIscreen
*__eglFindDRIScreen(__DRInativeDisplay
*ndpy
, int scrn
)
509 driDisplay
*disp
= (driDisplay
*)ndpy
;
510 return &disp
->driScreen
;
513 static GLboolean
__eglCreateContextWithConfig(__DRInativeDisplay
* ndpy
, int screen
, int configID
, void* context
, drm_context_t
* hHWContext
)
515 __DRIscreen
*pDRIScreen
;
516 __DRIscreenPrivate
*psp
;
518 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
519 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
522 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
524 if (drmCreateContext(psp
->fd
, hHWContext
)) {
525 fprintf(stderr
, ">>> drmCreateContext failed\n");
528 *(void**)context
= (void*) *hHWContext
;
531 __DRIscreen
*pDRIScreen
;
532 __DRIscreenPrivate
*psp
;
534 pDRIScreen
= __glXFindDRIScreen(dpy
, screen
);
535 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
539 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
542 if (drmCreateContext(psp
->fd
, hHWContext
)) {
543 fprintf(stderr
, ">>> drmCreateContext failed\n");
546 *(void**)contextID
= (void*) *hHWContext
;
552 static GLboolean
__eglDestroyContext( __DRInativeDisplay
* ndpy
, int screen
, __DRIid context
)
554 __DRIscreen
*pDRIScreen
;
555 __DRIscreenPrivate
*psp
;
557 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
558 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
561 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
563 drmDestroyContext(psp
->fd
, context
);
568 static GLboolean
__eglCreateDrawable( __DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
, drm_drawable_t
* hHWDrawable
)
570 __DRIscreen
*pDRIScreen
;
571 __DRIscreenPrivate
*psp
;
573 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
574 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
577 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
579 if (drmCreateDrawable(psp
->fd
, hHWDrawable
)) {
580 fprintf(stderr
, ">>> drmCreateDrawable failed\n");
587 static GLboolean
__eglDestroyDrawable( __DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
)
589 __DRIscreen
*pDRIScreen
;
590 __DRIscreenPrivate
*psp
;
592 pDRIScreen
= __eglFindDRIScreen(ndpy
, screen
);
593 if ( (pDRIScreen
== NULL
) || (pDRIScreen
->private == NULL
) ) {
596 psp
= (__DRIscreenPrivate
*) pDRIScreen
->private;
598 drmDestroyDrawable(psp
->fd
, drawable
);
603 static GLboolean
__eglGetDrawableInfo(__DRInativeDisplay
* ndpy
, int screen
, __DRIid drawable
,
604 unsigned int* index
, unsigned int* stamp
,
605 int* X
, int* Y
, int* W
, int* H
,
606 int* numClipRects
, drm_clip_rect_t
** pClipRects
,
607 int* backX
, int* backY
,
608 int* numBackClipRects
, drm_clip_rect_t
** pBackClipRects
)
610 driSurface
*surf
= Lookup_driSurface(drawable
);
614 *W
= surf
->Base
.Width
;
615 *H
= surf
->Base
.Height
;
618 *pClipRects
= malloc(sizeof(**pClipRects
));
619 **pClipRects
= (drm_clip_rect_t
){0, 0, surf
->Base
.Width
, surf
->Base
.Height
};
622 GLXDrawable drawable
= (GLXDrawable
) draw
;
623 drm_clip_rect_t
* cliprect
;
624 Display
* display
= (Display
*)dpy
;
625 __DRIcontextPrivate
*pcp
= (__DRIcontextPrivate
*)CurrentContext
->driContext
.private;
630 cliprect
= (drm_clip_rect_t
*) _mesa_malloc(sizeof(drm_clip_rect_t
));
631 cliprect
->x1
= drawable
->x
;
632 cliprect
->y1
= drawable
->y
;
633 cliprect
->x2
= drawable
->x
+ drawable
->w
;
634 cliprect
->y2
= drawable
->y
+ drawable
->h
;
636 /* the drawable index is by client id */
637 *index
= display
->clientID
;
639 *stamp
= pcp
->driScreenPriv
->pSAREA
->drawableTable
[display
->clientID
].stamp
;
642 *width
= drawable
->w
;
643 *height
= drawable
->h
;
645 *pClipRects
= cliprect
;
647 *backX
= drawable
->x
;
648 *backY
= drawable
->y
;
649 *numBackClipRects
= 0;
656 * Implement \c __DRIinterfaceMethods::getProcAddress.
658 static __DRIfuncPtr
get_proc_address( const char * proc_name
)
661 if (strcmp( proc_name
, "glxEnableExtension" ) == 0) {
662 return (__DRIfuncPtr
) __glXScrEnableExtension
;
670 * Destroy a linked list of \c __GLcontextModes structures created by
671 * \c _gl_context_modes_create.
673 * \param modes Linked list of structures to be destroyed. All structres
674 * in the list will be freed.
677 __egl_context_modes_destroy( __GLcontextModes
* modes
)
679 while ( modes
!= NULL
) {
680 __GLcontextModes
* const next
= modes
->next
;
689 * Allocate a linked list of \c __GLcontextModes structures. The fields of
690 * each structure will be initialized to "reasonable" default values. In
691 * most cases this is the default value defined by table 3.4 of the GLX
692 * 1.3 specification. This means that most values are either initialized to
693 * zero or \c GLX_DONT_CARE (which is -1). As support for additional
694 * extensions is added, the new values will be initialized to appropriate
695 * values from the extension specification.
697 * \param count Number of structures to allocate.
698 * \param minimum_size Minimum size of a structure to allocate. This allows
699 * for differences in the version of the
700 * \c __GLcontextModes stucture used in libGL and in a
702 * \returns A pointer to the first element in a linked list of \c count
703 * stuctures on success, or \c NULL on failure.
705 * \warning Use of \c minimum_size does \b not guarantee binary compatibility.
706 * The fundamental assumption is that if the \c minimum_size
707 * specified by the driver and the size of the \c __GLcontextModes
708 * structure in libGL is the same, then the meaning of each byte in
709 * the structure is the same in both places. \b Be \b careful!
710 * Basically this means that fields have to be added in libGL and
711 * then propagated to drivers. Drivers should \b never arbitrarilly
712 * extend the \c __GLcontextModes data-structure.
714 static __GLcontextModes
*
715 __egl_context_modes_create( unsigned count
, size_t minimum_size
)
717 const size_t size
= (minimum_size
> sizeof( __GLcontextModes
))
718 ? minimum_size
: sizeof( __GLcontextModes
);
719 __GLcontextModes
* base
= NULL
;
720 __GLcontextModes
** next
;
724 for ( i
= 0 ; i
< count
; i
++ ) {
725 *next
= (__GLcontextModes
*) malloc( size
);
726 if ( *next
== NULL
) {
727 __egl_context_modes_destroy( base
);
732 (void) memset( *next
, 0, size
);
733 (*next
)->visualID
= GLX_DONT_CARE
;
734 (*next
)->visualType
= GLX_DONT_CARE
;
735 (*next
)->visualRating
= GLX_NONE
;
736 (*next
)->transparentPixel
= GLX_NONE
;
737 (*next
)->transparentRed
= GLX_DONT_CARE
;
738 (*next
)->transparentGreen
= GLX_DONT_CARE
;
739 (*next
)->transparentBlue
= GLX_DONT_CARE
;
740 (*next
)->transparentAlpha
= GLX_DONT_CARE
;
741 (*next
)->transparentIndex
= GLX_DONT_CARE
;
742 (*next
)->xRenderable
= GLX_DONT_CARE
;
743 (*next
)->fbconfigID
= GLX_DONT_CARE
;
744 (*next
)->swapMethod
= GLX_SWAP_UNDEFINED_OML
;
746 next
= & ((*next
)->next
);
754 __eglWindowExists(__DRInativeDisplay
*dpy
, __DRIid draw
)
761 * Get the unadjusted system time (UST). Currently, the UST is measured in
762 * microseconds since Epoc. The actual resolution of the UST may vary from
763 * system to system, and the units may vary from release to release.
764 * Drivers should not call this function directly. They should instead use
765 * \c glXGetProcAddress to obtain a pointer to the function.
767 * \param ust Location to store the 64-bit UST
768 * \returns Zero on success or a negative errno value on failure.
770 * \sa glXGetProcAddress, PFNGLXGETUSTPROC
772 * \since Internal API version 20030317.
775 __eglGetUST( int64_t * ust
)
783 if ( gettimeofday( & tv
, NULL
) == 0 ) {
784 ust
[0] = (tv
.tv_sec
* 1000000) + tv
.tv_usec
;
792 * Determine the refresh rate of the specified drawable and display.
794 * \param dpy Display whose refresh rate is to be determined.
795 * \param drawable Drawable whose refresh rate is to be determined.
796 * \param numerator Numerator of the refresh rate.
797 * \param demoninator Denominator of the refresh rate.
798 * \return If the refresh rate for the specified display and drawable could
799 * be calculated, True is returned. Otherwise False is returned.
801 * \note This function is implemented entirely client-side. A lot of other
802 * functionality is required to export GLX_OML_sync_control, so on
803 * XFree86 this function can be called for direct-rendering contexts
804 * when GLX_OML_sync_control appears in the client extension string.
807 __eglGetMSCRate(__DRInativeDisplay
* dpy
, __DRIid drawable
,
808 int32_t * numerator
, int32_t * denominator
)
815 * Table of functions exported by the loader to the driver.
817 static const __DRIinterfaceMethods interface_methods
= {
820 __egl_context_modes_create
,
821 __egl_context_modes_destroy
,
826 __eglCreateContextWithConfig
,
830 __eglDestroyDrawable
,
831 __eglGetDrawableInfo
,
838 int __glXGetInternalVersion(void)
843 static const char createNewScreenName
[] = "__driCreateNewScreen_20050727";
846 _eglDRICreateDisplay( driDisplay
*dpy
, __DRIframebuffer
*framebuffer
) {
847 PFNCREATENEWSCREENFUNC createNewScreen
;
848 int api_ver
= __glXGetInternalVersion();
849 __DRIversion ddx_version
;
850 __DRIversion dri_version
;
851 __DRIversion drm_version
;
852 drmVersionPtr version
;
854 version
= drmGetVersion( dpy
->drmFD
);
856 drm_version
.major
= version
->version_major
;
857 drm_version
.minor
= version
->version_minor
;
858 drm_version
.patch
= version
->version_patchlevel
;
859 drmFreeVersion( version
);
861 drm_version
.major
= -1;
862 drm_version
.minor
= -1;
863 drm_version
.patch
= -1;
867 * Get device name (like "tdfx") and the ddx version numbers.
868 * We'll check the version in each DRI driver's "createScreen"
871 ddx_version
.major
= 4;
872 ddx_version
.minor
= 0;
873 ddx_version
.patch
= 0;
876 * Get the DRI X extension version.
878 dri_version
.major
= 4;
879 dri_version
.minor
= 0;
880 dri_version
.patch
= 0;
882 createNewScreen
= ( PFNCREATENEWSCREENFUNC
) dlsym( dpy
->Base
.Driver
->LibHandle
, createNewScreenName
);
883 if ( !createNewScreen
) {
884 fprintf( stderr
, "Couldn't find %s in CallCreateNewScreen\n", createNewScreenName
);
888 dpy
->driScreen
.private = createNewScreen( dpy
, 0, &dpy
->driScreen
, NULL
,
889 &ddx_version
, &dri_version
,
890 &drm_version
, framebuffer
,
891 dpy
->pSAREA
, dpy
->drmFD
,
894 ( __GLcontextModes
** ) & dpy
->driver_modes
);
895 if (!dpy
->driScreen
.private)
898 DRM_UNLOCK( dpy
->drmFD
, dpy
->pSAREA
, dpy
->serverContext
);
905 _eglDRICreateScreen( driDisplay
*dpy
) {
906 char c
, *buffer
, path
[ NAME_MAX
];
907 unsigned int i
, x
, y
, r
;
913 /* Create a screen */
914 if ( !( s
= ( driScreen
* ) calloc( 1, sizeof( *s
) ) ) )
917 snprintf( s
->fb
, NAME_MAX
, "fb%d", dpy
->minor
);
919 _eglInitScreen( scrn
);
920 _eglAddScreen( &dpy
->Base
, scrn
);
922 snprintf( path
, sizeof( path
), "%s/graphics/%s/modes", sysfs
, s
->fb
);
923 file
= fopen( path
, "r" );
924 while ( fgets( path
, sizeof( path
), file
) ) {
925 path
[ strlen( path
) - 1 ] = '\0'; /* strip off \n from sysfs */
926 sscanf( path
, "%c:%ux%u-%u", &c
, &x
, &y
, &r
);
927 _eglAddMode( scrn
, x
, y
, r
* 1000, path
);
931 /* cmap attribute uses 256 lines of 16 bytes */
932 if ( !( buffer
= malloc( 256 * 16 ) ) )
935 /* cmap attribute uses 256 lines of 16 bytes */
936 for ( i
= 0; i
< 256; i
++ )
937 sprintf( &buffer
[ i
* 16 ], "%02x%c%4x%4x%4x\n",
938 i
, ' ', 256 * i
, 256 * i
, 256 * i
);
940 snprintf( path
, sizeof( path
), "%s/graphics/%s/color_map", sysfs
, s
->fb
);
941 if ( !( fd
= open( path
, O_RDWR
) ) )
943 write( fd
, buffer
, 256 * 16 );
952 _eglDRIInitialize(_EGLDriver
*drv
, EGLDisplay dpy
, EGLint
*major
, EGLint
*minor
)
954 _EGLDisplay
*disp
= _eglLookupDisplay(dpy
);
957 /* Switch display structure to one with our private fields */
958 display
= calloc(1, sizeof(*display
));
959 display
->Base
= *disp
;
960 _eglHashInsert(_eglGlobal
.Displays
, disp
->Handle
, display
);
966 sscanf(&disp
->Name
[1], "%d", &display
->minor
);
968 drv
->Initialized
= EGL_TRUE
;
974 _eglDRITerminate(_EGLDriver
*drv
, EGLDisplay dpy
)
976 driDisplay
*display
= Lookup_driDisplay(dpy
);
977 _eglCleanupDisplay(&display
->Base
);
985 _eglDRIInitDriverFallbacks(_EGLDriver
*drv
)
987 _eglInitDriverFallbacks(drv
);
989 drv
->API
.Initialize
= _eglDRIInitialize
;
990 drv
->API
.Terminate
= _eglDRITerminate
;
991 drv
->API
.CreateContext
= _eglDRICreateContext
;
992 drv
->API
.MakeCurrent
= _eglDRIMakeCurrent
;
993 drv
->API
.CreateWindowSurface
= _eglDRICreateWindowSurface
;
994 drv
->API
.CreatePixmapSurface
= _eglDRICreatePixmapSurface
;
995 drv
->API
.CreatePbufferSurface
= _eglDRICreatePbufferSurface
;
996 drv
->API
.DestroySurface
= _eglDRIDestroySurface
;
997 drv
->API
.DestroyContext
= _eglDRIDestroyContext
;
998 drv
->API
.CreateScreenSurfaceMESA
= _eglDRICreateScreenSurfaceMESA
;
999 drv
->API
.ShowSurfaceMESA
= _eglDRIShowSurfaceMESA
;
1000 drv
->API
.SwapBuffers
= _eglDRISwapBuffers
;
1002 /* enable supported extensions */
1003 drv
->MESA_screen_surface
= EGL_TRUE
;
1004 drv
->MESA_copy_context
= EGL_TRUE
;