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