ed7eab50ddab5d2244802ab9ceff580b7f35e68a
[mesa.git] / src / gallium / winsys / egl_xlib / egl_xlib.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * EGL / softpipe / xlib winsys module
30 *
31 * Authors: Brian Paul
32 */
33
34
35 #include <dlfcn.h>
36 #include <X11/Xutil.h>
37
38 #include "pipe/p_compiler.h"
39 #include "pipe/p_format.h"
40 #include "pipe/p_state.h"
41 #include "pipe/internal/p_winsys_screen.h"
42 #include "util/u_memory.h"
43 #include "softpipe/sp_winsys.h"
44 #include "softpipe/sp_texture.h"
45
46 #include "eglconfig.h"
47 #include "eglconfigutil.h"
48 #include "eglcontext.h"
49 #include "egldisplay.h"
50 #include "egldriver.h"
51 #include "eglglobals.h"
52 #include "egllog.h"
53 #include "eglsurface.h"
54
55 #include "state_tracker/st_public.h"
56
57 #include "sw_winsys.h"
58
59
60 /** subclass of _EGLDriver */
61 struct xlib_egl_driver
62 {
63 _EGLDriver Base; /**< base class */
64
65 struct pipe_winsys *winsys;
66 struct pipe_screen *screen;
67 };
68
69
70 /** subclass of _EGLContext */
71 struct xlib_egl_context
72 {
73 _EGLContext Base; /**< base class */
74
75 struct pipe_context *pipe; /**< Gallium driver context */
76 struct st_context *Context; /**< Mesa/gallium state tracker context */
77 };
78
79
80 /** subclass of _EGLSurface */
81 struct xlib_egl_surface
82 {
83 _EGLSurface Base; /**< base class */
84
85 /* These are set for window surface */
86 Display *Dpy; /**< The X Display of the window */
87 Window Win; /**< The user-created window ID */
88 GC Gc;
89 XVisualInfo VisInfo;
90
91 struct pipe_winsys *winsys;
92
93 struct st_framebuffer *Framebuffer;
94 };
95
96
97 /** cast wrapper */
98 static INLINE struct xlib_egl_driver *
99 xlib_egl_driver(_EGLDriver *drv)
100 {
101 return (struct xlib_egl_driver *) drv;
102 }
103
104
105 static INLINE struct xlib_egl_surface *
106 lookup_surface(_EGLSurface *surf)
107 {
108 return (struct xlib_egl_surface *) surf;
109 }
110
111
112 static INLINE struct xlib_egl_context *
113 lookup_context(_EGLContext *ctx)
114 {
115 return (struct xlib_egl_context *) ctx;
116 }
117
118
119 static unsigned int
120 bitcount(unsigned int n)
121 {
122 unsigned int bits;
123 for (bits = 0; n > 0; n = n >> 1) {
124 bits += (n & 1);
125 }
126 return bits;
127 }
128
129
130 /**
131 * Create the EGLConfigs. (one per X visual)
132 */
133 static void
134 create_configs(_EGLDriver *drv, _EGLDisplay *disp)
135 {
136 static const EGLint all_apis = (EGL_OPENGL_ES_BIT |
137 EGL_OPENGL_ES2_BIT |
138 EGL_OPENVG_BIT |
139 EGL_OPENGL_BIT);
140 XVisualInfo *visInfo, visTemplate;
141 int num_visuals, i;
142
143 /* get list of all X visuals, create an EGL config for each */
144 visTemplate.screen = DefaultScreen(disp->Xdpy);
145 visInfo = XGetVisualInfo(disp->Xdpy, VisualScreenMask,
146 &visTemplate, &num_visuals);
147 if (!visInfo) {
148 printf("egl_xlib.c: couldn't get any X visuals\n");
149 abort();
150 }
151
152 for (i = 0; i < num_visuals; i++) {
153 _EGLConfig *config = calloc(1, sizeof(_EGLConfig));
154 int id = i + 1;
155 int rbits = bitcount(visInfo[i].red_mask);
156 int gbits = bitcount(visInfo[i].green_mask);
157 int bbits = bitcount(visInfo[i].blue_mask);
158 int abits = bbits == 8 ? 8 : 0;
159 int zbits = 24;
160 int sbits = 8;
161 int visid = visInfo[i].visualid;
162 #if defined(__cplusplus) || defined(c_plusplus)
163 int vistype = visInfo[i].c_class;
164 #else
165 int vistype = visInfo[i].class;
166 #endif
167
168 _eglInitConfig(config, id);
169 SET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE, rbits + gbits + bbits + abits);
170 SET_CONFIG_ATTRIB(config, EGL_RED_SIZE, rbits);
171 SET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE, gbits);
172 SET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE, bbits);
173 SET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE, abits);
174 SET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE, zbits);
175 SET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE, sbits);
176 SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_ID, visid);
177 SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, vistype);
178 SET_CONFIG_ATTRIB(config, EGL_NATIVE_RENDERABLE, EGL_FALSE);
179 SET_CONFIG_ATTRIB(config, EGL_CONFORMANT, all_apis);
180 SET_CONFIG_ATTRIB(config, EGL_RENDERABLE_TYPE, all_apis);
181 SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT);
182 SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE);
183 SET_CONFIG_ATTRIB(config, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE);
184
185 _eglAddConfig(disp, config);
186 }
187 }
188
189
190 /**
191 * Called via eglInitialize(), drv->API.Initialize().
192 */
193 static EGLBoolean
194 xlib_eglInitialize(_EGLDriver *drv, _EGLDisplay *dpy,
195 EGLint *minor, EGLint *major)
196 {
197 create_configs(drv, dpy);
198
199 drv->Initialized = EGL_TRUE;
200
201 /* we're supporting EGL 1.4 */
202 *minor = 1;
203 *major = 4;
204
205 return EGL_TRUE;
206 }
207
208
209 /**
210 * Called via eglTerminate(), drv->API.Terminate().
211 */
212 static EGLBoolean
213 xlib_eglTerminate(_EGLDriver *drv, _EGLDisplay *dpy)
214 {
215 return EGL_TRUE;
216 }
217
218
219 static _EGLProc
220 xlib_eglGetProcAddress(const char *procname)
221 {
222 return (_EGLProc) st_get_proc_address(procname);
223 }
224
225
226 static void
227 get_drawable_visual_info(Display *dpy, Drawable d, XVisualInfo *visInfo)
228 {
229 XWindowAttributes attr;
230 XVisualInfo visTemp, *vis;
231 int num_visuals;
232
233 XGetWindowAttributes(dpy, d, &attr);
234
235 visTemp.screen = DefaultScreen(dpy);
236 visTemp.visualid = attr.visual->visualid;
237 vis = XGetVisualInfo(dpy,
238 (VisualScreenMask | VisualIDMask),
239 &visTemp, &num_visuals);
240 if (vis)
241 *visInfo = *vis;
242
243 XFree(vis);
244 }
245
246
247
248 /** Get size of given window */
249 static Status
250 get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
251 {
252 Window root;
253 Status stat;
254 int xpos, ypos;
255 unsigned int w, h, bw, depth;
256 stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
257 *width = w;
258 *height = h;
259 return stat;
260 }
261
262
263 static void
264 check_and_update_buffer_size(struct xlib_egl_surface *surface)
265 {
266 uint width, height;
267 if (surface->Base.Type == EGL_PBUFFER_BIT) {
268 width = surface->Base.Width;
269 height = surface->Base.Height;
270 }
271 else {
272 get_drawable_size(surface->Dpy, surface->Win, &width, &height);
273 }
274 st_resize_framebuffer(surface->Framebuffer, width, height);
275 surface->Base.Width = width;
276 surface->Base.Height = height;
277 }
278
279
280
281 static void
282 display_surface(struct pipe_winsys *pws,
283 struct pipe_surface *psurf,
284 struct xlib_egl_surface *xsurf)
285 {
286 struct softpipe_texture *spt = softpipe_texture(psurf->texture);
287 XImage *ximage;
288 void *data;
289
290 if (xsurf->Base.Type == EGL_PBUFFER_BIT)
291 return;
292
293 ximage = XCreateImage(xsurf->Dpy,
294 xsurf->VisInfo.visual,
295 xsurf->VisInfo.depth,
296 ZPixmap, 0, /* format, offset */
297 NULL, /* data */
298 0, 0, /* size */
299 32, /* bitmap_pad */
300 0); /* bytes_per_line */
301
302
303 assert(ximage->format);
304 assert(ximage->bitmap_unit);
305
306 data = pws->buffer_map(pws, spt->buffer, 0);
307
308 /* update XImage's fields */
309 ximage->data = data;
310 ximage->width = psurf->width;
311 ximage->height = psurf->height;
312 ximage->bytes_per_line = spt->stride[psurf->level];
313
314 XPutImage(xsurf->Dpy, xsurf->Win, xsurf->Gc,
315 ximage, 0, 0, 0, 0, psurf->width, psurf->height);
316
317 XSync(xsurf->Dpy, 0);
318
319 ximage->data = NULL;
320 XDestroyImage(ximage);
321
322 pws->buffer_unmap(pws, spt->buffer);
323 }
324
325
326
327 /** Display gallium surface in X window */
328 static void
329 flush_frontbuffer(struct pipe_winsys *pws,
330 struct pipe_surface *psurf,
331 void *context_private)
332 {
333 struct xlib_egl_surface *xsurf = (struct xlib_egl_surface *) context_private;
334 display_surface(pws, psurf, xsurf);
335 }
336
337
338
339 /**
340 * Called via eglCreateContext(), drv->API.CreateContext().
341 */
342 static _EGLContext *
343 xlib_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
344 _EGLContext *share_list, const EGLint *attrib_list)
345 {
346 struct xlib_egl_driver *xdrv = xlib_egl_driver(drv);
347 struct xlib_egl_context *ctx;
348 struct st_context *share_ctx = NULL; /* XXX fix */
349 __GLcontextModes visual;
350
351 ctx = CALLOC_STRUCT(xlib_egl_context);
352 if (!ctx)
353 return NULL;
354
355 /* let EGL lib init the common stuff */
356 if (!_eglInitContext(drv, &ctx->Base, conf, attrib_list)) {
357 free(ctx);
358 return NULL;
359 }
360
361 /* API-dependent context creation */
362 switch (ctx->Base.ClientAPI) {
363 case EGL_OPENVG_API:
364 case EGL_OPENGL_ES_API:
365 _eglLog(_EGL_DEBUG, "Create Context for ES version %d\n",
366 ctx->Base.ClientVersion);
367 /* fall-through */
368 case EGL_OPENGL_API:
369 /* create a softpipe context */
370 ctx->pipe = softpipe_create(xdrv->screen);
371 /* Now do xlib / state tracker inits here */
372 _eglConfigToContextModesRec(conf, &visual);
373 ctx->Context = st_create_context(ctx->pipe, &visual, share_ctx);
374 break;
375 default:
376 _eglError(EGL_BAD_MATCH, "eglCreateContext(unsupported API)");
377 free(ctx);
378 return NULL;
379 }
380
381 return &ctx->Base;
382 }
383
384
385 static EGLBoolean
386 xlib_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
387 {
388 struct xlib_egl_context *context = lookup_context(ctx);
389
390 if (!_eglIsContextBound(&context->Base)) {
391 /* API-dependent clean-up */
392 switch (context->Base.ClientAPI) {
393 case EGL_OPENGL_ES_API:
394 case EGL_OPENVG_API:
395 /* fall-through */
396 case EGL_OPENGL_API:
397 st_destroy_context(context->Context);
398 break;
399 default:
400 assert(0);
401 }
402 free(context);
403 }
404 return EGL_TRUE;
405 }
406
407
408 /**
409 * Called via eglMakeCurrent(), drv->API.MakeCurrent().
410 */
411 static EGLBoolean
412 xlib_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy,
413 _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx)
414 {
415 struct xlib_egl_context *context = lookup_context(ctx);
416 struct xlib_egl_surface *draw_surf = lookup_surface(draw);
417 struct xlib_egl_surface *read_surf = lookup_surface(read);
418 struct st_context *oldctx = st_get_current();
419
420 if (!_eglMakeCurrent(drv, dpy, draw, read, ctx))
421 return EGL_FALSE;
422
423 /* Flush before switching context. Check client API? */
424 if (oldctx)
425 st_flush(oldctx, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
426 st_make_current((context ? context->Context : NULL),
427 (draw_surf ? draw_surf->Framebuffer : NULL),
428 (read_surf ? read_surf->Framebuffer : NULL));
429
430 if (draw_surf)
431 check_and_update_buffer_size(draw_surf);
432 if (read_surf && read_surf != draw_surf)
433 check_and_update_buffer_size(draw_surf);
434
435 return EGL_TRUE;
436 }
437
438
439 static enum pipe_format
440 choose_color_format(const __GLcontextModes *visual)
441 {
442 if (visual->redBits == 8 &&
443 visual->greenBits == 8 &&
444 visual->blueBits == 8 &&
445 visual->alphaBits == 8) {
446 /* XXX this really also depends on the ordering of R,G,B,A */
447 return PIPE_FORMAT_A8R8G8B8_UNORM;
448 }
449 else {
450 assert(0);
451 return PIPE_FORMAT_NONE;
452 }
453 }
454
455
456 static enum pipe_format
457 choose_depth_format(const __GLcontextModes *visual)
458 {
459 if (visual->depthBits > 0)
460 return PIPE_FORMAT_S8Z24_UNORM;
461 else
462 return PIPE_FORMAT_NONE;
463 }
464
465
466 static enum pipe_format
467 choose_stencil_format(const __GLcontextModes *visual)
468 {
469 if (visual->stencilBits > 0)
470 return PIPE_FORMAT_S8Z24_UNORM;
471 else
472 return PIPE_FORMAT_NONE;
473 }
474
475
476 /**
477 * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
478 */
479 static _EGLSurface *
480 xlib_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
481 NativeWindowType window, const EGLint *attrib_list)
482 {
483 struct xlib_egl_driver *xdrv = xlib_egl_driver(drv);
484 struct xlib_egl_surface *surf;
485 __GLcontextModes visual;
486 uint width, height;
487
488 surf = CALLOC_STRUCT(xlib_egl_surface);
489 if (!surf)
490 return NULL;
491
492 /* Let EGL lib init the common stuff */
493 if (!_eglInitSurface(drv, &surf->Base, EGL_WINDOW_BIT,
494 conf, attrib_list)) {
495 free(surf);
496 return NULL;
497 }
498
499 /*
500 * Now init the Xlib and gallium stuff
501 */
502 surf->Win = (Window) window; /* The X window ID */
503 surf->Dpy = disp->Xdpy; /* The X display */
504 surf->Gc = XCreateGC(surf->Dpy, surf->Win, 0, NULL);
505
506 surf->winsys = xdrv->winsys;
507
508 _eglConfigToContextModesRec(conf, &visual);
509 get_drawable_size(surf->Dpy, surf->Win, &width, &height);
510 get_drawable_visual_info(surf->Dpy, surf->Win, &surf->VisInfo);
511
512 surf->Base.Width = width;
513 surf->Base.Height = height;
514
515 /* Create GL statetracker framebuffer */
516 surf->Framebuffer = st_create_framebuffer(&visual,
517 choose_color_format(&visual),
518 choose_depth_format(&visual),
519 choose_stencil_format(&visual),
520 width, height,
521 (void *) surf);
522
523 st_resize_framebuffer(surf->Framebuffer, width, height);
524
525 return &surf->Base;
526 }
527
528
529 static _EGLSurface *
530 xlib_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
531 const EGLint *attrib_list)
532 {
533 struct xlib_egl_driver *xdrv = xlib_egl_driver(drv);
534 struct xlib_egl_surface *surf;
535 __GLcontextModes visual;
536 uint width, height;
537 EGLBoolean bind_texture;
538
539 surf = CALLOC_STRUCT(xlib_egl_surface);
540 if (!surf) {
541 _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface");
542 return NULL;
543 }
544
545 if (!_eglInitSurface(drv, &surf->Base, EGL_PBUFFER_BIT,
546 conf, attrib_list)) {
547 free(surf);
548 return NULL;
549 }
550 if (surf->Base.Width < 0 || surf->Base.Height < 0) {
551 _eglError(EGL_BAD_PARAMETER, "eglCreatePbufferSurface");
552 free(surf);
553 return NULL;
554 }
555
556 bind_texture = (surf->Base.TextureFormat != EGL_NO_TEXTURE);
557 width = (uint) surf->Base.Width;
558 height = (uint) surf->Base.Height;
559 if ((surf->Base.TextureTarget == EGL_NO_TEXTURE && bind_texture) ||
560 (surf->Base.TextureTarget != EGL_NO_TEXTURE && !bind_texture)) {
561 _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface");
562 free(surf);
563 return NULL;
564 }
565 /* a framebuffer of zero width or height confuses st */
566 if (width == 0 || height == 0) {
567 _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface");
568 free(surf);
569 return NULL;
570 }
571 /* no mipmap generation */
572 if (surf->Base.MipmapTexture) {
573 _eglError(EGL_BAD_MATCH, "eglCreatePbufferSurface");
574 free(surf);
575 return NULL;
576 }
577
578 surf->winsys = xdrv->winsys;
579
580 _eglConfigToContextModesRec(conf, &visual);
581
582 /* Create GL statetracker framebuffer */
583 surf->Framebuffer = st_create_framebuffer(&visual,
584 choose_color_format(&visual),
585 choose_depth_format(&visual),
586 choose_stencil_format(&visual),
587 width, height,
588 (void *) surf);
589 st_resize_framebuffer(surf->Framebuffer, width, height);
590
591 return &surf->Base;
592 }
593
594
595 static EGLBoolean
596 xlib_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface)
597 {
598 struct xlib_egl_surface *surf = lookup_surface(surface);
599 if (!_eglIsSurfaceBound(&surf->Base)) {
600 if (surf->Base.Type != EGL_PBUFFER_BIT)
601 XFreeGC(surf->Dpy, surf->Gc);
602 st_unreference_framebuffer(surf->Framebuffer);
603 free(surf);
604 }
605 return EGL_TRUE;
606 }
607
608
609 static EGLBoolean
610 xlib_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy,
611 _EGLSurface *surface, EGLint buffer)
612 {
613 struct xlib_egl_surface *xsurf = lookup_surface(surface);
614 struct xlib_egl_context *xctx;
615 struct pipe_surface *psurf;
616 enum pipe_format format;
617 int target;
618
619 if (!xsurf || xsurf->Base.Type != EGL_PBUFFER_BIT)
620 return _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
621 if (buffer != EGL_BACK_BUFFER)
622 return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
623 if (xsurf->Base.BoundToTexture)
624 return _eglError(EGL_BAD_ACCESS, "eglBindTexImage");
625
626 /* this should be updated when choose_color_format is */
627 switch (xsurf->Base.TextureFormat) {
628 case EGL_TEXTURE_RGB:
629 format = PIPE_FORMAT_R8G8B8_UNORM;
630 break;
631 case EGL_TEXTURE_RGBA:
632 format = PIPE_FORMAT_A8R8G8B8_UNORM;
633 break;
634 default:
635 return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
636 }
637
638 switch (xsurf->Base.TextureTarget) {
639 case EGL_TEXTURE_2D:
640 target = ST_TEXTURE_2D;
641 break;
642 default:
643 return _eglError(EGL_BAD_MATCH, "eglBindTexImage");
644 }
645
646 /* flush properly */
647 if (eglGetCurrentSurface(EGL_DRAW) == surface) {
648 xctx = lookup_context(_eglGetCurrentContext());
649 st_flush(xctx->Context, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME,
650 NULL);
651 }
652 else if (_eglIsSurfaceBound(&xsurf->Base)) {
653 xctx = lookup_context(xsurf->Base.Binding);
654 if (xctx)
655 st_finish(xctx->Context);
656 }
657
658 st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT,
659 &psurf);
660 st_bind_texture_surface(psurf, target, xsurf->Base.MipmapLevel, format);
661 xsurf->Base.BoundToTexture = EGL_TRUE;
662
663 return EGL_TRUE;
664 }
665
666
667 static EGLBoolean
668 xlib_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
669 EGLint buffer)
670 {
671 struct xlib_egl_surface *xsurf = lookup_surface(surface);
672 struct pipe_surface *psurf;
673
674 if (!xsurf || xsurf->Base.Type != EGL_PBUFFER_BIT ||
675 !xsurf->Base.BoundToTexture)
676 return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
677 if (buffer != EGL_BACK_BUFFER)
678 return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
679
680 st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT,
681 &psurf);
682 st_unbind_texture_surface(psurf, ST_TEXTURE_2D, xsurf->Base.MipmapLevel);
683 xsurf->Base.BoundToTexture = EGL_FALSE;
684
685 return EGL_TRUE;
686 }
687
688
689 static EGLBoolean
690 xlib_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw)
691 {
692 /* error checking step: */
693 if (!_eglSwapBuffers(drv, dpy, draw))
694 return EGL_FALSE;
695
696 {
697 struct xlib_egl_surface *xsurf = lookup_surface(draw);
698 struct pipe_winsys *pws = xsurf->winsys;
699 struct pipe_surface *psurf;
700
701 st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT,
702 &psurf);
703
704 st_notify_swapbuffers(xsurf->Framebuffer);
705
706 display_surface(pws, psurf, xsurf);
707
708 check_and_update_buffer_size(xsurf);
709 }
710
711 return EGL_TRUE;
712 }
713
714
715 /**
716 * Determine which API(s) is(are) present by looking for some specific
717 * global symbols.
718 */
719 static EGLint
720 find_supported_apis(void)
721 {
722 EGLint mask = 0;
723 void *handle;
724
725 handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL);
726 if(!handle)
727 return mask;
728
729 if (dlsym(handle, "st_api_OpenGL_ES1"))
730 mask |= EGL_OPENGL_ES_BIT;
731
732 if (dlsym(handle, "st_api_OpenGL_ES2"))
733 mask |= EGL_OPENGL_ES2_BIT;
734
735 if (dlsym(handle, "st_api_OpenGL"))
736 mask |= EGL_OPENGL_BIT;
737
738 if (dlsym(handle, "st_api_OpenVG"))
739 mask |= EGL_OPENVG_BIT;
740
741 dlclose(handle);
742
743 return mask;
744 }
745
746
747 /**
748 * This is the main entrypoint into the driver.
749 * Called by libEGL to instantiate an _EGLDriver object.
750 */
751 _EGLDriver *
752 _eglMain(_EGLDisplay *dpy, const char *args)
753 {
754 struct xlib_egl_driver *xdrv;
755
756 _eglLog(_EGL_INFO, "Entering EGL/Xlib _eglMain(%s)", args);
757
758 xdrv = CALLOC_STRUCT(xlib_egl_driver);
759 if (!xdrv)
760 return NULL;
761
762 if (!dpy->Xdpy) {
763 dpy->Xdpy = XOpenDisplay(NULL);
764 }
765
766 _eglInitDriverFallbacks(&xdrv->Base);
767 xdrv->Base.API.Initialize = xlib_eglInitialize;
768 xdrv->Base.API.Terminate = xlib_eglTerminate;
769 xdrv->Base.API.GetProcAddress = xlib_eglGetProcAddress;
770 xdrv->Base.API.CreateContext = xlib_eglCreateContext;
771 xdrv->Base.API.DestroyContext = xlib_eglDestroyContext;
772 xdrv->Base.API.CreateWindowSurface = xlib_eglCreateWindowSurface;
773 xdrv->Base.API.CreatePbufferSurface = xlib_eglCreatePbufferSurface;
774 xdrv->Base.API.DestroySurface = xlib_eglDestroySurface;
775 xdrv->Base.API.BindTexImage = xlib_eglBindTexImage;
776 xdrv->Base.API.ReleaseTexImage = xlib_eglReleaseTexImage;
777 xdrv->Base.API.MakeCurrent = xlib_eglMakeCurrent;
778 xdrv->Base.API.SwapBuffers = xlib_eglSwapBuffers;
779
780 xdrv->Base.ClientAPIsMask = find_supported_apis();
781 if (xdrv->Base.ClientAPIsMask == 0x0) {
782 /* the app isn't directly linked with any EGL-supprted APIs
783 * (such as libGLESv2.so) so use an EGL utility to see what
784 * APIs might be loaded dynamically on this system.
785 */
786 xdrv->Base.ClientAPIsMask = _eglFindAPIs();
787 }
788
789 xdrv->Base.Name = "Xlib/softpipe";
790
791 /* create one winsys and use it for all contexts/surfaces */
792 xdrv->winsys = create_sw_winsys();
793 xdrv->winsys->flush_frontbuffer = flush_frontbuffer;
794
795 xdrv->screen = softpipe_create_screen(xdrv->winsys);
796
797 return &xdrv->Base;
798 }