egl_g3d_st.c revision a5183a38c293249dad36a7230ff872ea7485eee0
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_format.h" 34#include "util/u_dl.h" 35#include "egldriver.h" 36#include "eglimage.h" 37#include "eglmutex.h" 38 39#include "egl_g3d.h" 40#include "egl_g3d_st.h" 41 42struct egl_g3d_st_manager { 43 struct st_manager base; 44 _EGLDisplay *display; 45}; 46 47static INLINE struct egl_g3d_st_manager * 48egl_g3d_st_manager(struct st_manager *smapi) 49{ 50 return (struct egl_g3d_st_manager *) smapi; 51} 52 53static struct egl_g3d_st_module { 54 const char *filename; 55 struct util_dl_library *lib; 56 struct st_api *stapi; 57} egl_g3d_st_modules[ST_API_COUNT]; 58 59static EGLBoolean 60egl_g3d_search_path_callback(const char *dir, size_t len, void *callback_data) 61{ 62 struct egl_g3d_st_module *stmod = 63 (struct egl_g3d_st_module *) callback_data; 64 char path[1024]; 65 int ret; 66 67 ret = util_snprintf(path, sizeof(path), 68 "%.*s/%s", len, dir, stmod->filename); 69 if (ret > 0 && ret < sizeof(path)) 70 stmod->lib = util_dl_open(path); 71 72 return !(stmod->lib); 73} 74 75static boolean 76egl_g3d_load_st_module(struct egl_g3d_st_module *stmod, 77 const char *filename, const char *procname) 78{ 79 struct st_api *(*create_api)(void); 80 81 stmod->filename = filename; 82 if (stmod->filename) 83 _eglSearchPathForEach(egl_g3d_search_path_callback, (void *) stmod); 84 else 85 stmod->lib = util_dl_open(NULL); 86 87 if (stmod->lib) { 88 create_api = (struct st_api *(*)(void)) 89 util_dl_get_proc_address(stmod->lib, procname); 90 if (create_api) 91 stmod->stapi = create_api(); 92 93 if (!stmod->stapi) { 94 util_dl_close(stmod->lib); 95 stmod->lib = NULL; 96 } 97 } 98 99 if (stmod->stapi) { 100 return TRUE; 101 } 102 else { 103 stmod->filename = NULL; 104 return FALSE; 105 } 106} 107 108void 109egl_g3d_init_st_apis(struct st_api *stapis[ST_API_COUNT]) 110{ 111 const char *skip_checks[ST_API_COUNT], *symbols[ST_API_COUNT]; 112 const char *filenames[ST_API_COUNT][4]; 113 struct util_dl_library *self; 114 int num_needed = 0, api; 115 116 self = util_dl_open(NULL); 117 118 /* collect the necessary data for loading modules */ 119 for (api = 0; api < ST_API_COUNT; api++) { 120 int count = 0; 121 122 switch (api) { 123 case ST_API_OPENGL: 124 skip_checks[api] = "glColor4d"; 125 symbols[api] = ST_CREATE_OPENGL_SYMBOL; 126 filenames[api][count++] = "api_GL.so"; 127 break; 128 case ST_API_OPENGL_ES1: 129 skip_checks[api] = "glColor4x"; 130 symbols[api] = ST_CREATE_OPENGL_ES1_SYMBOL; 131 filenames[api][count++] = "api_GLESv1_CM.so"; 132 filenames[api][count++] = "api_GL.so"; 133 break; 134 case ST_API_OPENGL_ES2: 135 skip_checks[api] = "glShaderBinary"; 136 symbols[api] = ST_CREATE_OPENGL_ES2_SYMBOL; 137 filenames[api][count++] = "api_GLESv2.so"; 138 filenames[api][count++] = "api_GL.so"; 139 break; 140 case ST_API_OPENVG: 141 skip_checks[api] = "vgClear"; 142 symbols[api] = ST_CREATE_OPENVG_SYMBOL; 143 filenames[api][count++]= "api_OpenVG.so"; 144 break; 145 default: 146 assert(!"Unknown API Type\n"); 147 skip_checks[api] = NULL; 148 symbols[api] = NULL; 149 break; 150 } 151 filenames[api][count++]= NULL; 152 assert(count < Elements(filenames[api])); 153 154 /* heuristicically decide if the module is needed */ 155 if (!self || !skip_checks[api] || 156 util_dl_get_proc_address(self, skip_checks[api])) { 157 /* unset so the module is not skipped */ 158 skip_checks[api] = NULL; 159 num_needed++; 160 } 161 } 162 /* mark all moudles needed if we wrongly decided that none is needed */ 163 if (!num_needed) 164 memset(skip_checks, 0, sizeof(skip_checks)); 165 166 if (self) 167 util_dl_close(self); 168 169 for (api = 0; api < ST_API_COUNT; api++) { 170 struct egl_g3d_st_module *stmod = &egl_g3d_st_modules[api]; 171 const char **p; 172 173 /* skip the module */ 174 if (skip_checks[api]) 175 continue; 176 177 /* try all filenames, including NULL */ 178 for (p = filenames[api]; *p; p++) { 179 if (egl_g3d_load_st_module(stmod, *p, symbols[api])) 180 break; 181 } 182 if (!stmod->stapi) 183 egl_g3d_load_st_module(stmod, NULL, symbols[api]); 184 185 stapis[api] = stmod->stapi; 186 } 187} 188 189void 190egl_g3d_destroy_st_apis(void) 191{ 192 int api; 193 194 for (api = 0; api < ST_API_COUNT; api++) { 195 struct egl_g3d_st_module *stmod = &egl_g3d_st_modules[api]; 196 197 if (stmod->stapi) { 198 stmod->stapi->destroy(stmod->stapi); 199 stmod->stapi = NULL; 200 } 201 if (stmod->lib) { 202 util_dl_close(stmod->lib); 203 stmod->lib = NULL; 204 } 205 stmod->filename = NULL; 206 } 207} 208 209static boolean 210egl_g3d_st_manager_get_egl_image(struct st_manager *smapi, 211 struct st_context_iface *stctx, 212 void *egl_image, 213 struct st_egl_image *out) 214{ 215 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); 216 EGLImageKHR handle = (EGLImageKHR) egl_image; 217 _EGLImage *img; 218 struct egl_g3d_image *gimg; 219 220 /* this is called from state trackers */ 221 _eglLockMutex(&gsmapi->display->Mutex); 222 223 img = _eglLookupImage(handle, gsmapi->display); 224 if (!img) { 225 _eglUnlockMutex(&gsmapi->display->Mutex); 226 return FALSE; 227 } 228 229 gimg = egl_g3d_image(img); 230 231 out->texture = NULL; 232 pipe_resource_reference(&out->texture, gimg->texture); 233 out->face = gimg->face; 234 out->level = gimg->level; 235 out->zslice = gimg->zslice; 236 237 _eglUnlockMutex(&gsmapi->display->Mutex); 238 239 return TRUE; 240} 241 242static int 243egl_g3d_st_manager_get_param(struct st_manager *smapi, 244 enum st_manager_param param) 245{ 246 return 0; 247} 248 249struct st_manager * 250egl_g3d_create_st_manager(_EGLDisplay *dpy) 251{ 252 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 253 struct egl_g3d_st_manager *gsmapi; 254 255 gsmapi = CALLOC_STRUCT(egl_g3d_st_manager); 256 if (gsmapi) { 257 gsmapi->display = dpy; 258 259 gsmapi->base.screen = gdpy->native->screen; 260 gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image; 261 gsmapi->base.get_param = egl_g3d_st_manager_get_param; 262 } 263 264 return &gsmapi->base;; 265} 266 267void 268egl_g3d_destroy_st_manager(struct st_manager *smapi) 269{ 270 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); 271 FREE(gsmapi); 272} 273 274static boolean 275egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi, 276 enum st_attachment_type statt) 277{ 278 return TRUE; 279} 280 281static void 282pbuffer_reference_openvg_image(struct egl_g3d_surface *gsurf) 283{ 284 /* TODO */ 285} 286 287static void 288pbuffer_allocate_render_texture(struct egl_g3d_surface *gsurf) 289{ 290 struct egl_g3d_display *gdpy = 291 egl_g3d_display(gsurf->base.Resource.Display); 292 struct pipe_screen *screen = gdpy->native->screen; 293 struct pipe_resource templ, *ptex; 294 295 memset(&templ, 0, sizeof(templ)); 296 templ.target = PIPE_TEXTURE_2D; 297 templ.last_level = 0; 298 templ.width0 = gsurf->base.Width; 299 templ.height0 = gsurf->base.Height; 300 templ.depth0 = 1; 301 templ.format = gsurf->stvis.color_format; 302 templ.bind = PIPE_BIND_RENDER_TARGET; 303 304 ptex = screen->resource_create(screen, &templ); 305 gsurf->render_texture = ptex; 306} 307 308static boolean 309egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface *stfbi, 310 const enum st_attachment_type *statts, 311 unsigned count, 312 struct pipe_resource **out) 313{ 314 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; 315 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 316 unsigned i; 317 318 for (i = 0; i < count; i++) { 319 out[i] = NULL; 320 321 if (gsurf->stvis.render_buffer != statts[i]) 322 continue; 323 324 if (!gsurf->render_texture) { 325 switch (gsurf->client_buffer_type) { 326 case EGL_NONE: 327 pbuffer_allocate_render_texture(gsurf); 328 break; 329 case EGL_OPENVG_IMAGE: 330 pbuffer_reference_openvg_image(gsurf); 331 break; 332 default: 333 break; 334 } 335 336 if (!gsurf->render_texture) 337 return FALSE; 338 } 339 340 pipe_resource_reference(&out[i], gsurf->render_texture); 341 } 342 343 return TRUE; 344} 345 346static boolean 347egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, 348 enum st_attachment_type statt) 349{ 350 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; 351 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 352 353 return gsurf->native->flush_frontbuffer(gsurf->native); 354} 355 356static boolean 357egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, 358 const enum st_attachment_type *statts, 359 unsigned count, 360 struct pipe_resource **out) 361{ 362 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; 363 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 364 struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; 365 uint attachment_mask = 0; 366 unsigned i; 367 368 for (i = 0; i < count; i++) { 369 int natt; 370 371 switch (statts[i]) { 372 case ST_ATTACHMENT_FRONT_LEFT: 373 natt = NATIVE_ATTACHMENT_FRONT_LEFT; 374 break; 375 case ST_ATTACHMENT_BACK_LEFT: 376 natt = NATIVE_ATTACHMENT_BACK_LEFT; 377 break; 378 case ST_ATTACHMENT_FRONT_RIGHT: 379 natt = NATIVE_ATTACHMENT_FRONT_RIGHT; 380 break; 381 case ST_ATTACHMENT_BACK_RIGHT: 382 natt = NATIVE_ATTACHMENT_BACK_RIGHT; 383 break; 384 default: 385 natt = -1; 386 break; 387 } 388 389 if (natt >= 0) 390 attachment_mask |= 1 << natt; 391 } 392 393 if (!gsurf->native->validate(gsurf->native, attachment_mask, 394 &gsurf->sequence_number, textures, &gsurf->base.Width, 395 &gsurf->base.Height)) 396 return FALSE; 397 398 for (i = 0; i < count; i++) { 399 struct pipe_resource *tex; 400 int natt; 401 402 switch (statts[i]) { 403 case ST_ATTACHMENT_FRONT_LEFT: 404 natt = NATIVE_ATTACHMENT_FRONT_LEFT; 405 break; 406 case ST_ATTACHMENT_BACK_LEFT: 407 natt = NATIVE_ATTACHMENT_BACK_LEFT; 408 break; 409 case ST_ATTACHMENT_FRONT_RIGHT: 410 natt = NATIVE_ATTACHMENT_FRONT_RIGHT; 411 break; 412 case ST_ATTACHMENT_BACK_RIGHT: 413 natt = NATIVE_ATTACHMENT_BACK_RIGHT; 414 break; 415 default: 416 natt = -1; 417 break; 418 } 419 420 if (natt >= 0) { 421 tex = textures[natt]; 422 423 if (statts[i] == stfbi->visual->render_buffer) 424 pipe_resource_reference(&gsurf->render_texture, tex); 425 426 if (attachment_mask & (1 << natt)) { 427 /* transfer the ownership to the caller */ 428 out[i] = tex; 429 attachment_mask &= ~(1 << natt); 430 } 431 else { 432 /* the attachment is listed more than once */ 433 pipe_resource_reference(&out[i], tex); 434 } 435 } 436 } 437 438 return TRUE; 439} 440 441struct st_framebuffer_iface * 442egl_g3d_create_st_framebuffer(_EGLSurface *surf) 443{ 444 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 445 struct st_framebuffer_iface *stfbi; 446 447 stfbi = CALLOC_STRUCT(st_framebuffer_iface); 448 if (!stfbi) 449 return NULL; 450 451 stfbi->visual = &gsurf->stvis; 452 if (gsurf->base.Type != EGL_PBUFFER_BIT) { 453 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front; 454 stfbi->validate = egl_g3d_st_framebuffer_validate; 455 } 456 else { 457 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer; 458 stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer; 459 } 460 stfbi->st_manager_private = (void *) &gsurf->base; 461 462 return stfbi; 463} 464 465void 466egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) 467{ 468 FREE(stfbi); 469} 470