egl_g3d_st.c revision 0c572c6828b6a338b07a6860280b3a314a81662e
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_inlines.h" 31#include "util/u_dl.h" 32#include "eglimage.h" 33#include "eglmutex.h" 34 35#include "egl_g3d.h" 36#include "egl_g3d_st.h" 37 38struct egl_g3d_st_manager { 39 struct st_manager base; 40 _EGLDisplay *display; 41}; 42 43static INLINE struct egl_g3d_st_manager * 44egl_g3d_st_manager(struct st_manager *smapi) 45{ 46 return (struct egl_g3d_st_manager *) smapi; 47} 48 49struct st_api * 50egl_g3d_create_st_api(enum st_api_type api) 51{ 52 struct util_dl_library *lib; 53 const char *proc_name; 54 struct st_api * (*proc)(void) = NULL; 55 56 switch (api) { 57 case ST_API_OPENGL: 58 proc_name = ST_CREATE_OPENGL_SYMBOL; 59 break; 60 case ST_API_OPENGL_ES1: 61 proc_name = ST_CREATE_OPENGL_ES1_SYMBOL; 62 break; 63 case ST_API_OPENGL_ES2: 64 proc_name = ST_CREATE_OPENGL_ES2_SYMBOL; 65 break; 66 case ST_API_OPENVG: 67 proc_name = ST_CREATE_OPENVG_SYMBOL; 68 break; 69 default: 70 assert(!"Unknown API Type\n"); 71 return NULL; 72 } 73 74 if (!proc_name) 75 return NULL; 76 77 lib = util_dl_open(NULL); 78 if (lib) { 79 proc = util_dl_get_proc_address(lib, proc_name); 80 debug_printf("%s: %s %p\n", __func__, proc_name, proc); 81 util_dl_close(lib); 82 } 83 84 if (!proc) 85 return NULL; 86 87 return proc(); 88} 89 90static boolean 91egl_g3d_st_manager_get_egl_image(struct st_manager *smapi, 92 struct st_egl_image *stimg) 93{ 94 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); 95 EGLImageKHR handle = (EGLImageKHR) stimg->egl_image; 96 _EGLImage *img; 97 struct egl_g3d_image *gimg; 98 99 /* this is called from state trackers */ 100 _eglLockMutex(&gsmapi->display->Mutex); 101 102 img = _eglLookupImage(handle, gsmapi->display); 103 if (!img) { 104 _eglUnlockMutex(&gsmapi->display->Mutex); 105 return FALSE; 106 } 107 108 gimg = egl_g3d_image(img); 109 110 stimg->texture = NULL; 111 pipe_resource_reference(&stimg->texture, gimg->texture); 112 stimg->face = gimg->face; 113 stimg->level = gimg->level; 114 stimg->zslice = gimg->zslice; 115 116 _eglUnlockMutex(&gsmapi->display->Mutex); 117 118 return TRUE; 119} 120 121struct st_manager * 122egl_g3d_create_st_manager(_EGLDisplay *dpy) 123{ 124 struct egl_g3d_display *gdpy = egl_g3d_display(dpy); 125 struct egl_g3d_st_manager *gsmapi; 126 127 gsmapi = CALLOC_STRUCT(egl_g3d_st_manager); 128 if (gsmapi) { 129 gsmapi->display = dpy; 130 131 gsmapi->base.screen = gdpy->native->screen; 132 gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image; 133 } 134 135 return &gsmapi->base;; 136} 137 138void 139egl_g3d_destroy_st_manager(struct st_manager *smapi) 140{ 141 struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); 142 FREE(gsmapi); 143} 144 145static boolean 146egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi, 147 enum st_attachment_type statt) 148{ 149 return TRUE; 150} 151 152static boolean 153egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface *stfbi, 154 const enum st_attachment_type *statts, 155 unsigned count, 156 struct pipe_resource **out) 157{ 158 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; 159 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 160 struct pipe_resource templ; 161 unsigned i; 162 163 for (i = 0; i < count; i++) { 164 out[i] = NULL; 165 166 if (gsurf->stvis.render_buffer != statts[i]) 167 continue; 168 169 if (!gsurf->render_texture) { 170 struct egl_g3d_display *gdpy = 171 egl_g3d_display(gsurf->base.Resource.Display); 172 struct pipe_screen *screen = gdpy->native->screen; 173 174 memset(&templ, 0, sizeof(templ)); 175 templ.target = PIPE_TEXTURE_2D; 176 templ.last_level = 0; 177 templ.width0 = gsurf->base.Width; 178 templ.height0 = gsurf->base.Height; 179 templ.depth0 = 1; 180 templ.format = gsurf->stvis.color_format; 181 templ.bind = PIPE_BIND_RENDER_TARGET; 182 183 gsurf->render_texture = screen->resource_create(screen, &templ); 184 } 185 186 pipe_resource_reference(&out[i], gsurf->render_texture); 187 } 188 189 return TRUE; 190} 191 192static boolean 193egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, 194 enum st_attachment_type statt) 195{ 196 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; 197 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 198 199 return gsurf->native->flush_frontbuffer(gsurf->native); 200} 201 202static boolean 203egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, 204 const enum st_attachment_type *statts, 205 unsigned count, 206 struct pipe_resource **out) 207{ 208 _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; 209 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 210 struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; 211 uint attachment_mask = 0; 212 unsigned i; 213 214 for (i = 0; i < count; i++) { 215 int natt; 216 217 switch (statts[i]) { 218 case ST_ATTACHMENT_FRONT_LEFT: 219 natt = NATIVE_ATTACHMENT_FRONT_LEFT; 220 break; 221 case ST_ATTACHMENT_BACK_LEFT: 222 natt = NATIVE_ATTACHMENT_BACK_LEFT; 223 break; 224 case ST_ATTACHMENT_FRONT_RIGHT: 225 natt = NATIVE_ATTACHMENT_FRONT_RIGHT; 226 break; 227 case ST_ATTACHMENT_BACK_RIGHT: 228 natt = NATIVE_ATTACHMENT_BACK_RIGHT; 229 break; 230 default: 231 natt = -1; 232 break; 233 } 234 235 if (natt >= 0) 236 attachment_mask |= 1 << natt; 237 } 238 239 if (!gsurf->native->validate(gsurf->native, attachment_mask, 240 &gsurf->sequence_number, textures, &gsurf->base.Width, 241 &gsurf->base.Height)) 242 return FALSE; 243 244 for (i = 0; i < count; i++) { 245 struct pipe_resource *tex; 246 int natt; 247 248 switch (statts[i]) { 249 case ST_ATTACHMENT_FRONT_LEFT: 250 natt = NATIVE_ATTACHMENT_FRONT_LEFT; 251 break; 252 case ST_ATTACHMENT_BACK_LEFT: 253 natt = NATIVE_ATTACHMENT_BACK_LEFT; 254 break; 255 case ST_ATTACHMENT_FRONT_RIGHT: 256 natt = NATIVE_ATTACHMENT_FRONT_RIGHT; 257 break; 258 case ST_ATTACHMENT_BACK_RIGHT: 259 natt = NATIVE_ATTACHMENT_BACK_RIGHT; 260 break; 261 default: 262 natt = -1; 263 break; 264 } 265 266 if (natt >= 0) { 267 tex = textures[natt]; 268 269 if (statts[i] == stfbi->visual->render_buffer) 270 pipe_resource_reference(&gsurf->render_texture, tex); 271 272 if (attachment_mask & (1 << natt)) { 273 /* transfer the ownership to the caller */ 274 out[i] = tex; 275 attachment_mask &= ~(1 << natt); 276 } 277 else { 278 /* the attachment is listed more than once */ 279 pipe_resource_reference(&out[i], tex); 280 } 281 } 282 } 283 284 return TRUE; 285} 286 287struct st_framebuffer_iface * 288egl_g3d_create_st_framebuffer(_EGLSurface *surf) 289{ 290 struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); 291 struct st_framebuffer_iface *stfbi; 292 293 stfbi = CALLOC_STRUCT(st_framebuffer_iface); 294 if (!stfbi) 295 return NULL; 296 297 stfbi->visual = &gsurf->stvis; 298 if (gsurf->base.Type != EGL_PBUFFER_BIT) { 299 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front; 300 stfbi->validate = egl_g3d_st_framebuffer_validate; 301 } 302 else { 303 stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer; 304 stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer; 305 } 306 stfbi->st_manager_private = (void *) &gsurf->base; 307 308 return stfbi; 309} 310 311void 312egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) 313{ 314 FREE(stfbi); 315} 316