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