use _egl_api struct, make some functions static
[mesa.git] / src / egl / drivers / dri / egldri.c
1 /*
2 * Generic EGL driver for DRI
3 */
4 #include <dirent.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <linux/fb.h>
8 #include <assert.h>
9 #include <dlfcn.h>
10 #include <fcntl.h>
11 #include <unistd.h>
12 #include <errno.h>
13 #include <sys/time.h>
14
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"
22 #include "eglmode.h"
23
24 #include "egldri.h"
25
26 const char *sysfs = "/sys/class";
27 #define None 0
28 static const int empty_attribute_list[1] = { None };
29
30 /**
31 * The bootstrap function. Return a new driDriver object and
32 * plug in API functions.
33 */
34 _EGLDriver *
35 _eglMain(_EGLDisplay *dpy)
36 {
37 int length;
38 char path[NAME_MAX];
39 struct dirent *dirent;
40 FILE *file;
41 DIR *dir;
42 _EGLDriver *driver = NULL;;
43
44 snprintf(path, sizeof(path), "%s/drm", sysfs);
45 if (!(dir = opendir(path))) {
46 printf("EGL - %s DRM devices not found.", path);
47 return EGL_FALSE;
48 }
49 while ((dirent = readdir(dir))) {
50
51 if (strncmp(&dirent->d_name[0], "card", 4) != 0)
52 continue;
53 if (strcmp(&dirent->d_name[4], &dpy->Name[1]) != 0)
54 continue;
55
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);
59 fclose(file);
60
61 if ((length = strlen(path)) > 0)
62 path[length - 1] = '\0'; /* remove the trailing newline from sysfs */
63 strncat(path, "_dri", sizeof(path));
64
65 driver = _eglOpenDriver(dpy, path);
66
67 break;
68 }
69 closedir(dir);
70
71 return driver;
72 }
73
74
75 static EGLContext
76 _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
77 {
78 _EGLConfig *conf;
79 driContext *c;
80 driDisplay *disp = Lookup_driDisplay(dpy);
81 driContext *share = Lookup_driContext(share_list);
82 void *sharePriv;
83 __GLcontextModes mode;
84 int i;
85
86 conf = _eglLookupConfig(drv, dpy, config);
87 if (!conf) {
88 _eglError(EGL_BAD_CONFIG, "eglCreateContext");
89 return EGL_NO_CONTEXT;
90 }
91
92 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
93 switch (attrib_list[i]) {
94 /* no attribs defined for now */
95 default:
96 _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext");
97 return EGL_NO_CONTEXT;
98 }
99 }
100
101 c = (driContext *) calloc(1, sizeof(*c));
102 if (!c)
103 return EGL_NO_CONTEXT;
104
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;
110
111 _eglConfigToContextModesRec(conf, &mode);
112
113 if (share)
114 sharePriv = share->driContext.private;
115 else
116 sharePriv = NULL;
117
118 c->driContext.private = disp->driScreen.createNewContext(disp, &mode,
119 GLX_WINDOW_BIT, sharePriv, &c->driContext);
120
121 if (!c->driContext.private) {
122 free(c);
123 return EGL_FALSE;
124 }
125
126 /* generate handle and insert into hash table */
127 _eglSaveContext(&c->Base);
128 assert(c->Base.Handle);
129
130 return c->Base.Handle;
131 }
132
133
134 static EGLBoolean
135 _eglDRIMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context)
136 {
137 driDisplay *disp = Lookup_driDisplay(dpy);
138 driContext *ctx = Lookup_driContext(context);
139 EGLBoolean b;
140
141 b = _eglMakeCurrent(drv, dpy, draw, read, context);
142 if (!b)
143 return EGL_FALSE;
144
145 if (ctx) {
146 ctx->driContext.bindContext(disp, 0, read, draw, &ctx->driContext);
147 } else {
148 // _mesa_make_current( NULL, NULL, NULL );
149 }
150 return EGL_TRUE;
151 }
152
153
154 static EGLSurface
155 _eglDRICreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list)
156 {
157 int i;
158 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
159 switch (attrib_list[i]) {
160 /* no attribs at this time */
161 default:
162 _eglError(EGL_BAD_ATTRIBUTE, "eglCreateWindowSurface");
163 return EGL_NO_SURFACE;
164 }
165 }
166 printf("eglCreateWindowSurface()\n");
167 /* XXX unfinished */
168
169 return EGL_NO_SURFACE;
170 }
171
172
173 static EGLSurface
174 _eglDRICreatePixmapSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list)
175 {
176 _EGLConfig *conf;
177 EGLint i;
178
179 conf = _eglLookupConfig(drv, dpy, config);
180 if (!conf) {
181 _eglError(EGL_BAD_CONFIG, "eglCreatePixmapSurface");
182 return EGL_NO_SURFACE;
183 }
184
185 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
186 switch (attrib_list[i]) {
187 /* no attribs at this time */
188 default:
189 _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePixmapSurface");
190 return EGL_NO_SURFACE;
191 }
192 }
193
194 if (conf->Attrib[EGL_SURFACE_TYPE - FIRST_ATTRIB] == 0) {
195 _eglError(EGL_BAD_MATCH, "eglCreatePixmapSurface");
196 return EGL_NO_SURFACE;
197 }
198
199 printf("eglCreatePixmapSurface()\n");
200 return EGL_NO_SURFACE;
201 }
202
203
204 static EGLSurface
205 _eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
206 {
207 driSurface *surf;
208
209 surf = (driSurface *) calloc(1, sizeof(*surf));
210 if (!surf) {
211 return EGL_NO_SURFACE;
212 }
213
214 if (_eglInitPbufferSurface(&surf->Base, drv, dpy, config, attrib_list) == EGL_NO_SURFACE) {
215 free(surf);
216 return EGL_NO_SURFACE;
217 }
218
219 /* create software-based pbuffer */
220 {
221 // GLcontext *ctx = NULL; /* this _should_ be OK */
222 GLvisual vis;
223 _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
224 assert(conf); /* bad config should be caught earlier */
225 _eglConfigToContextModesRec(conf, &vis);
226
227 #if 0
228 surf->mesa_framebuffer = _mesa_create_framebuffer(&vis);
229 _mesa_add_soft_renderbuffers(surf->mesa_framebuffer,
230 GL_TRUE, /* color bufs */
231 vis.haveDepthBuffer,
232 vis.haveStencilBuffer,
233 vis.haveAccumBuffer,
234 GL_FALSE, /* alpha */
235 GL_FALSE /* aux */ );
236
237 /* set pbuffer/framebuffer size */
238 _mesa_resize_framebuffer(ctx, surf->mesa_framebuffer,
239 surf->Base.Width, surf->Base.Height);
240 #endif
241 }
242
243 return surf->Base.Handle;
244 }
245
246
247 static EGLBoolean
248 _eglDRIDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
249 {
250 driDisplay *disp = Lookup_driDisplay(dpy);
251 driSurface *fs = Lookup_driSurface(surface);
252 _eglRemoveSurface(&fs->Base);
253
254 fs->drawable.destroyDrawable(disp, fs->drawable.private);
255
256 if (fs->Base.IsBound) {
257 fs->Base.DeletePending = EGL_TRUE;
258 }
259 else {
260 free(fs);
261 }
262 return EGL_TRUE;
263 }
264
265
266 static EGLBoolean
267 _eglDRIDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
268 {
269 driDisplay *disp = Lookup_driDisplay(dpy);
270 driContext *fc = Lookup_driContext(context);
271
272 _eglRemoveContext(&fc->Base);
273
274 fc->driContext.destroyContext(disp, 0, fc->driContext.private);
275
276 if (fc->Base.IsBound) {
277 fc->Base.DeletePending = EGL_TRUE;
278 } else {
279 free(fc);
280 }
281 return EGL_TRUE;
282 }
283
284
285 /**
286 * Create a drawing surface which can be directly displayed on a screen.
287 */
288 static EGLSurface
289 _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
290 const EGLint *attrib_list)
291 {
292 _EGLConfig *config = _eglLookupConfig(drv, dpy, cfg);
293 driDisplay *disp = Lookup_driDisplay(dpy);
294 driSurface *surface;
295 EGLSurface surf;
296 GLvisual vis;
297
298 surface = (driSurface *) malloc(sizeof(*surface));
299 if (!surface) {
300 return EGL_NO_SURFACE;
301 }
302
303 /* init base class, error check, etc. */
304 surf = _eglInitScreenSurface(&surface->Base, drv, dpy, cfg, attrib_list);
305 if (surf == EGL_NO_SURFACE) {
306 free(surface);
307 return EGL_NO_SURFACE;
308 }
309
310 /* convert EGLConfig to GLvisual */
311 _eglConfigToContextModesRec(config, &vis);
312
313 /* Create a new drawable */
314 if (!disp->driScreen.createNewDrawable(disp, &vis, surf, &surface->drawable,
315 GLX_WINDOW_BIT, empty_attribute_list)) {
316 free(surface);
317 _eglRemoveSurface(&surface->Base);
318 return EGL_NO_SURFACE;
319 }
320 return surf;
321 }
322
323
324 /**
325 * Show the given surface on the named screen.
326 * If surface is EGL_NO_SURFACE, disable the screen's output.
327 */
328 EGLBoolean
329 _eglDRIShowSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen,
330 EGLSurface surface, EGLModeMESA m)
331 {
332 driDisplay *display = Lookup_driDisplay(dpy);
333 driScreen *scrn = Lookup_driScreen(dpy, screen);
334 driSurface *surf = Lookup_driSurface(surface);
335 FILE *file;
336 char buffer[NAME_MAX];
337 _EGLMode *mode = _eglLookupMode(dpy, m);
338 int width, height, temp;
339
340 _eglQuerySurface(drv, dpy, surface, EGL_WIDTH, &width);
341 _eglQuerySurface(drv, dpy, surface, EGL_HEIGHT, &height);
342
343 if (!_eglShowSurfaceMESA(drv, dpy, screen, surface, m))
344 return EGL_FALSE;
345
346 snprintf(buffer, sizeof(buffer), "%s/graphics/%s/blank", sysfs, scrn->fb);
347
348 file = fopen(buffer, "r+");
349 if (!file) {
350 err:
351 printf("kernel patch?? chown all fb sysfs attrib to allow write - %s\n", buffer);
352 _eglError(EGL_BAD_SURFACE, "eglShowSurfaceMESA");
353 return EGL_FALSE;
354 }
355 snprintf(buffer, sizeof(buffer), "%d", (m == EGL_NO_MODE_MESA ? VESA_POWERDOWN : VESA_VSYNC_SUSPEND));
356 fputs(buffer, file);
357 fclose(file);
358
359 if (m == EGL_NO_MODE_MESA)
360 return EGL_TRUE;
361
362 snprintf(buffer, sizeof(buffer), "%s/graphics/%s/mode", sysfs, scrn->fb);
363
364 file = fopen(buffer, "r+");
365 if (!file)
366 goto err;
367 fputs(mode->Name, file);
368 fclose(file);
369
370 snprintf(buffer, sizeof(buffer), "%s/graphics/%s/bits_per_pixel", sysfs, scrn->fb);
371
372 file = fopen(buffer, "r+");
373 if (!file)
374 goto err;
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);
378 fputs(buffer, file);
379 fclose(file);
380
381 snprintf(buffer, sizeof(buffer), "%s/graphics/%s/blank", sysfs, scrn->fb);
382
383 file = fopen(buffer, "r+");
384 if (!file)
385 goto err;
386
387 snprintf(buffer, sizeof(buffer), "%d", VESA_NO_BLANKING);
388 fputs(buffer, file);
389 fclose(file);
390
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);
394 fputs(buffer, file);
395 rewind(file);
396 fgets(buffer, sizeof(buffer), file);
397 sscanf(buffer, "%d,%d", &display->virtualWidth, &display->virtualHeight);
398 fclose(file);
399
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;
404 case 3:
405 case 4: temp = (display->virtualWidth + 15) & ~15; break;
406 }
407 display->virtualWidth = temp;
408
409 if ((width != display->virtualWidth) || (height != display->virtualHeight))
410 goto err;
411
412 return EGL_TRUE;
413 }
414
415
416 /* If the backbuffer is on a videocard, this is extraordinarily slow!
417 */
418 static EGLBoolean
419 _eglDRISwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
420 {
421 driSurface *drawable = Lookup_driSurface(draw);
422
423 if (!_eglSwapBuffers(drv, dpy, draw))
424 return EGL_FALSE;
425
426 drawable->drawable.swapBuffers(NULL, drawable->drawable.private);
427
428 return EGL_TRUE;
429 }
430
431
432 EGLBoolean
433 _eglDRIGetDisplayInfo( driDisplay *dpy) {
434 char path[ NAME_MAX ];
435 FILE *file;
436 int rc, mtrr;
437 unsigned int i;
438 drmMapType type;
439 drmMapFlags flags;
440 drm_handle_t handle, offset;
441 drmSize size;
442 drmSetVersion sv;
443 drm_magic_t magic;
444
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 );
449 fclose( file );
450
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" );
454 return EGL_FALSE;
455 }
456
457 /* Set the interface version, asking for 1.2 */
458 sv.drm_di_major = 1;
459 sv.drm_di_minor = 2;
460 sv.drm_dd_major = -1;
461 if ((rc = drmSetInterfaceVersion(dpy->drmFD, &sv)))
462 return EGL_FALSE;
463
464 /* self authorize */
465 if (drmGetMagic(dpy->drmFD, &magic))
466 return EGL_FALSE;
467 if (drmAuthMagic(dpy->drmFD, magic))
468 return EGL_FALSE;
469
470 for ( i = 0;; i++ ) {
471 if ( ( rc = drmGetMap( dpy->drmFD, i, &offset, &size, &type, &flags, &handle, &mtrr ) ) != 0 )
472 break;
473 if ( type == DRM_FRAME_BUFFER ) {
474 if ( ( rc = drmMap( dpy->drmFD, offset, size, ( drmAddressPtr ) & dpy->pFB ) ) < 0 )
475 return EGL_FALSE;
476 dpy->fbSize = size;
477 break;
478 }
479 }
480 if ( !dpy->pFB )
481 return EGL_FALSE;
482
483 dpy->SAREASize = SAREA_MAX;
484
485 for ( i = 0;; i++ ) {
486 if ( drmGetMap( dpy->drmFD, i, &offset, &size, &type, &flags, &handle, &mtrr ) != 0 )
487 break;
488 if ( type == DRM_SHM ) {
489 if ( drmMap( dpy->drmFD, offset, size, ( drmAddressPtr ) ( &dpy->pSAREA ) ) < 0 ) {
490 fprintf( stderr, "[drm] drmMap failed\n" );
491 return 0;
492 }
493 break;
494 }
495 }
496 if ( !dpy->pSAREA )
497 return 0;
498
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 );
502 return EGL_TRUE;
503 }
504
505
506 /* Return the DRI per screen structure */
507 static __DRIscreen *__eglFindDRIScreen(__DRInativeDisplay *ndpy, int scrn)
508 {
509 driDisplay *disp = (driDisplay *)ndpy;
510 return &disp->driScreen;
511 }
512
513 static GLboolean __eglCreateContextWithConfig(__DRInativeDisplay* ndpy, int screen, int configID, void* context, drm_context_t * hHWContext)
514 {
515 __DRIscreen *pDRIScreen;
516 __DRIscreenPrivate *psp;
517
518 pDRIScreen = __eglFindDRIScreen(ndpy, screen);
519 if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
520 return GL_FALSE;
521 }
522 psp = (__DRIscreenPrivate *) pDRIScreen->private;
523 if (psp->fd) {
524 if (drmCreateContext(psp->fd, hHWContext)) {
525 fprintf(stderr, ">>> drmCreateContext failed\n");
526 return GL_FALSE;
527 }
528 *(void**)context = (void*) *hHWContext;
529 }
530 #if 0
531 __DRIscreen *pDRIScreen;
532 __DRIscreenPrivate *psp;
533
534 pDRIScreen = __glXFindDRIScreen(dpy, screen);
535 if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
536 return GL_FALSE;
537 }
538
539 psp = (__DRIscreenPrivate *) pDRIScreen->private;
540
541 if (psp->fd) {
542 if (drmCreateContext(psp->fd, hHWContext)) {
543 fprintf(stderr, ">>> drmCreateContext failed\n");
544 return GL_FALSE;
545 }
546 *(void**)contextID = (void*) *hHWContext;
547 }
548 #endif
549 return GL_TRUE;
550 }
551
552 static GLboolean __eglDestroyContext( __DRInativeDisplay * ndpy, int screen, __DRIid context )
553 {
554 __DRIscreen *pDRIScreen;
555 __DRIscreenPrivate *psp;
556
557 pDRIScreen = __eglFindDRIScreen(ndpy, screen);
558 if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
559 return GL_FALSE;
560 }
561 psp = (__DRIscreenPrivate *) pDRIScreen->private;
562 if (psp->fd)
563 drmDestroyContext(psp->fd, context);
564
565 return GL_TRUE;
566 }
567
568 static GLboolean __eglCreateDrawable( __DRInativeDisplay * ndpy, int screen, __DRIid drawable, drm_drawable_t * hHWDrawable )
569 {
570 __DRIscreen *pDRIScreen;
571 __DRIscreenPrivate *psp;
572
573 pDRIScreen = __eglFindDRIScreen(ndpy, screen);
574 if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
575 return GL_FALSE;
576 }
577 psp = (__DRIscreenPrivate *) pDRIScreen->private;
578 if (psp->fd) {
579 if (drmCreateDrawable(psp->fd, hHWDrawable)) {
580 fprintf(stderr, ">>> drmCreateDrawable failed\n");
581 return GL_FALSE;
582 }
583 }
584 return GL_TRUE;
585 }
586
587 static GLboolean __eglDestroyDrawable( __DRInativeDisplay * ndpy, int screen, __DRIid drawable )
588 {
589 __DRIscreen *pDRIScreen;
590 __DRIscreenPrivate *psp;
591
592 pDRIScreen = __eglFindDRIScreen(ndpy, screen);
593 if ( (pDRIScreen == NULL) || (pDRIScreen->private == NULL) ) {
594 return GL_FALSE;
595 }
596 psp = (__DRIscreenPrivate *) pDRIScreen->private;
597 if (psp->fd)
598 drmDestroyDrawable(psp->fd, drawable);
599
600 return GL_TRUE;
601 }
602
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 )
609 {
610 driSurface *surf = Lookup_driSurface(drawable);
611
612 *X = 0;
613 *Y = 0;
614 *W = surf->Base.Width;
615 *H = surf->Base.Height;
616
617 *numClipRects = 1;
618 *pClipRects = malloc(sizeof(**pClipRects));
619 **pClipRects = (drm_clip_rect_t){0, 0, surf->Base.Width, surf->Base.Height};
620
621 #if 0
622 GLXDrawable drawable = (GLXDrawable) draw;
623 drm_clip_rect_t * cliprect;
624 Display* display = (Display*)dpy;
625 __DRIcontextPrivate *pcp = (__DRIcontextPrivate *)CurrentContext->driContext.private;
626 if (drawable == 0) {
627 return GL_FALSE;
628 }
629
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;
635
636 /* the drawable index is by client id */
637 *index = display->clientID;
638
639 *stamp = pcp->driScreenPriv->pSAREA->drawableTable[display->clientID].stamp;
640 *x = drawable->x;
641 *y = drawable->y;
642 *width = drawable->w;
643 *height = drawable->h;
644 *numClipRects = 1;
645 *pClipRects = cliprect;
646
647 *backX = drawable->x;
648 *backY = drawable->y;
649 *numBackClipRects = 0;
650 *pBackClipRects = 0;
651 #endif
652 return GL_TRUE;
653 }
654
655 /**
656 * Implement \c __DRIinterfaceMethods::getProcAddress.
657 */
658 static __DRIfuncPtr get_proc_address( const char * proc_name )
659 {
660 #if 0
661 if (strcmp( proc_name, "glxEnableExtension" ) == 0) {
662 return (__DRIfuncPtr) __glXScrEnableExtension;
663 }
664 #endif
665 return NULL;
666 }
667
668
669 /**
670 * Destroy a linked list of \c __GLcontextModes structures created by
671 * \c _gl_context_modes_create.
672 *
673 * \param modes Linked list of structures to be destroyed. All structres
674 * in the list will be freed.
675 */
676 static void
677 __egl_context_modes_destroy( __GLcontextModes * modes )
678 {
679 while ( modes != NULL ) {
680 __GLcontextModes * const next = modes->next;
681
682 free( modes );
683 modes = next;
684 }
685 }
686
687
688 /**
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.
696 *
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
701 * DRI-based driver.
702 * \returns A pointer to the first element in a linked list of \c count
703 * stuctures on success, or \c NULL on failure.
704 *
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.
713 */
714 static __GLcontextModes *
715 __egl_context_modes_create( unsigned count, size_t minimum_size )
716 {
717 const size_t size = (minimum_size > sizeof( __GLcontextModes ))
718 ? minimum_size : sizeof( __GLcontextModes );
719 __GLcontextModes * base = NULL;
720 __GLcontextModes ** next;
721 unsigned i;
722
723 next = & base;
724 for ( i = 0 ; i < count ; i++ ) {
725 *next = (__GLcontextModes *) malloc( size );
726 if ( *next == NULL ) {
727 __egl_context_modes_destroy( base );
728 base = NULL;
729 break;
730 }
731
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;
745
746 next = & ((*next)->next);
747 }
748
749 return base;
750 }
751
752
753 static GLboolean
754 __eglWindowExists(__DRInativeDisplay *dpy, __DRIid draw)
755 {
756 return EGL_TRUE;
757 }
758
759
760 /**
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.
766 *
767 * \param ust Location to store the 64-bit UST
768 * \returns Zero on success or a negative errno value on failure.
769 *
770 * \sa glXGetProcAddress, PFNGLXGETUSTPROC
771 *
772 * \since Internal API version 20030317.
773 */
774 static int
775 __eglGetUST( int64_t * ust )
776 {
777 struct timeval tv;
778
779 if ( ust == NULL ) {
780 return -EFAULT;
781 }
782
783 if ( gettimeofday( & tv, NULL ) == 0 ) {
784 ust[0] = (tv.tv_sec * 1000000) + tv.tv_usec;
785 return 0;
786 } else {
787 return -errno;
788 }
789 }
790
791 /**
792 * Determine the refresh rate of the specified drawable and display.
793 *
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.
800 *
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.
805 */
806 static GLboolean
807 __eglGetMSCRate(__DRInativeDisplay * dpy, __DRIid drawable,
808 int32_t * numerator, int32_t * denominator)
809 {
810 return EGL_TRUE;
811 }
812
813
814 /**
815 * Table of functions exported by the loader to the driver.
816 */
817 static const __DRIinterfaceMethods interface_methods = {
818 get_proc_address,
819
820 __egl_context_modes_create,
821 __egl_context_modes_destroy,
822
823 __eglFindDRIScreen,
824 __eglWindowExists,
825
826 __eglCreateContextWithConfig,
827 __eglDestroyContext,
828
829 __eglCreateDrawable,
830 __eglDestroyDrawable,
831 __eglGetDrawableInfo,
832
833 __eglGetUST,
834 __eglGetMSCRate,
835 };
836
837
838 int __glXGetInternalVersion(void)
839 {
840 return 20050725;
841 }
842
843 static const char createNewScreenName[] = "__driCreateNewScreen_20050727";
844
845 EGLBoolean
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;
853
854 version = drmGetVersion( dpy->drmFD );
855 if ( version ) {
856 drm_version.major = version->version_major;
857 drm_version.minor = version->version_minor;
858 drm_version.patch = version->version_patchlevel;
859 drmFreeVersion( version );
860 } else {
861 drm_version.major = -1;
862 drm_version.minor = -1;
863 drm_version.patch = -1;
864 }
865
866 /*
867 * Get device name (like "tdfx") and the ddx version numbers.
868 * We'll check the version in each DRI driver's "createScreen"
869 * function.
870 */
871 ddx_version.major = 4;
872 ddx_version.minor = 0;
873 ddx_version.patch = 0;
874
875 /*
876 * Get the DRI X extension version.
877 */
878 dri_version.major = 4;
879 dri_version.minor = 0;
880 dri_version.patch = 0;
881
882 createNewScreen = ( PFNCREATENEWSCREENFUNC ) dlsym( dpy->Base.Driver->LibHandle, createNewScreenName );
883 if ( !createNewScreen ) {
884 fprintf( stderr, "Couldn't find %s in CallCreateNewScreen\n", createNewScreenName );
885 return EGL_FALSE;
886 }
887
888 dpy->driScreen.private = createNewScreen( dpy, 0, &dpy->driScreen, NULL,
889 &ddx_version, &dri_version,
890 &drm_version, framebuffer,
891 dpy->pSAREA, dpy->drmFD,
892 api_ver,
893 & interface_methods,
894 ( __GLcontextModes ** ) & dpy->driver_modes );
895 if (!dpy->driScreen.private)
896 return EGL_FALSE;
897
898 DRM_UNLOCK( dpy->drmFD, dpy->pSAREA, dpy->serverContext );
899
900 return EGL_TRUE;
901 }
902
903
904 EGLBoolean
905 _eglDRICreateScreen( driDisplay *dpy) {
906 char c, *buffer, path[ NAME_MAX ];
907 unsigned int i, x, y, r;
908 int fd;
909 FILE *file;
910 driScreen *s;
911 _EGLScreen *scrn;
912
913 /* Create a screen */
914 if ( !( s = ( driScreen * ) calloc( 1, sizeof( *s ) ) ) )
915 return EGL_FALSE;
916
917 snprintf( s->fb, NAME_MAX, "fb%d", dpy->minor );
918 scrn = &s->Base;
919 _eglInitScreen( scrn );
920 _eglAddScreen( &dpy->Base, scrn );
921
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 );
928 }
929 fclose( file );
930
931 /* cmap attribute uses 256 lines of 16 bytes */
932 if ( !( buffer = malloc( 256 * 16 ) ) )
933 return EGL_FALSE;
934
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 );
939
940 snprintf( path, sizeof( path ), "%s/graphics/%s/color_map", sysfs, s->fb );
941 if ( !( fd = open( path, O_RDWR ) ) )
942 return EGL_FALSE;
943 write( fd, buffer, 256 * 16 );
944 close( fd );
945
946 free( buffer );
947
948 return EGL_TRUE;
949 }
950
951 EGLBoolean
952 _eglDRIInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor)
953 {
954 _EGLDisplay *disp = _eglLookupDisplay(dpy);
955 driDisplay *display;
956
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);
961 free(disp);
962
963 *major = 1;
964 *minor = 0;
965
966 sscanf(&disp->Name[1], "%d", &display->minor);
967
968 drv->Initialized = EGL_TRUE;
969 return EGL_TRUE;
970 }
971
972
973 static EGLBoolean
974 _eglDRITerminate(_EGLDriver *drv, EGLDisplay dpy)
975 {
976 driDisplay *display = Lookup_driDisplay(dpy);
977 _eglCleanupDisplay(&display->Base);
978 free(display);
979 free(drv);
980 return EGL_TRUE;
981 }
982
983
984 void
985 _eglDRIInitDriverFallbacks(_EGLDriver *drv)
986 {
987 _eglInitDriverFallbacks(drv);
988
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;
1001
1002 /* enable supported extensions */
1003 drv->MESA_screen_surface = EGL_TRUE;
1004 drv->MESA_copy_context = EGL_TRUE;
1005
1006 }