egl_g3d_st.c revision d8e0e114567ec19fd59f974080a418dc959cc9b6
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.9 4 * 5 * Copyright (C) 2010 LunarG Inc. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 * DEALINGS IN THE SOFTWARE. 24 * 25 * Authors: 26 * Chia-I Wu <olv@lunarg.com> 27 */ 28 29#include "util/u_memory.h" 30#include "util/u_string.h" 31#include "util/u_inlines.h" 32#include "util/u_pointer.h" 33#include "util/u_dl.h" 34#include "egldriver.h" 35#include "eglimage.h" 36#include "eglmutex.h" 37 38#include "egl_g3d.h" 39#include "egl_g3d_st.h" 40 41struct egl_g3d_st_manager { 42 struct st_manager base; 43 _EGLDisplay *display; 44}; 45 46static INLINE struct egl_g3d_st_manager * 47egl_g3d_st_manager(struct st_manager *smapi) 48{ 49 return (struct egl_g3d_st_manager *) smapi; 50} 51 52static struct egl_g3d_st_module { 53 const char *filename; 54 struct util_dl_library *lib; 55 struct st_api *stapi; 56} egl_g3d_st_modules[ST_API_COUNT]; 57 58static EGLBoolean 59egl_g3d_search_path_callback(const char *dir, size_t len, void *callback_data) 60{ 61 struct egl_g3d_st_module *stmod = 62 (struct egl_g3d_st_module *) callback_data; 63 char path[1024]; 64 int ret; 65 66 if (!len) { 67 stmod->lib = util_dl_open(stmod->filename); 68 return !(stmod->lib); 69 } 70 71 ret = util_snprintf(path, sizeof(path), 72 "%.*s/%s", len, dir, stmod->filename); 73 if (ret > 0 && ret < sizeof(path)) 74 stmod->lib = util_dl_open(path); 75 76 return !(stmod->lib); 77} 78 79static boolean 80egl_g3d_load_st_module(struct egl_g3d_st_module *stmod, 81 const char *filename, const char *procname) 82{ 83 struct st_api *(*create_api)(void); 84 85 stmod->filename = filename; 86 if (stmod->filename) 87 _eglSearchPathForEach(egl_g3d_search_path_callback, (void *) stmod); 88 else 89 stmod->lib = util_dl_open(NULL); 90 91 if (stmod->lib) { 92 create_api = (struct st_api *(*)(void)) 93 util_dl_get_proc_address(stmod->lib, procname); 94 if (create_api) 95 stmod->stapi = create_api(); 96 97 if (!stmod->stapi) { 98 util_dl_close(stmod->lib); 99 stmod->lib = NULL; 100 } 101 } 102 103 if (stmod->stapi) { 104 return TRUE; 105 } 106 else { 107 stmod->filename = NULL; 108 return FALSE; 109 } 110} 111 112#ifdef PIPE_OS_WINDOWS 113#define ST_MODULE_SUFFIX ".dll" 114#else 115#define ST_MODULE_SUFFIX ".so" 116#endif 117 118void 119egl_g3d_init_st_apis(struct st_api *stapis[ST_API_COUNT]) 120{ 121 const char *skip_checks[ST_API_COUNT], *symbols[ST_API_COUNT]; 122 const char *filenames[ST_API_COUNT][4]; 123 struct util_dl_library *self; 124 int num_needed = 0, api; 125 126 self = util_dl_open(NULL); 127 128 /* collect the necessary data for loading modules */ 129 for (api = 0; api < ST_API_COUNT; api++) { 130 int count = 0; 131 132 switch (api) { 133 case ST_API_OPENGL: 134 skip_checks[api] = "glColor4d"; 135 symbols[api] = ST_CREATE_OPENGL_SYMBOL; 136 filenames[api][count++] = ST_MODULE_PREFIX "GL" ST_MODULE_SUFFIX; 137 break; 138 case ST_API_OPENGL_ES1: 139 skip_checks[api] = "glColor4x"; 140 symbols[api] = ST_CREATE_OPENGL_ES1_SYMBOL; 141 filenames[api][count++] = ST_MODULE_PREFIX "GLESv1_CM" ST_MODULE_SUFFIX; 142 filenames[api][count++] = ST_MODULE_PREFIX "GL" ST_MODULE_SUFFIX; 143 break; 144 case ST_API_OPENGL_ES2: 145 skip_checks[api] = "glShaderBinary"; 146 symbols[api] = ST_CREATE_OPENGL_ES2_SYMBOL; 147 filenames[api][count++] = ST_MODULE_PREFIX "GLESv2" ST_MODULE_SUFFIX; 148 filenames[api][count++] = ST_MODULE_PREFIX "GL" ST_MODULE_SUFFIX; 149 break; 150 case ST_API_OPENVG: 151 skip_checks[api] = "vgClear"; 152 symbols[api] = ST_CREATE_OPENVG_SYMBOL; 153 filenames[api][count++]= ST_MODULE_PREFIX "OpenVG" ST_MODULE_SUFFIX; 154 break; 155 default: 156 assert(!"Unknown API Type\n"); 157 skip_checks[api] = NULL; 158 symbols[api] = NULL; 159 break; 160 } 161 filenames[api][count++]= NULL; 162 assert(count < Elements(filenames[api])); 163 164 /* heuristicically decide if the module is needed */ 165 if (!self || !skip_checks[api] || 166 util_dl_get_proc_address(self, skip_checks[api])) { 167 /* unset so the module is not skipped */ 168 skip_checks[api] = NULL; 169 num_needed++; 170 } 171 } 172 /* mark all moudles needed if we wrongly decided that none is needed */ 173 if (!num_needed) 174 memset(skip_checks, 0, sizeof(skip_checks)); 175 176 if (self) 177 util_dl_close(self); 178 179 for (api = 0; api < ST_API_COUNT; api++) { 180 struct egl_g3d_st_module *stmod = &egl_g3d_st_modules[api]; 181 const char **p; 182 183 /* skip the module */ 184 if (skip_checks[api]) 185 continue; 186 187 /* try all filenames, including NULL */ 188 for (p = filenames[api]; *p; p++) { 189 if (egl_g3d_load_st_module(stmod, *p, symbols[api])) 190 break; 191 } 192 if (!stmod->stapi) 193 egl_g3d_load_st_module(stmod, NULL, symbols[api]); 194 195 stapis[api] = stmod->stapi; 196 } 197} 198 199void 200egl_g3d_destroy_st_apis(void) 201{ 202 int api; 203 204 for (api = 0; api < ST_API_COUNT; api++) { 205 struct egl_g3d_st_module *stmod = &egl_g3d_st_modules[api]; 206 207 if (stmod->stapi) { 208 stmod->stapi->destroy(stmod->stapi); 209 stmod->stapi = NULL; 210 } 211 if (stmod->lib) { 212 util_dl_close(stmod->lib); 213 stmod->lib = NULL; 214 } 215 stmod->filename = NULL; 216 } 217} 218 219static boolean 220egl_g3d_st_manager_get_egl_image(struct st_manager *smapi, 221 struct st_context_iface *stctx, 222 void *egl_image, 223 struct st_egl_image *out) 224{ 225 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); 226 EGLImageKHR handle = (EGLImageKHR) egl_image; 227 _EGLImage *img; 228 struct egl_g3d_image *gimg; 229 230 /* this is called from state trackers */ 231 _eglLockMutex(&gsmapi->display->Mutex); 232 233 img = _eglLookupImage(handle, gsmapi->display); 234 if (!img) { 235 _eglUnlockMutex(&gsmapi->display->Mutex); 236 return FALSE; 237 } 238 239 gimg = egl_g3d_image(img); 240 241 out->texture = NULL; 242 pipe_resource_reference(&out->texture, gimg->texture); 243 out->face = gimg->face; 244 out->level = gimg->level; 245 out->zslice = gimg->zslice; 246 247 _eglUnlockMutex(&gsmapi->display->Mutex); 248 249 return TRUE; 250} 251 252static int 253egl_g3d_st_manager_get_param(struct st_manager *smapi, 254 enum st_manager_param param) 255{ 256 return 0; 257} 258 259struct st_manager * 260egl_g3d_create_st_manager(_EGLDisplay *dpy) 261{ 262 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 263 struct egl_g3d_st_manager *gsmapi; 264 265 gsmapi = CALLOC_STRUCT(egl_g3d_st_manager); 266 if (gsmapi) { 267 gsmapi->display = dpy; 268 269 gsmapi->base.screen = gdpy->native->screen; 270 gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image; 271 gsmapi->base.get_param = egl_g3d_st_manager_get_param; 272 } 273 274 return &gsmapi->base;; 275} 276 277void 278egl_g3d_destroy_st_manager(struct st_manager *smapi) 279{ 280 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); 281 FREE(gsmapi); 282} 283 284static boolean 285egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi, 286 enum st_attachment_type statt) 287{ 288 return TRUE; 289} 290 291static void 292pbuffer_reference_openvg_image(struct egl_g3d_surface *gsurf) 293{ 294 /* TODO */ 295} 296 297static void 298pbuffer_allocate_render_texture(struct egl_g3d_surface *gsurf) 299{ 300 struct egl_g3d_display *gdpy = 301 egl_g3d_display(gsurf->base.Resource.Display); 302 struct pipe_screen *screen = gdpy->native->screen; 303 struct pipe_resource templ, *ptex; 304 305 memset(&templ, 0, sizeof(templ)); 306 templ.target = PIPE_TEXTURE_2D; 307 templ.last_level = 0; 308 templ.width0 = gsurf->base.Width; 309 templ.height0 = gsurf->base.Height; 310 templ.depth0 = 1; 311 templ.format = gsurf->stvis.color_format; 312 templ.bind = PIPE_BIND_RENDER_TARGET; 313 314 ptex = screen->resource_create(screen, &templ); 315 gsurf->render_texture = ptex; 316} 317 318static boolean 319egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface *stfbi, 320 const enum st_attachment_type *statts, 321 unsigned count, 322 struct pipe_resource **out) 323{ 324 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; 325 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 326 unsigned i; 327 328 for (i = 0; i < count; i++) { 329 out[i] = NULL; 330 331 if (gsurf->stvis.render_buffer != statts[i]) 332 continue; 333 334 if (!gsurf->render_texture) { 335 switch (gsurf->client_buffer_type) { 336 case EGL_NONE: 337 pbuffer_allocate_render_texture(gsurf); 338 break; 339 case EGL_OPENVG_IMAGE: 340 pbuffer_reference_openvg_image(gsurf); 341 break; 342 default: 343 break; 344 } 345 346 if (!gsurf->render_texture) 347 return FALSE; 348 } 349 350 pipe_resource_reference(&out[i], gsurf->render_texture); 351 } 352 353 return TRUE; 354} 355 356static boolean 357egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, 358 enum st_attachment_type statt) 359{ 360 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; 361 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 362 363 return gsurf->native->flush_frontbuffer(gsurf->native); 364} 365 366static boolean 367egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, 368 const enum st_attachment_type *statts, 369 unsigned count, 370 struct pipe_resource **out) 371{ 372 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; 373 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 374 struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; 375 uint attachment_mask = 0; 376 unsigned i; 377 378 for (i = 0; i < count; i++) { 379 int natt; 380 381 switch (statts[i]) { 382 case ST_ATTACHMENT_FRONT_LEFT: 383 natt = NATIVE_ATTACHMENT_FRONT_LEFT; 384 break; 385 case ST_ATTACHMENT_BACK_LEFT: 386 natt = NATIVE_ATTACHMENT_BACK_LEFT; 387 break; 388 case ST_ATTACHMENT_FRONT_RIGHT: 389 natt = NATIVE_ATTACHMENT_FRONT_RIGHT; 390 break; 391 case ST_ATTACHMENT_BACK_RIGHT: 392 natt = NATIVE_ATTACHMENT_BACK_RIGHT; 393 break; 394 default: 395 natt = -1; 396 break; 397 } 398 399 if (natt >= 0) 400 attachment_mask |= 1 << natt; 401 } 402 403 if (!gsurf->native->validate(gsurf->native, attachment_mask, 404 &gsurf->sequence_number, textures, &gsurf->base.Width, 405 &gsurf->base.Height)) 406 return FALSE; 407 408 for (i = 0; i < count; i++) { 409 struct pipe_resource *tex; 410 int natt; 411 412 switch (statts[i]) { 413 case ST_ATTACHMENT_FRONT_LEFT: 414 natt = NATIVE_ATTACHMENT_FRONT_LEFT; 415 break; 416 case ST_ATTACHMENT_BACK_LEFT: 417 natt = NATIVE_ATTACHMENT_BACK_LEFT; 418 break; 419 case ST_ATTACHMENT_FRONT_RIGHT: 420 natt = NATIVE_ATTACHMENT_FRONT_RIGHT; 421 break; 422 case ST_ATTACHMENT_BACK_RIGHT: 423 natt = NATIVE_ATTACHMENT_BACK_RIGHT; 424 break; 425 default: 426 natt = -1; 427 break; 428 } 429 430 if (natt >= 0) { 431 tex = textures[natt]; 432 433 if (statts[i] == stfbi->visual->render_buffer) 434 pipe_resource_reference(&gsurf->render_texture, tex); 435 436 if (attachment_mask & (1 << natt)) { 437 /* transfer the ownership to the caller */ 438 out[i] = tex; 439 attachment_mask &= ~(1 << natt); 440 } 441 else { 442 /* the attachment is listed more than once */ 443 pipe_resource_reference(&out[i], tex); 444 } 445 } 446 } 447 448 return TRUE; 449} 450 451struct st_framebuffer_iface * 452egl_g3d_create_st_framebuffer(_EGLSurface *surf) 453{ 454 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 455 struct st_framebuffer_iface *stfbi; 456 457 stfbi = CALLOC_STRUCT(st_framebuffer_iface); 458 if (!stfbi) 459 return NULL; 460 461 stfbi->visual = &gsurf->stvis; 462 if (gsurf->base.Type != EGL_PBUFFER_BIT) { 463 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front; 464 stfbi->validate = egl_g3d_st_framebuffer_validate; 465 } 466 else { 467 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer; 468 stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer; 469 } 470 stfbi->st_manager_private = (void *) &gsurf->base; 471 472 return stfbi; 473} 474 475void 476egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) 477{ 478 FREE(stfbi); 479} 480