if we can't find a mode, return first. At least we should
[mesa.git] / src / gallium / winsys / drm / intel / egl / intel_egl.c
1
2 #include <assert.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <stdint.h>
7
8 #include "eglconfig.h"
9 #include "eglcontext.h"
10 #include "egldisplay.h"
11 #include "egldriver.h"
12 #include "eglglobals.h"
13 #include "eglmode.h"
14 #include "eglscreen.h"
15 #include "eglsurface.h"
16 #include "egllog.h"
17
18 #include "intel_egl.h"
19
20 #include "xf86drm.h"
21 #include "xf86drmMode.h"
22
23 #include "intel_context.h"
24
25 #include "state_tracker/st_public.h"
26
27 #define MAX_SCREENS 16
28
29 static void
30 drm_get_device_id(struct egl_drm_device *device)
31 {
32 char path[512];
33 FILE *file;
34
35 /* TODO get the real minor */
36 int minor = 0;
37
38 snprintf(path, sizeof(path), "/sys/class/drm/card%d/device/device", minor);
39 file = fopen(path, "r");
40 if (!file) {
41 _eglLog(_EGL_WARNING, "Could not retrive device ID\n");
42 return;
43 }
44
45 fgets(path, sizeof( path ), file);
46 sscanf(path, "%x", &device->deviceID);
47 fclose(file);
48 }
49
50 static struct egl_drm_device*
51 egl_drm_create_device(int drmFD)
52 {
53 struct egl_drm_device *device = malloc(sizeof(*device));
54 memset(device, 0, sizeof(*device));
55 device->drmFD = drmFD;
56
57 device->version = drmGetVersion(device->drmFD);
58
59 drm_get_device_id(device);
60
61 if (!intel_create_device(device)) {
62 free(device);
63 return NULL;
64 }
65
66 return device;
67 }
68
69 static void
70 _egl_context_modes_destroy(__GLcontextModes *modes)
71 {
72 _eglLog(_EGL_DEBUG, "%s", __FUNCTION__);
73
74 while (modes) {
75 __GLcontextModes * const next = modes->next;
76 free(modes);
77 modes = next;
78 }
79 }
80 /**
81 * Create a linked list of 'count' GLcontextModes.
82 * These are used during the client/server visual negotiation phase,
83 * then discarded.
84 */
85 static __GLcontextModes *
86 _egl_context_modes_create(unsigned count, size_t minimum_size)
87 {
88 /* This code copied from libGLX, and modified */
89 const size_t size = (minimum_size > sizeof(__GLcontextModes))
90 ? minimum_size : sizeof(__GLcontextModes);
91 __GLcontextModes * head = NULL;
92 __GLcontextModes ** next;
93 unsigned i;
94
95 _eglLog(_EGL_DEBUG, "%s %d %d", __FUNCTION__, count, minimum_size);
96
97 next = & head;
98 for (i = 0 ; i < count ; i++) {
99 *next = (__GLcontextModes *) calloc(1, size);
100 if (*next == NULL) {
101 _egl_context_modes_destroy(head);
102 head = NULL;
103 break;
104 }
105
106 (*next)->doubleBufferMode = 1;
107 (*next)->visualID = GLX_DONT_CARE;
108 (*next)->visualType = GLX_DONT_CARE;
109 (*next)->visualRating = GLX_NONE;
110 (*next)->transparentPixel = GLX_NONE;
111 (*next)->transparentRed = GLX_DONT_CARE;
112 (*next)->transparentGreen = GLX_DONT_CARE;
113 (*next)->transparentBlue = GLX_DONT_CARE;
114 (*next)->transparentAlpha = GLX_DONT_CARE;
115 (*next)->transparentIndex = GLX_DONT_CARE;
116 (*next)->xRenderable = GLX_DONT_CARE;
117 (*next)->fbconfigID = GLX_DONT_CARE;
118 (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML;
119 (*next)->bindToTextureRgb = GLX_DONT_CARE;
120 (*next)->bindToTextureRgba = GLX_DONT_CARE;
121 (*next)->bindToMipmapTexture = GLX_DONT_CARE;
122 (*next)->bindToTextureTargets = 0;
123 (*next)->yInverted = GLX_DONT_CARE;
124
125 next = & ((*next)->next);
126 }
127
128 return head;
129 }
130
131 struct drm_screen;
132
133 struct drm_driver
134 {
135 _EGLDriver base; /* base class/object */
136
137 drmModeResPtr res;
138
139 struct drm_screen *screens[MAX_SCREENS];
140 size_t count_screens;
141
142 struct egl_drm_device *device;
143 };
144
145 struct drm_surface
146 {
147 _EGLSurface base; /* base class/object */
148
149 struct egl_drm_drawable *drawable;
150 };
151
152 struct drm_context
153 {
154 _EGLContext base; /* base class/object */
155
156 struct egl_drm_context *context;
157 };
158
159 struct drm_screen
160 {
161 _EGLScreen base;
162
163 /* currently only support one connector */
164 drmModeConnectorPtr connector;
165
166 /* Has this screen been shown */
167 int shown;
168
169 /* Surface that is currently attached to this screen */
170 struct drm_surface *surf;
171
172 /* backing buffer */
173 drmBO buffer;
174
175 /* framebuffer */
176 drmModeFBPtr fb;
177 uint32_t fbID;
178
179 /* crtc and mode used */
180 drmModeCrtcPtr crtc;
181 uint32_t crtcID;
182
183 struct drm_mode_modeinfo *mode;
184
185 /* geometry of the screen */
186 struct egl_drm_frontbuffer front;
187 };
188
189 static void
190 drm_update_res(struct drm_driver *drm_drv)
191 {
192 drmModeFreeResources(drm_drv->res);
193 drm_drv->res = drmModeGetResources(drm_drv->device->drmFD);
194 }
195
196 static void
197 drm_add_modes_from_connector(_EGLScreen *screen, drmModeConnectorPtr connector)
198 {
199 struct drm_mode_modeinfo *m;
200 int i;
201
202 for (i = 0; i < connector->count_modes; i++) {
203 m = &connector->modes[i];
204 _eglAddNewMode(screen, m->hdisplay, m->vdisplay, m->vrefresh, m->name);
205 }
206 }
207
208
209 static EGLBoolean
210 drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor)
211 {
212 _EGLDisplay *disp = _eglLookupDisplay(dpy);
213 struct drm_driver *drm_drv = (struct drm_driver *)drv;
214 struct drm_screen *screen = NULL;
215 drmModeConnectorPtr connector = NULL;
216 drmModeResPtr res = NULL;
217 unsigned count_connectors = 0;
218 int num_screens = 0;
219
220 EGLint i;
221 int fd;
222
223 fd = drmOpen("i915", NULL);
224 if (fd < 0) {
225 return EGL_FALSE;
226 }
227
228 drm_drv->device = egl_drm_create_device(fd);
229 if (!drm_drv->device) {
230 drmClose(fd);
231 return EGL_FALSE;
232 }
233
234 drm_update_res(drm_drv);
235 res = drm_drv->res;
236 if (res)
237 count_connectors = res->count_connectors;
238
239 for(i = 0; i < count_connectors && i < MAX_SCREENS; i++) {
240 connector = drmModeGetConnector(fd, res->connectors[i]);
241
242 if (!connector)
243 continue;
244
245 if (connector->connection != DRM_MODE_CONNECTED) {
246 drmModeFreeConnector(connector);
247 continue;
248 }
249
250 screen = malloc(sizeof(struct drm_screen));
251 memset(screen, 0, sizeof(*screen));
252 screen->connector = connector;
253 _eglInitScreen(&screen->base);
254 _eglAddScreen(disp, &screen->base);
255 drm_add_modes_from_connector(&screen->base, connector);
256 drm_drv->screens[num_screens++] = screen;
257 }
258 drm_drv->count_screens = num_screens;
259
260 /* for now we only have one config */
261 _EGLConfig *config = calloc(1, sizeof(*config));
262 memset(config, 1, sizeof(*config));
263 _eglInitConfig(config, 1);
264 _eglSetConfigAttrib(config, EGL_RED_SIZE, 8);
265 _eglSetConfigAttrib(config, EGL_GREEN_SIZE, 8);
266 _eglSetConfigAttrib(config, EGL_BLUE_SIZE, 8);
267 _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, 8);
268 _eglSetConfigAttrib(config, EGL_BUFFER_SIZE, 32);
269 _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, 24);
270 _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, 8);
271 _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
272 _eglAddConfig(disp, config);
273
274 drv->Initialized = EGL_TRUE;
275
276 *major = 1;
277 *minor = 4;
278
279 return EGL_TRUE;
280 }
281
282 static void
283 drm_takedown_shown_screen(_EGLDriver *drv, struct drm_screen *screen)
284 {
285 struct drm_driver *drm_drv = (struct drm_driver *)drv;
286 unsigned int i;
287
288 intel_bind_frontbuffer(screen->surf->drawable, NULL);
289 screen->surf = NULL;
290
291 for (i = 0; i < drm_drv->res->count_crtcs; i++) {
292 drmModeSetCrtc(
293 drm_drv->device->drmFD,
294 drm_drv->res->crtcs[i],
295 0, // FD
296 0, 0,
297 NULL, 0, // List of output ids
298 NULL);
299 }
300
301 drmModeRmFB(drm_drv->device->drmFD, screen->fbID);
302 drmModeFreeFB(screen->fb);
303 screen->fb = NULL;
304
305 drmBOUnreference(drm_drv->device->drmFD, &screen->buffer);
306
307 screen->shown = 0;
308 }
309
310 static EGLBoolean
311 drm_terminate(_EGLDriver *drv, EGLDisplay dpy)
312 {
313 struct drm_driver *drm_drv = (struct drm_driver *)drv;
314 struct drm_screen *screen;
315 int i = 0;
316
317 intel_destroy_device(drm_drv->device);
318 drmFreeVersion(drm_drv->device->version);
319
320 for (i = 0; i < drm_drv->count_screens; i++) {
321 screen = drm_drv->screens[i];
322
323 if (screen->shown)
324 drm_takedown_shown_screen(drv, screen);
325
326 drmModeFreeConnector(screen->connector);
327 _eglDestroyScreen(&screen->base);
328 drm_drv->screens[i] = NULL;
329 }
330
331 drmClose(drm_drv->device->drmFD);
332
333 free(drm_drv->device);
334
335 _eglCleanupDisplay(_eglLookupDisplay(dpy));
336 free(drm_drv);
337
338 return EGL_TRUE;
339 }
340
341
342 static struct drm_context *
343 lookup_drm_context(EGLContext context)
344 {
345 _EGLContext *c = _eglLookupContext(context);
346 return (struct drm_context *) c;
347 }
348
349
350 static struct drm_surface *
351 lookup_drm_surface(EGLSurface surface)
352 {
353 _EGLSurface *s = _eglLookupSurface(surface);
354 return (struct drm_surface *) s;
355 }
356
357 static struct drm_screen *
358 lookup_drm_screen(EGLDisplay dpy, EGLScreenMESA screen)
359 {
360 _EGLScreen *s = _eglLookupScreen(dpy, screen);
361 return (struct drm_screen *) s;
362 }
363
364 static __GLcontextModes*
365 visual_from_config(_EGLConfig *conf)
366 {
367 __GLcontextModes *visual;
368 (void)conf;
369
370 visual = _egl_context_modes_create(1, sizeof(*visual));
371 visual->redBits = 8;
372 visual->greenBits = 8;
373 visual->blueBits = 8;
374 visual->alphaBits = 8;
375
376 visual->rgbBits = 32;
377 visual->doubleBufferMode = 1;
378
379 visual->depthBits = 24;
380 visual->haveDepthBuffer = visual->depthBits > 0;
381 visual->stencilBits = 8;
382 visual->haveStencilBuffer = visual->stencilBits > 0;
383
384 return visual;
385 }
386
387
388
389 static EGLContext
390 drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
391 {
392 struct drm_driver *drm_drv = (struct drm_driver *)drv;
393 struct drm_context *c;
394 struct drm_egl_context *share = NULL;
395 _EGLConfig *conf;
396 int i;
397 int ret;
398 __GLcontextModes *visual;
399 struct egl_drm_context *context;
400
401 conf = _eglLookupConfig(drv, dpy, config);
402 if (!conf) {
403 _eglError(EGL_BAD_CONFIG, "eglCreateContext");
404 return EGL_NO_CONTEXT;
405 }
406
407 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
408 switch (attrib_list[i]) {
409 /* no attribs defined for now */
410 default:
411 _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext");
412 return EGL_NO_CONTEXT;
413 }
414 }
415
416 c = (struct drm_context *) calloc(1, sizeof(struct drm_context));
417 if (!c)
418 return EGL_NO_CONTEXT;
419
420 _eglInitContext(drv, dpy, &c->base, config, attrib_list);
421
422 context = malloc(sizeof(*context));
423 memset(context, 0, sizeof(*context));
424
425 if (!context)
426 goto err_c;
427
428 context->device = drm_drv->device;
429 visual = visual_from_config(conf);
430
431 ret = intel_create_context(context, visual, share);
432 free(visual);
433
434 if (!ret)
435 goto err_gl;
436
437 c->context = context;
438
439 /* generate handle and insert into hash table */
440 _eglSaveContext(&c->base);
441 assert(_eglGetContextHandle(&c->base));
442
443 return _eglGetContextHandle(&c->base);
444 err_gl:
445 free(context);
446 err_c:
447 free(c);
448 return EGL_NO_CONTEXT;
449 }
450
451 static EGLBoolean
452 drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
453 {
454 struct drm_context *fc = lookup_drm_context(context);
455 _eglRemoveContext(&fc->base);
456 if (fc->base.IsBound) {
457 fc->base.DeletePending = EGL_TRUE;
458 } else {
459 intel_destroy_context(fc->context);
460 free(fc->context);
461 free(fc);
462 }
463 return EGL_TRUE;
464 }
465
466
467 static EGLSurface
468 drm_create_window_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list)
469 {
470 return EGL_NO_SURFACE;
471 }
472
473
474 static EGLSurface
475 drm_create_pixmap_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list)
476 {
477 return EGL_NO_SURFACE;
478 }
479
480
481 static EGLSurface
482 drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
483 const EGLint *attrib_list)
484 {
485 struct drm_driver *drm_drv = (struct drm_driver *)drv;
486 int i;
487 int ret;
488 int width = -1;
489 int height = -1;
490 struct drm_surface *surf = NULL;
491 struct egl_drm_drawable *drawable = NULL;
492 __GLcontextModes *visual;
493 _EGLConfig *conf;
494
495 conf = _eglLookupConfig(drv, dpy, config);
496 if (!conf) {
497 _eglError(EGL_BAD_CONFIG, "eglCreatePbufferSurface");
498 return EGL_NO_CONTEXT;
499 }
500
501 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
502 switch (attrib_list[i]) {
503 case EGL_WIDTH:
504 width = attrib_list[++i];
505 break;
506 case EGL_HEIGHT:
507 height = attrib_list[++i];
508 break;
509 default:
510 _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface");
511 return EGL_NO_SURFACE;
512 }
513 }
514
515 if (width < 1 || height < 1) {
516 _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface");
517 return EGL_NO_SURFACE;
518 }
519
520 surf = (struct drm_surface *) calloc(1, sizeof(struct drm_surface));
521 if (!surf)
522 goto err;
523
524 if (!_eglInitSurface(drv, dpy, &surf->base, EGL_PBUFFER_BIT, config, attrib_list))
525 goto err_surf;
526
527 drawable = malloc(sizeof(*drawable));
528 memset(drawable, 0, sizeof(*drawable));
529
530 drawable->w = width;
531 drawable->h = height;
532
533 visual = visual_from_config(conf);
534
535 drawable->device = drm_drv->device;
536 ret = intel_create_drawable(drawable, visual);
537 free(visual);
538
539 if (!ret)
540 goto err_draw;
541
542 surf->drawable = drawable;
543
544 _eglSaveSurface(&surf->base);
545 return surf->base.Handle;
546
547 err_draw:
548 free(drawable);
549 err_surf:
550 free(surf);
551 err:
552 return EGL_NO_SURFACE;
553 }
554
555 static EGLSurface
556 drm_create_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
557 const EGLint *attrib_list)
558 {
559 EGLSurface surf = drm_create_pbuffer_surface(drv, dpy, cfg, attrib_list);
560
561 return surf;
562 }
563
564 static struct drm_mode_modeinfo *
565 drm_find_mode(drmModeConnectorPtr connector, _EGLMode *mode)
566 {
567 int i;
568 struct drm_mode_modeinfo *m;
569
570 for (i = 0; i < connector->count_modes; i++) {
571 m = &connector->modes[i];
572 if (m->hdisplay == mode->Width && m->vdisplay == mode->Height && m->vrefresh == mode->RefreshRate)
573 break;
574 m = &connector->modes[0]; /* if we can't find one, return first */
575 }
576
577 return m;
578 }
579 static void
580 draw(size_t x, size_t y, size_t w, size_t h, size_t pitch, size_t v, unsigned int *ptr)
581 {
582 int i, j;
583
584 for (i = x; i < x + w; i++)
585 for(j = y; j < y + h; j++)
586 ptr[(i * pitch / 4) + j] = v;
587
588 }
589
590 static void
591 prettyColors(int fd, unsigned int handle, size_t pitch)
592 {
593 drmBO bo;
594 unsigned int *ptr;
595 void *p;
596 int i;
597
598 drmBOReference(fd, handle, &bo);
599 drmBOMap(fd, &bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, &p);
600 ptr = (unsigned int*)p;
601
602 for (i = 0; i < (bo.size / 4); i++)
603 ptr[i] = 0xFFFFFFFF;
604
605 for (i = 0; i < 4; i++)
606 draw(i * 40, i * 40, 40, 40, pitch, 0, ptr);
607
608
609 draw(200, 100, 40, 40, pitch, 0xff00ff, ptr);
610 draw(100, 200, 40, 40, pitch, 0xff00ff, ptr);
611
612 drmBOUnmap(fd, &bo);
613 }
614
615 static EGLBoolean
616 drm_show_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy,
617 EGLScreenMESA screen,
618 EGLSurface surface, EGLModeMESA m)
619 {
620 struct drm_driver *drm_drv = (struct drm_driver *)drv;
621 struct drm_surface *surf = lookup_drm_surface(surface);
622 struct drm_screen *scrn = lookup_drm_screen(dpy, screen);
623 _EGLMode *mode = _eglLookupMode(dpy, m);
624 size_t pitch = mode->Width * 4;
625 size_t size = mode->Height * pitch;
626 int ret;
627 unsigned int i,j,k;
628
629 if (scrn->shown)
630 drm_takedown_shown_screen(drv, scrn);
631
632 ret = drmBOCreate(drm_drv->device->drmFD, size, 0, 0,
633 DRM_BO_FLAG_READ |
634 DRM_BO_FLAG_WRITE |
635 DRM_BO_FLAG_MEM_TT |
636 DRM_BO_FLAG_MEM_VRAM |
637 DRM_BO_FLAG_NO_EVICT,
638 DRM_BO_HINT_DONT_FENCE, &scrn->buffer);
639
640 if (ret)
641 return EGL_FALSE;
642
643 prettyColors(drm_drv->device->drmFD, scrn->buffer.handle, pitch);
644
645 ret = drmModeAddFB(drm_drv->device->drmFD, mode->Width, mode->Height,
646 32, 32, pitch,
647 scrn->buffer.handle,
648 &scrn->fbID);
649
650 if (ret)
651 goto err_bo;
652
653 scrn->fb = drmModeGetFB(drm_drv->device->drmFD, scrn->fbID);
654 if (!scrn->fb)
655 goto err_bo;
656
657 for (j = 0; j < drm_drv->res->count_connectors; j++) {
658 drmModeConnector *con = drmModeGetConnector(drm_drv->device->drmFD, drm_drv->res->connectors[j]);
659 scrn->mode = drm_find_mode(con, mode);
660 if (!scrn->mode)
661 goto err_fb;
662
663 for (k = 0; k < con->count_encoders; k++) {
664 drmModeEncoder *enc = drmModeGetEncoder(drm_drv->device->drmFD, con->encoders[k]);
665 for (i = 0; i < drm_drv->res->count_crtcs; i++) {
666 if (enc->possible_crtcs & (1<<i)) {
667 ret = drmModeSetCrtc(
668 drm_drv->device->drmFD,
669 drm_drv->res->crtcs[i],
670 scrn->fbID,
671 0, 0,
672 &drm_drv->res->connectors[j], 1,
673 scrn->mode);
674 /* skip the other crtcs now */
675 i = drm_drv->res->count_crtcs;
676 }
677 }
678 }
679 }
680
681 scrn->front.handle = scrn->buffer.handle;
682 scrn->front.pitch = pitch;
683 scrn->front.width = mode->Width;
684 scrn->front.height = mode->Height;
685
686 scrn->surf = surf;
687 intel_bind_frontbuffer(surf->drawable, &scrn->front);
688
689 scrn->shown = 1;
690
691 return EGL_TRUE;
692
693 err_fb:
694 /* TODO remove fb */
695
696 err_bo:
697 drmBOUnreference(drm_drv->device->drmFD, &scrn->buffer);
698 return EGL_FALSE;
699 }
700
701 static EGLBoolean
702 drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
703 {
704 struct drm_surface *fs = lookup_drm_surface(surface);
705 _eglRemoveSurface(&fs->base);
706 if (fs->base.IsBound) {
707 fs->base.DeletePending = EGL_TRUE;
708 } else {
709 intel_bind_frontbuffer(fs->drawable, NULL);
710 intel_destroy_drawable(fs->drawable);
711 free(fs->drawable);
712 free(fs);
713 }
714 return EGL_TRUE;
715 }
716
717
718 static EGLBoolean
719 drm_make_current(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context)
720 {
721 struct drm_surface *readSurf = lookup_drm_surface(read);
722 struct drm_surface *drawSurf = lookup_drm_surface(draw);
723 struct drm_context *ctx = lookup_drm_context(context);
724 EGLBoolean b;
725
726 b = _eglMakeCurrent(drv, dpy, draw, read, context);
727 if (!b)
728 return EGL_FALSE;
729
730 if (ctx) {
731 if (!drawSurf || !readSurf)
732 return EGL_FALSE;
733
734 intel_make_current(ctx->context, drawSurf->drawable, readSurf->drawable);
735 } else {
736 intel_make_current(NULL, NULL, NULL);
737 }
738
739 return EGL_TRUE;
740 }
741
742 static EGLBoolean
743 drm_swap_buffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
744 {
745 struct drm_surface *surf = lookup_drm_surface(draw);
746 if (!surf)
747 return EGL_FALSE;
748
749 /* error checking */
750 if (!_eglSwapBuffers(drv, dpy, draw))
751 return EGL_FALSE;
752
753 intel_swap_buffers(surf->drawable);
754 return EGL_TRUE;
755 }
756
757
758 /**
759 * The bootstrap function. Return a new drm_driver object and
760 * plug in API functions.
761 */
762 _EGLDriver *
763 _eglMain(_EGLDisplay *dpy, const char *args)
764 {
765 struct drm_driver *drm;
766
767 drm = (struct drm_driver *) calloc(1, sizeof(struct drm_driver));
768 if (!drm) {
769 return NULL;
770 }
771
772 /* First fill in the dispatch table with defaults */
773 _eglInitDriverFallbacks(&drm->base);
774 /* then plug in our Drm-specific functions */
775 drm->base.API.Initialize = drm_initialize;
776 drm->base.API.Terminate = drm_terminate;
777 drm->base.API.CreateContext = drm_create_context;
778 drm->base.API.MakeCurrent = drm_make_current;
779 drm->base.API.CreateWindowSurface = drm_create_window_surface;
780 drm->base.API.CreatePixmapSurface = drm_create_pixmap_surface;
781 drm->base.API.CreatePbufferSurface = drm_create_pbuffer_surface;
782 drm->base.API.DestroySurface = drm_destroy_surface;
783 drm->base.API.DestroyContext = drm_destroy_context;
784 drm->base.API.CreateScreenSurfaceMESA = drm_create_screen_surface_mesa;
785 drm->base.API.ShowScreenSurfaceMESA = drm_show_screen_surface_mesa;
786 drm->base.API.SwapBuffers = drm_swap_buffers;
787
788 drm->base.ClientAPIsMask = EGL_OPENGL_BIT /*| EGL_OPENGL_ES_BIT*/;
789 drm->base.Name = "DRM/Gallium";
790
791 /* enable supported extensions */
792 drm->base.Extensions.MESA_screen_surface = EGL_TRUE;
793 drm->base.Extensions.MESA_copy_context = EGL_TRUE;
794
795 return &drm->base;
796 }