/* * Mesa 3-D graphics library * Version: 7.9 * * Copyright (C) 2010 LunarG Inc. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * * Authors: * Chia-I Wu */ #include "util/u_memory.h" #include "util/u_string.h" #include "util/u_inlines.h" #include "util/u_pointer.h" #include "util/u_dl.h" #include "egldriver.h" #include "eglimage.h" #include "eglmutex.h" #include "egl_g3d.h" #include "egl_g3d_st.h" struct egl_g3d_st_manager { struct st_manager base; _EGLDisplay *display; }; static INLINE struct egl_g3d_st_manager * egl_g3d_st_manager(struct st_manager *smapi) { return (struct egl_g3d_st_manager *) smapi; } static boolean egl_g3d_st_manager_get_egl_image(struct st_manager *smapi, void *egl_image, struct st_egl_image *out) { struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); EGLImageKHR handle = (EGLImageKHR) egl_image; _EGLImage *img; struct egl_g3d_image *gimg; /* this is called from state trackers */ _eglLockMutex(&gsmapi->display->Mutex); img = _eglLookupImage(handle, gsmapi->display); if (!img) { _eglUnlockMutex(&gsmapi->display->Mutex); return FALSE; } gimg = egl_g3d_image(img); out->texture = NULL; pipe_resource_reference(&out->texture, gimg->texture); out->level = gimg->level; out->layer = gimg->layer; _eglUnlockMutex(&gsmapi->display->Mutex); return TRUE; } static int egl_g3d_st_manager_get_param(struct st_manager *smapi, enum st_manager_param param) { return 0; } struct st_manager * egl_g3d_create_st_manager(_EGLDisplay *dpy) { struct egl_g3d_display *gdpy = egl_g3d_display(dpy); struct egl_g3d_st_manager *gsmapi; gsmapi = CALLOC_STRUCT(egl_g3d_st_manager); if (gsmapi) { gsmapi->display = dpy; gsmapi->base.screen = gdpy->native->screen; gsmapi->base.get_egl_image = egl_g3d_st_manager_get_egl_image; gsmapi->base.get_param = egl_g3d_st_manager_get_param; } return &gsmapi->base;; } void egl_g3d_destroy_st_manager(struct st_manager *smapi) { struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); FREE(gsmapi); } static boolean egl_g3d_st_framebuffer_flush_front_pbuffer(struct st_framebuffer_iface *stfbi, enum st_attachment_type statt) { return TRUE; } static void pbuffer_reference_openvg_image(struct egl_g3d_surface *gsurf) { /* TODO */ } static void pbuffer_allocate_pbuffer_texture(struct egl_g3d_surface *gsurf) { struct egl_g3d_display *gdpy = egl_g3d_display(gsurf->base.Resource.Display); struct pipe_screen *screen = gdpy->native->screen; struct pipe_resource templ, *ptex; memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_2D; templ.last_level = 0; templ.width0 = gsurf->base.Width; templ.height0 = gsurf->base.Height; templ.depth0 = 1; templ.array_size = 1; templ.format = gsurf->stvis.color_format; /* for rendering and binding to texture */ templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; ptex = screen->resource_create(screen, &templ); gsurf->render_texture = ptex; } static boolean egl_g3d_st_framebuffer_validate_pbuffer(struct st_framebuffer_iface *stfbi, const enum st_attachment_type *statts, unsigned count, struct pipe_resource **out) { _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); unsigned i; for (i = 0; i < count; i++) { out[i] = NULL; if (gsurf->stvis.render_buffer != statts[i]) continue; if (!gsurf->render_texture) { switch (gsurf->client_buffer_type) { case EGL_NONE: pbuffer_allocate_pbuffer_texture(gsurf); break; case EGL_OPENVG_IMAGE: pbuffer_reference_openvg_image(gsurf); break; default: break; } if (!gsurf->render_texture) return FALSE; } pipe_resource_reference(&out[i], gsurf->render_texture); } return TRUE; } static boolean egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, enum st_attachment_type statt) { _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); struct native_present_control ctrl; memset(&ctrl, 0, sizeof(ctrl)); ctrl.natt = NATIVE_ATTACHMENT_FRONT_LEFT; return gsurf->native->present(gsurf->native, &ctrl); } static boolean egl_g3d_st_framebuffer_validate(struct st_framebuffer_iface *stfbi, const enum st_attachment_type *statts, unsigned count, struct pipe_resource **out) { _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; uint attachment_mask = 0; unsigned i; for (i = 0; i < count; i++) { int natt; switch (statts[i]) { case ST_ATTACHMENT_FRONT_LEFT: natt = NATIVE_ATTACHMENT_FRONT_LEFT; break; case ST_ATTACHMENT_BACK_LEFT: natt = NATIVE_ATTACHMENT_BACK_LEFT; break; case ST_ATTACHMENT_FRONT_RIGHT: natt = NATIVE_ATTACHMENT_FRONT_RIGHT; break; case ST_ATTACHMENT_BACK_RIGHT: natt = NATIVE_ATTACHMENT_BACK_RIGHT; break; default: natt = -1; break; } if (natt >= 0) attachment_mask |= 1 << natt; } if (!gsurf->native->validate(gsurf->native, attachment_mask, &gsurf->sequence_number, textures, &gsurf->base.Width, &gsurf->base.Height)) return FALSE; for (i = 0; i < count; i++) { struct pipe_resource *tex; int natt; switch (statts[i]) { case ST_ATTACHMENT_FRONT_LEFT: natt = NATIVE_ATTACHMENT_FRONT_LEFT; break; case ST_ATTACHMENT_BACK_LEFT: natt = NATIVE_ATTACHMENT_BACK_LEFT; break; case ST_ATTACHMENT_FRONT_RIGHT: natt = NATIVE_ATTACHMENT_FRONT_RIGHT; break; case ST_ATTACHMENT_BACK_RIGHT: natt = NATIVE_ATTACHMENT_BACK_RIGHT; break; default: natt = -1; break; } if (natt >= 0) { tex = textures[natt]; if (statts[i] == stfbi->visual->render_buffer) pipe_resource_reference(&gsurf->render_texture, tex); if (attachment_mask & (1 << natt)) { /* transfer the ownership to the caller */ out[i] = tex; attachment_mask &= ~(1 << natt); } else { /* the attachment is listed more than once */ pipe_resource_reference(&out[i], tex); } } } return TRUE; } struct st_framebuffer_iface * egl_g3d_create_st_framebuffer(_EGLSurface *surf) { struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); struct st_framebuffer_iface *stfbi; stfbi = CALLOC_STRUCT(st_framebuffer_iface); if (!stfbi) return NULL; stfbi->visual = &gsurf->stvis; p_atomic_set(&stfbi->stamp, 1); if (gsurf->base.Type != EGL_PBUFFER_BIT) { stfbi->flush_front = egl_g3d_st_framebuffer_flush_front; stfbi->validate = egl_g3d_st_framebuffer_validate; } else { stfbi->flush_front = egl_g3d_st_framebuffer_flush_front_pbuffer; stfbi->validate = egl_g3d_st_framebuffer_validate_pbuffer; } stfbi->st_manager_private = (void *) &gsurf->base; return stfbi; } void egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi) { FREE(stfbi); }