00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00035 #include <dlfcn.h>
00036 #include <X11/Xutil.h>
00037
00038 #include "pipe/p_compiler.h"
00039 #include "pipe/p_format.h"
00040 #include "pipe/p_state.h"
00041 #include "pipe/p_winsys.h"
00042 #include "util/u_memory.h"
00043 #include "softpipe/sp_winsys.h"
00044
00045 #include "eglconfig.h"
00046 #include "eglconfigutil.h"
00047 #include "eglcontext.h"
00048 #include "egldisplay.h"
00049 #include "egldriver.h"
00050 #include "eglglobals.h"
00051 #include "egllog.h"
00052 #include "eglsurface.h"
00053
00054 #include "state_tracker/st_public.h"
00055
00056 #include "sw_winsys.h"
00057
00058
00060 struct xlib_egl_driver
00061 {
00062 _EGLDriver Base;
00064 struct pipe_winsys *winsys;
00065 struct pipe_screen *screen;
00066 };
00067
00068
00070 struct xlib_egl_context
00071 {
00072 _EGLContext Base;
00074 struct pipe_context *pipe;
00075 struct st_context *Context;
00076 };
00077
00078
00080 struct xlib_egl_surface
00081 {
00082 _EGLSurface Base;
00084 Display *Dpy;
00085 Window Win;
00086 GC Gc;
00087 XVisualInfo VisInfo;
00088
00089 struct pipe_winsys *winsys;
00090
00091 struct st_framebuffer *Framebuffer;
00092 };
00093
00094
00096 static INLINE struct xlib_egl_driver *
00097 xlib_egl_driver(_EGLDriver *drv)
00098 {
00099 return (struct xlib_egl_driver *) drv;
00100 }
00101
00102
00103 static struct xlib_egl_surface *
00104 lookup_surface(EGLSurface surf)
00105 {
00106 _EGLSurface *surface = _eglLookupSurface(surf);
00107 return (struct xlib_egl_surface *) surface;
00108 }
00109
00110
00111 static struct xlib_egl_context *
00112 lookup_context(EGLContext surf)
00113 {
00114 _EGLContext *context = _eglLookupContext(surf);
00115 return (struct xlib_egl_context *) context;
00116 }
00117
00118
00119 static unsigned int
00120 bitcount(unsigned int n)
00121 {
00122 unsigned int bits;
00123 for (bits = 0; n > 0; n = n >> 1) {
00124 bits += (n & 1);
00125 }
00126 return bits;
00127 }
00128
00129
00133 static void
00134 create_configs(_EGLDriver *drv, EGLDisplay dpy)
00135 {
00136 static const EGLint all_apis = (EGL_OPENGL_ES_BIT |
00137 EGL_OPENGL_ES2_BIT |
00138 EGL_OPENVG_BIT |
00139 EGL_OPENGL_BIT);
00140 _EGLDisplay *disp = _eglLookupDisplay(dpy);
00141 XVisualInfo *visInfo, visTemplate;
00142 int num_visuals, i;
00143
00144
00145 visTemplate.screen = DefaultScreen(disp->Xdpy);
00146 visInfo = XGetVisualInfo(disp->Xdpy, VisualScreenMask,
00147 &visTemplate, &num_visuals);
00148 if (!visInfo) {
00149 printf("egl_xlib.c: couldn't get any X visuals\n");
00150 abort();
00151 }
00152
00153 for (i = 0; i < num_visuals; i++) {
00154 _EGLConfig *config = calloc(1, sizeof(_EGLConfig));
00155 int id = i + 1;
00156 int rbits = bitcount(visInfo[i].red_mask);
00157 int gbits = bitcount(visInfo[i].green_mask);
00158 int bbits = bitcount(visInfo[i].blue_mask);
00159 int abits = bbits == 8 ? 8 : 0;
00160 int zbits = 24;
00161 int sbits = 8;
00162 int visid = visInfo[i].visualid;
00163 #if defined(__cplusplus) || defined(c_plusplus)
00164 int vistype = visInfo[i].c_class;
00165 #else
00166 int vistype = visInfo[i].class;
00167 #endif
00168
00169 _eglInitConfig(config, id);
00170 SET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE, rbits + gbits + bbits + abits);
00171 SET_CONFIG_ATTRIB(config, EGL_RED_SIZE, rbits);
00172 SET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE, gbits);
00173 SET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE, bbits);
00174 SET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE, abits);
00175 SET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE, zbits);
00176 SET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE, sbits);
00177 SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_ID, visid);
00178 SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, vistype);
00179 SET_CONFIG_ATTRIB(config, EGL_NATIVE_RENDERABLE, EGL_FALSE);
00180 SET_CONFIG_ATTRIB(config, EGL_CONFORMANT, all_apis);
00181 SET_CONFIG_ATTRIB(config, EGL_RENDERABLE_TYPE, all_apis);
00182 SET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
00183
00184 _eglAddConfig(disp, config);
00185 }
00186 }
00187
00188
00192 static EGLBoolean
00193 xlib_eglInitialize(_EGLDriver *drv, EGLDisplay dpy,
00194 EGLint *minor, EGLint *major)
00195 {
00196 create_configs(drv, dpy);
00197
00198 drv->Initialized = EGL_TRUE;
00199
00200
00201 *minor = 1;
00202 *major = 4;
00203
00204 return EGL_TRUE;
00205 }
00206
00207
00211 static EGLBoolean
00212 xlib_eglTerminate(_EGLDriver *drv, EGLDisplay dpy)
00213 {
00214 return EGL_TRUE;
00215 }
00216
00217
00218 static _EGLProc
00219 xlib_eglGetProcAddress(const char *procname)
00220 {
00221 return (_EGLProc) st_get_proc_address(procname);
00222 }
00223
00224
00225 static void
00226 get_drawable_visual_info(Display *dpy, Drawable d, XVisualInfo *visInfo)
00227 {
00228 XWindowAttributes attr;
00229 XVisualInfo visTemp, *vis;
00230 int num_visuals;
00231
00232 XGetWindowAttributes(dpy, d, &attr);
00233
00234 visTemp.screen = DefaultScreen(dpy);
00235 visTemp.visualid = attr.visual->visualid;
00236 vis = XGetVisualInfo(dpy,
00237 (VisualScreenMask | VisualIDMask),
00238 &visTemp, &num_visuals);
00239 if (vis)
00240 *visInfo = *vis;
00241
00242 XFree(vis);
00243 }
00244
00245
00246
00248 static Status
00249 get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
00250 {
00251 Window root;
00252 Status stat;
00253 int xpos, ypos;
00254 unsigned int w, h, bw, depth;
00255 stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
00256 *width = w;
00257 *height = h;
00258 return stat;
00259 }
00260
00261
00262 static void
00263 check_and_update_buffer_size(struct xlib_egl_surface *surface)
00264 {
00265 uint width, height;
00266 get_drawable_size(surface->Dpy, surface->Win, &width, &height);
00267 st_resize_framebuffer(surface->Framebuffer, width, height);
00268 surface->Base.Width = width;
00269 surface->Base.Height = height;
00270 }
00271
00272
00273
00274 static void
00275 display_surface(struct pipe_winsys *pws,
00276 struct pipe_surface *psurf,
00277 struct xlib_egl_surface *xsurf)
00278 {
00279 XImage *ximage;
00280 void *data;
00281
00282 ximage = XCreateImage(xsurf->Dpy,
00283 xsurf->VisInfo.visual,
00284 xsurf->VisInfo.depth,
00285 ZPixmap, 0,
00286 NULL,
00287 0, 0,
00288 32,
00289 0);
00290
00291
00292 assert(ximage->format);
00293 assert(ximage->bitmap_unit);
00294
00295 data = pws->buffer_map(pws, psurf->buffer, 0);
00296
00297
00298 ximage->data = data;
00299 ximage->width = psurf->width;
00300 ximage->height = psurf->height;
00301 ximage->bytes_per_line = psurf->stride;
00302
00303 XPutImage(xsurf->Dpy, xsurf->Win, xsurf->Gc,
00304 ximage, 0, 0, 0, 0, psurf->width, psurf->height);
00305
00306 XSync(xsurf->Dpy, 0);
00307
00308 ximage->data = NULL;
00309 XDestroyImage(ximage);
00310
00311 pws->buffer_unmap(pws, psurf->buffer);
00312 }
00313
00314
00315
00317 static void
00318 flush_frontbuffer(struct pipe_winsys *pws,
00319 struct pipe_surface *psurf,
00320 void *context_private)
00321 {
00322 struct xlib_egl_surface *xsurf = (struct xlib_egl_surface *) context_private;
00323 display_surface(pws, psurf, xsurf);
00324 }
00325
00326
00327
00331 static EGLContext
00332 xlib_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
00333 EGLContext share_list, const EGLint *attrib_list)
00334 {
00335 struct xlib_egl_driver *xdrv = xlib_egl_driver(drv);
00336 _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
00337 struct xlib_egl_context *ctx;
00338 struct st_context *share_ctx = NULL;
00339 __GLcontextModes visual;
00340
00341 ctx = CALLOC_STRUCT(xlib_egl_context);
00342 if (!ctx)
00343 return EGL_NO_CONTEXT;
00344
00345
00346 if (!_eglInitContext(drv, dpy, &ctx->Base, config, attrib_list)) {
00347 free(ctx);
00348 return EGL_NO_CONTEXT;
00349 }
00350
00351
00352 switch (ctx->Base.ClientAPI) {
00353 case EGL_OPENVG_API:
00354 case EGL_OPENGL_ES_API:
00355 _eglLog(_EGL_DEBUG, "Create Context for ES version %d\n",
00356 ctx->Base.ClientVersion);
00357
00358 case EGL_OPENGL_API:
00359
00360 ctx->pipe = softpipe_create(xdrv->screen, xdrv->winsys, NULL);
00361
00362 _eglConfigToContextModesRec(conf, &visual);
00363 ctx->Context = st_create_context(ctx->pipe, &visual, share_ctx);
00364 break;
00365 default:
00366 _eglError(EGL_BAD_MATCH, "eglCreateContext(unsupported API)");
00367 free(ctx);
00368 return EGL_NO_CONTEXT;
00369 }
00370
00371 _eglSaveContext(&ctx->Base);
00372
00373 return _eglGetContextHandle(&ctx->Base);
00374 }
00375
00376
00377 static EGLBoolean
00378 xlib_eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx)
00379 {
00380 struct xlib_egl_context *context = lookup_context(ctx);
00381 if (context) {
00382 if (context->Base.IsBound) {
00383 context->Base.DeletePending = EGL_TRUE;
00384 }
00385 else {
00386
00387 switch (context->Base.ClientAPI) {
00388 case EGL_OPENGL_ES_API:
00389
00390 case EGL_OPENGL_API:
00391 st_destroy_context(context->Context);
00392 break;
00393 default:
00394 assert(0);
00395 }
00396 free(context);
00397 }
00398 return EGL_TRUE;
00399 }
00400 else {
00401 _eglError(EGL_BAD_CONTEXT, "eglDestroyContext");
00402 return EGL_TRUE;
00403 }
00404 }
00405
00406
00410 static EGLBoolean
00411 xlib_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy,
00412 EGLSurface draw, EGLSurface read, EGLContext ctx)
00413 {
00414 struct xlib_egl_context *context = lookup_context(ctx);
00415 struct xlib_egl_surface *draw_surf = lookup_surface(draw);
00416 struct xlib_egl_surface *read_surf = lookup_surface(read);
00417
00418 if (!_eglMakeCurrent(drv, dpy, draw, read, context))
00419 return EGL_FALSE;
00420
00421 st_make_current((context ? context->Context : NULL),
00422 (draw_surf ? draw_surf->Framebuffer : NULL),
00423 (read_surf ? read_surf->Framebuffer : NULL));
00424
00425 if (draw_surf)
00426 check_and_update_buffer_size(draw_surf);
00427 if (read_surf && read_surf != draw_surf)
00428 check_and_update_buffer_size(draw_surf);
00429
00430 return EGL_TRUE;
00431 }
00432
00433
00434 static enum pipe_format
00435 choose_color_format(const __GLcontextModes *visual)
00436 {
00437 if (visual->redBits == 8 &&
00438 visual->greenBits == 8 &&
00439 visual->blueBits == 8 &&
00440 visual->alphaBits == 8) {
00441
00442 return PIPE_FORMAT_A8R8G8B8_UNORM;
00443 }
00444 else {
00445 assert(0);
00446 return PIPE_FORMAT_NONE;
00447 }
00448 }
00449
00450
00451 static enum pipe_format
00452 choose_depth_format(const __GLcontextModes *visual)
00453 {
00454 if (visual->depthBits > 0)
00455 return PIPE_FORMAT_S8Z24_UNORM;
00456 else
00457 return PIPE_FORMAT_NONE;
00458 }
00459
00460
00461 static enum pipe_format
00462 choose_stencil_format(const __GLcontextModes *visual)
00463 {
00464 if (visual->stencilBits > 0)
00465 return PIPE_FORMAT_S8Z24_UNORM;
00466 else
00467 return PIPE_FORMAT_NONE;
00468 }
00469
00470
00474 static EGLSurface
00475 xlib_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
00476 NativeWindowType window, const EGLint *attrib_list)
00477 {
00478 struct xlib_egl_driver *xdrv = xlib_egl_driver(drv);
00479 _EGLDisplay *disp = _eglLookupDisplay(dpy);
00480 _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
00481
00482 struct xlib_egl_surface *surf;
00483 __GLcontextModes visual;
00484 uint width, height;
00485
00486 surf = CALLOC_STRUCT(xlib_egl_surface);
00487 if (!surf)
00488 return EGL_NO_SURFACE;
00489
00490
00491 if (!_eglInitSurface(drv, dpy, &surf->Base, EGL_WINDOW_BIT,
00492 config, attrib_list)) {
00493 free(surf);
00494 return EGL_NO_SURFACE;
00495 }
00496
00497 _eglSaveSurface(&surf->Base);
00498
00499
00500
00501
00502 surf->Win = (Window) window;
00503 surf->Dpy = disp->Xdpy;
00504 surf->Gc = XCreateGC(surf->Dpy, surf->Win, 0, NULL);
00505
00506 surf->winsys = xdrv->winsys;
00507
00508 _eglConfigToContextModesRec(conf, &visual);
00509 get_drawable_size(surf->Dpy, surf->Win, &width, &height);
00510 get_drawable_visual_info(surf->Dpy, surf->Win, &surf->VisInfo);
00511
00512 surf->Base.Width = width;
00513 surf->Base.Height = height;
00514
00515
00516 surf->Framebuffer = st_create_framebuffer(&visual,
00517 choose_color_format(&visual),
00518 choose_depth_format(&visual),
00519 choose_stencil_format(&visual),
00520 width, height,
00521 (void *) surf);
00522
00523 st_resize_framebuffer(surf->Framebuffer, width, height);
00524
00525 return _eglGetSurfaceHandle(&surf->Base);
00526 }
00527
00528
00529 static EGLBoolean
00530 xlib_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
00531 {
00532 struct xlib_egl_surface *surf = lookup_surface(surface);
00533 if (surf) {
00534 _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface);
00535 if (surf->Base.IsBound) {
00536 surf->Base.DeletePending = EGL_TRUE;
00537 }
00538 else {
00539 XFreeGC(surf->Dpy, surf->Gc);
00540 st_unreference_framebuffer(&surf->Framebuffer);
00541 free(surf);
00542 }
00543 return EGL_TRUE;
00544 }
00545 else {
00546 _eglError(EGL_BAD_SURFACE, "eglDestroySurface");
00547 return EGL_FALSE;
00548 }
00549 }
00550
00551
00552 static EGLBoolean
00553 xlib_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
00554 {
00555
00556 if (!_eglSwapBuffers(drv, dpy, draw))
00557 return EGL_FALSE;
00558
00559 {
00560 struct xlib_egl_surface *xsurf = lookup_surface(draw);
00561 struct pipe_winsys *pws = xsurf->winsys;
00562 struct pipe_surface *psurf =
00563 st_get_framebuffer_surface(xsurf->Framebuffer, ST_SURFACE_BACK_LEFT);
00564
00565 st_notify_swapbuffers(xsurf->Framebuffer);
00566
00567 display_surface(pws, psurf, xsurf);
00568
00569 check_and_update_buffer_size(xsurf);
00570 }
00571
00572 return EGL_TRUE;
00573 }
00574
00575
00580 static EGLint
00581 find_supported_apis(void)
00582 {
00583 EGLint mask = 0;
00584 void *handle;
00585
00586 handle = dlopen(NULL, 0);
00587
00588 if (dlsym(handle, "st_api_OpenGL_ES1"))
00589 mask |= EGL_OPENGL_ES_BIT;
00590
00591 if (dlsym(handle, "st_api_OpenGL_ES2"))
00592 mask |= EGL_OPENGL_ES2_BIT;
00593
00594 if (dlsym(handle, "st_api_OpenGL"))
00595 mask |= EGL_OPENGL_BIT;
00596
00597 if (dlsym(handle, "st_api_OpenVG"))
00598 mask |= EGL_OPENVG_BIT;
00599
00600 dlclose(handle);
00601
00602 return mask;
00603 }
00604
00605
00610 _EGLDriver *
00611 _eglMain(_EGLDisplay *dpy, const char *args)
00612 {
00613 struct xlib_egl_driver *xdrv;
00614
00615 _eglLog(_EGL_INFO, "Entering EGL/Xlib _eglMain(%s)", args);
00616
00617 xdrv = CALLOC_STRUCT(xlib_egl_driver);
00618 if (!xdrv)
00619 return NULL;
00620
00621 if (!dpy->Xdpy) {
00622 dpy->Xdpy = XOpenDisplay(NULL);
00623 }
00624
00625 _eglInitDriverFallbacks(&xdrv->Base);
00626 xdrv->Base.API.Initialize = xlib_eglInitialize;
00627 xdrv->Base.API.Terminate = xlib_eglTerminate;
00628 xdrv->Base.API.GetProcAddress = xlib_eglGetProcAddress;
00629 xdrv->Base.API.CreateContext = xlib_eglCreateContext;
00630 xdrv->Base.API.DestroyContext = xlib_eglDestroyContext;
00631 xdrv->Base.API.CreateWindowSurface = xlib_eglCreateWindowSurface;
00632 xdrv->Base.API.DestroySurface = xlib_eglDestroySurface;
00633 xdrv->Base.API.MakeCurrent = xlib_eglMakeCurrent;
00634 xdrv->Base.API.SwapBuffers = xlib_eglSwapBuffers;
00635
00636 xdrv->Base.ClientAPIsMask = find_supported_apis();
00637 if (xdrv->Base.ClientAPIsMask == 0x0) {
00638
00639
00640
00641
00642 xdrv->Base.ClientAPIsMask = _eglFindAPIs();
00643 }
00644
00645 xdrv->Base.Name = "Xlib/softpipe";
00646
00647
00648 xdrv->winsys = create_sw_winsys();
00649 xdrv->winsys->flush_frontbuffer = flush_frontbuffer;
00650
00651 xdrv->screen = softpipe_create_screen(xdrv->winsys);
00652
00653 return &xdrv->Base;
00654 }
00655