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