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