diff options
Diffstat (limited to 'src/gallium/state_trackers/egl/common')
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_g3d.c | 1271 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_g3d.h | 44 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_g3d_api.c | 731 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_g3d_api.h | 37 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_g3d_image.c | 36 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_g3d_image.h | 11 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_g3d_st.c | 312 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_g3d_st.h | 80 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_st.c | 131 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/egl_st.h | 73 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/native.h | 99 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/native_modeset.h | 15 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/native_probe.h | 68 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/common/st_public_tmp.h | 20 |
14 files changed, 1582 insertions, 1346 deletions
diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index 50774b03f3..3ab72dce2f 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -14,277 +14,28 @@ * 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, + * 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 - * BRIAN PAUL 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. + * 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. */ -#include <assert.h> -#include <stdio.h> -#include <string.h> -#include "pipe/p_screen.h" -#include "util/u_memory.h" -#include "util/u_rect.h" -#include "util/u_inlines.h" #include "egldriver.h" #include "eglcurrent.h" -#include "eglconfigutil.h" #include "egllog.h" -#include "native.h" -#include "egl_g3d.h" -#include "egl_g3d_image.h" -#include "egl_st.h" - -/** - * Validate the draw/read surfaces of the context. - */ -static void -egl_g3d_validate_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct pipe_screen *screen = gdpy->native->screen; - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - const uint st_att_map[NUM_NATIVE_ATTACHMENTS] = { - ST_SURFACE_FRONT_LEFT, - ST_SURFACE_BACK_LEFT, - ST_SURFACE_FRONT_RIGHT, - ST_SURFACE_BACK_RIGHT, - }; - EGLint num_surfaces, s; - - /* validate draw and/or read buffers */ - num_surfaces = (gctx->base.ReadSurface == gctx->base.DrawSurface) ? 1 : 2; - for (s = 0; s < num_surfaces; s++) { - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; - struct egl_g3d_surface *gsurf; - struct egl_g3d_buffer *gbuf; - EGLint att; - - if (s == 0) { - gsurf = egl_g3d_surface(gctx->base.DrawSurface); - gbuf = &gctx->draw; - } - else { - gsurf = egl_g3d_surface(gctx->base.ReadSurface); - gbuf = &gctx->read; - } - - if (!gctx->force_validate) { - unsigned int seq_num; - - gsurf->native->validate(gsurf->native, gbuf->attachment_mask, - &seq_num, NULL, NULL, NULL); - /* skip validation */ - if (gsurf->sequence_number == seq_num) - continue; - } - - pipe_surface_reference(&gsurf->render_surface, NULL); - memset(textures, 0, sizeof(textures)); - - gsurf->native->validate(gsurf->native, gbuf->attachment_mask, - &gsurf->sequence_number, textures, - &gsurf->base.Width, &gsurf->base.Height); - for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { - struct pipe_texture *pt = textures[att]; - struct pipe_surface *ps; - - if (native_attachment_mask_test(gbuf->attachment_mask, att) && pt) { - ps = screen->get_tex_surface(screen, pt, 0, 0, 0, - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); - gctx->stapi->st_set_framebuffer_surface(gbuf->st_fb, - st_att_map[att], ps); - - if (gsurf->render_att == att) - pipe_surface_reference(&gsurf->render_surface, ps); - - pipe_surface_reference(&ps, NULL); - pipe_texture_reference(&pt, NULL); - } - } - - gctx->stapi->st_resize_framebuffer(gbuf->st_fb, - gsurf->base.Width, gsurf->base.Height); - } - - gctx->force_validate = EGL_FALSE; - -} - -/** - * Create a st_framebuffer. - */ -static struct st_framebuffer * -create_framebuffer(_EGLContext *ctx, _EGLSurface *surf) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config); - - return gctx->stapi->st_create_framebuffer(&gconf->native->mode, - gconf->native->color_format, gconf->native->depth_format, - gconf->native->stencil_format, - gsurf->base.Width, gsurf->base.Height, &gsurf->base); -} - -/** - * Update the attachments of draw/read surfaces. - */ -static void -egl_g3d_route_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - EGLint s; - - /* route draw and read buffers' attachments */ - for (s = 0; s < 2; s++) { - struct egl_g3d_surface *gsurf; - struct egl_g3d_buffer *gbuf; - - if (s == 0) { - gsurf = egl_g3d_surface(gctx->base.DrawSurface); - gbuf = &gctx->draw; - } - else { - gsurf = egl_g3d_surface(gctx->base.ReadSurface); - gbuf = &gctx->read; - } - - gbuf->attachment_mask = (1 << gsurf->render_att); - - /* FIXME OpenGL defaults to draw the front or back buffer when the - * context is single-buffered or double-buffered respectively. In EGL, - * however, the buffer to be drawn is determined by the surface, instead - * of the context. As a result, rendering to a pixmap surface with a - * double-buffered context does not work as expected. - * - * gctx->stapi->st_draw_front_buffer(gctx->st_ctx, natt == - * NATIVE_ATTACHMENT_FRONT_LEFT); - */ - - /* - * FIXME If the back buffer is asked for here, and the front buffer is - * later needed by the client API (e.g. glDrawBuffer is called to draw - * the front buffer), it will create a new pipe texture and draw there. - * One fix is to ask for both buffers here, but it would be a waste if - * the front buffer is never used. A better fix is to add a callback to - * the pipe screen with context private (just like flush_frontbuffer). - */ - } -} - -/** - * Reallocate the context's framebuffers after draw/read surfaces change. - */ -static EGLBoolean -egl_g3d_realloc_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - struct egl_g3d_surface *gdraw = egl_g3d_surface(gctx->base.DrawSurface); - struct egl_g3d_surface *gread = egl_g3d_surface(gctx->base.ReadSurface); - - /* unreference the old framebuffers */ - if (gctx->draw.st_fb) { - EGLBoolean is_equal = (gctx->draw.st_fb == gctx->read.st_fb); - void *priv; - - priv = gctx->stapi->st_framebuffer_private(gctx->draw.st_fb); - if (!gdraw || priv != (void *) &gdraw->base) { - gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb); - gctx->draw.st_fb = NULL; - gctx->draw.attachment_mask = 0x0; - } - - if (is_equal) { - gctx->read.st_fb = NULL; - gctx->draw.attachment_mask = 0x0; - } - else { - priv = gctx->stapi->st_framebuffer_private(gctx->read.st_fb); - if (!gread || priv != (void *) &gread->base) { - gctx->stapi->st_unreference_framebuffer(gctx->read.st_fb); - gctx->read.st_fb = NULL; - gctx->draw.attachment_mask = 0x0; - } - } - } - - if (!gdraw) - return EGL_TRUE; - - /* create the draw fb */ - if (!gctx->draw.st_fb) { - gctx->draw.st_fb = create_framebuffer(&gctx->base, &gdraw->base); - if (!gctx->draw.st_fb) - return EGL_FALSE; - } - - /* create the read fb */ - if (!gctx->read.st_fb) { - if (gread != gdraw) { - gctx->read.st_fb = create_framebuffer(&gctx->base, &gread->base); - if (!gctx->read.st_fb) { - gctx->stapi->st_unreference_framebuffer(gctx->draw.st_fb); - gctx->draw.st_fb = NULL; - return EGL_FALSE; - } - } - else { - /* there is no st_reference_framebuffer... */ - gctx->read.st_fb = gctx->draw.st_fb; - } - } - - egl_g3d_route_context(dpy, &gctx->base); - gctx->force_validate = EGL_TRUE; - - return EGL_TRUE; -} - -/** - * Return the state tracker for the given context. - */ -static const struct egl_g3d_st * -egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) -{ - struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); - const struct egl_g3d_st *stapi; - EGLint idx = -1; - - switch (ctx->ClientAPI) { - case EGL_OPENGL_ES_API: - switch (ctx->ClientVersion) { - case 1: - idx = EGL_G3D_ST_OPENGL_ES; - break; - case 2: - idx = EGL_G3D_ST_OPENGL_ES2; - break; - default: - _eglLog(_EGL_WARNING, "unknown client version %d", - ctx->ClientVersion); - break; - } - break; - case EGL_OPENVG_API: - idx = EGL_G3D_ST_OPENVG; - break; - case EGL_OPENGL_API: - idx = EGL_G3D_ST_OPENGL; - break; - default: - _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI); - break; - } +#include "pipe/p_screen.h" +#include "util/u_memory.h" +#include "util/u_format.h" +#include "util/u_string.h" - stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL; - return stapi; -} +#include "egl_g3d.h" +#include "egl_g3d_api.h" +#include "egl_g3d_st.h" +#include "native.h" /** * Initialize the state trackers. @@ -299,10 +50,10 @@ egl_g3d_init_st(_EGLDriver *drv) if (gdrv->api_mask) return; - for (i = 0; i < NUM_EGL_G3D_STS; i++) { - gdrv->stapis[i] = egl_g3d_get_st(i); + for (i = 0; i < ST_API_COUNT; i++) { + gdrv->stapis[i] = egl_g3d_create_st_api(i); if (gdrv->stapis[i]) - gdrv->api_mask |= gdrv->stapis[i]->api_bit; + gdrv->api_mask |= egl_g3d_st_api_bit(i); } if (gdrv->api_mask) @@ -351,35 +102,6 @@ egl_g3d_destroy_probe(_EGLDriver *drv, _EGLDisplay *dpy) } } -/** - * Return an API mask that consists of the state trackers that supports the - * given mode. - * - * FIXME add st_is_mode_supported()? - */ -static EGLint -get_mode_api_mask(const __GLcontextModes *mode, EGLint api_mask) -{ - EGLint check; - - /* OpenGL ES 1.x and 2.x are checked together */ - check = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT; - if (api_mask & check) { - /* this is required by EGL, not by OpenGL ES */ - if (mode->drawableType & GLX_WINDOW_BIT && !mode->doubleBufferMode) - api_mask &= ~check; - } - - check = EGL_OPENVG_BIT; - if (api_mask & check) { - /* vega st needs the depth/stencil rb */ - if (!mode->depthBits && !mode->stencilBits) - api_mask &= ~check; - } - - return api_mask; -} - #ifdef EGL_MESA_screen_surface static void @@ -393,7 +115,7 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy) gdpy->native->modeset->get_connectors(gdpy->native, &num_connectors, NULL); if (!num_connectors) { if (native_connectors) - free(native_connectors); + FREE(native_connectors); return; } @@ -408,13 +130,13 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy) gdpy->native->modeset->get_modes(gdpy->native, nconn, &num_modes); if (!num_modes) { if (native_modes) - free(native_modes); + FREE(native_modes); continue; } gscr = CALLOC_STRUCT(egl_g3d_screen); if (!gscr) { - free(native_modes); + FREE(native_modes); continue; } @@ -438,98 +160,251 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy) _eglAddScreen(dpy, &gscr->base); } - free(native_connectors); + FREE(native_connectors); } #endif /* EGL_MESA_screen_surface */ /** - * Add configs to display and return the next config ID. + * Initialize and validate the EGL config attributes. */ -static EGLint -egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) +static EGLBoolean +init_config_attributes(_EGLConfig *conf, const struct native_config *nconf, + EGLint api_mask, enum pipe_format depth_stencil_format) { - struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - const struct native_config **native_configs; - int num_configs, i; + uint rgba[4], depth_stencil[2], buffer_size; + EGLint surface_type; + EGLint i; - native_configs = gdpy->native->get_configs(gdpy->native, - &num_configs); - if (!num_configs) { - if (native_configs) - free(native_configs); - return id; + /* get the color and depth/stencil component sizes */ + assert(nconf->color_format != PIPE_FORMAT_NONE); + buffer_size = 0; + for (i = 0; i < 4; i++) { + rgba[i] = util_format_get_component_bits(nconf->color_format, + UTIL_FORMAT_COLORSPACE_RGB, i); + buffer_size += rgba[i]; + } + for (i = 0; i < 2; i++) { + if (depth_stencil_format != PIPE_FORMAT_NONE) { + depth_stencil[i] = + util_format_get_component_bits(depth_stencil_format, + UTIL_FORMAT_COLORSPACE_ZS, i); + } + else { + depth_stencil[i] = 0; + } } - for (i = 0; i < num_configs; i++) { - EGLint api_mask; - struct egl_g3d_config *gconf; - EGLBoolean valid; + surface_type = 0x0; + if (nconf->window_bit) + surface_type |= EGL_WINDOW_BIT; + if (nconf->pixmap_bit) + surface_type |= EGL_PIXMAP_BIT; +#ifdef EGL_MESA_screen_surface + if (nconf->scanout_bit) + surface_type |= EGL_SCREEN_BIT_MESA; +#endif - gconf = CALLOC_STRUCT(egl_g3d_config); - if (!gconf) - continue; + if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) + surface_type |= EGL_PBUFFER_BIT; - _eglInitConfig(&gconf->base, dpy, id); + SET_CONFIG_ATTRIB(conf, EGL_CONFORMANT, api_mask); + SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, api_mask); - api_mask = get_mode_api_mask(&native_configs[i]->mode, gdrv->api_mask); - if (!api_mask) { - _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", - native_configs[i]->mode.visualID); - } + SET_CONFIG_ATTRIB(conf, EGL_RED_SIZE, rgba[0]); + SET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE, rgba[1]); + SET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE, rgba[2]); + SET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE, rgba[3]); + SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, buffer_size); - valid = _eglConfigFromContextModesRec(&gconf->base, - &native_configs[i]->mode, api_mask, api_mask); - if (valid) { -#ifdef EGL_MESA_screen_surface - /* check if scanout surface bit is set */ - if (native_configs[i]->scanout_bit) { - EGLint val = GET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE); - val |= EGL_SCREEN_BIT_MESA; - SET_CONFIG_ATTRIB(&gconf->base, EGL_SURFACE_TYPE, val); - } -#endif - valid = _eglValidateConfig(&gconf->base, EGL_FALSE); - } - if (!valid) { - _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", - native_configs[i]->mode.visualID); - free(gconf); - continue; + SET_CONFIG_ATTRIB(conf, EGL_DEPTH_SIZE, depth_stencil[0]); + SET_CONFIG_ATTRIB(conf, EGL_STENCIL_SIZE, depth_stencil[1]); + + SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type); + + SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, EGL_TRUE); + if (surface_type & EGL_WINDOW_BIT) { + SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, nconf->native_visual_id); + SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, + nconf->native_visual_type); + } + + if (surface_type & EGL_PBUFFER_BIT) { + SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, EGL_TRUE); + if (rgba[3]) + SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE); + + SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_WIDTH, 4096); + SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_HEIGHT, 4096); + SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_PIXELS, 4096 * 4096); + } + + SET_CONFIG_ATTRIB(conf, EGL_LEVEL, nconf->level); + SET_CONFIG_ATTRIB(conf, EGL_SAMPLES, nconf->samples); + SET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS, 1); + + if (nconf->slow_config) + SET_CONFIG_ATTRIB(conf, EGL_CONFIG_CAVEAT, EGL_SLOW_CONFIG); + + if (nconf->transparent_rgb) { + rgba[0] = nconf->transparent_rgb_values[0]; + rgba[1] = nconf->transparent_rgb_values[1]; + rgba[2] = nconf->transparent_rgb_values[2]; + + SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RGB); + SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, rgba[0]); + SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, rgba[1]); + SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, rgba[2]); + } + + return _eglValidateConfig(conf, EGL_FALSE); +} + +/** + * Initialize an EGL config from the native config. + */ +static EGLBoolean +egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, const struct native_config *nconf, + enum pipe_format depth_stencil_format) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + struct egl_g3d_config *gconf = egl_g3d_config(conf); + EGLint buffer_mask, api_mask; + EGLBoolean valid; + EGLint i; + + buffer_mask = 0x0; + if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_LEFT)) + buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; + if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_LEFT)) + buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_FRONT_RIGHT)) + buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (nconf->buffer_mask & (1 << NATIVE_ATTACHMENT_BACK_RIGHT)) + buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + + gconf->stvis.buffer_mask = buffer_mask; + gconf->stvis.color_format = nconf->color_format; + gconf->stvis.depth_stencil_format = depth_stencil_format; + gconf->stvis.accum_format = PIPE_FORMAT_NONE; + gconf->stvis.samples = nconf->samples; + + gconf->stvis.render_buffer = (buffer_mask & ST_ATTACHMENT_BACK_LEFT_MASK) ? + ST_ATTACHMENT_BACK_LEFT : ST_ATTACHMENT_FRONT_LEFT; + + api_mask = 0; + for (i = 0; i < ST_API_COUNT; i++) { + struct st_api *stapi = gdrv->stapis[i]; + if (stapi) { + if (stapi->is_visual_supported(stapi, &gconf->stvis)) + api_mask |= egl_g3d_st_api_bit(i); } + } + /* this is required by EGL, not by OpenGL ES */ + if (nconf->window_bit && + gconf->stvis.render_buffer != ST_ATTACHMENT_BACK_LEFT) + api_mask &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT); - gconf->native = native_configs[i]; - _eglAddConfig(dpy, &gconf->base); - id++; + if (!api_mask) { + _eglLog(_EGL_DEBUG, "no state tracker supports config 0x%x", + nconf->native_visual_id); } - free(native_configs); - return id; + valid = init_config_attributes(&gconf->base, + nconf, api_mask, depth_stencil_format); + if (!valid) { + _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id); + return EGL_FALSE; + } + + gconf->native = nconf; + + return EGL_TRUE; } /** - * Flush the front buffer of the context's draw surface. + * Get all interested depth/stencil formats of a display. */ -static void -egl_g3d_flush_frontbuffer(struct pipe_screen *screen, - struct pipe_surface *surf, void *context_private) +static EGLint +egl_g3d_fill_depth_stencil_formats(_EGLDisplay *dpy, + enum pipe_format formats[8]) { - struct egl_g3d_context *gctx = egl_g3d_context(context_private); - struct egl_g3d_surface *gsurf = egl_g3d_surface(gctx->base.DrawSurface); + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct pipe_screen *screen = gdpy->native->screen; + const EGLint candidates[] = { + 1, PIPE_FORMAT_Z16_UNORM, + 1, PIPE_FORMAT_Z32_UNORM, + 2, PIPE_FORMAT_Z24_UNORM_S8_USCALED, PIPE_FORMAT_S8_USCALED_Z24_UNORM, + 2, PIPE_FORMAT_Z24X8_UNORM, PIPE_FORMAT_X8Z24_UNORM, + 0 + }; + const EGLint *fmt = candidates; + EGLint count; + + count = 0; + formats[count++] = PIPE_FORMAT_NONE; + + while (*fmt) { + EGLint i, n = *fmt++; + + /* pick the first supported format */ + for (i = 0; i < n; i++) { + if (screen->is_format_supported(screen, fmt[i], + PIPE_TEXTURE_2D, PIPE_BIND_DEPTH_STENCIL, 0)) { + formats[count++] = fmt[i]; + break; + } + } - if (gsurf) - gsurf->native->flush_frontbuffer(gsurf->native); + fmt += n; + } + + return count; } /** - * Re-validate the context. + * Add configs to display and return the next config ID. */ -static void -egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private) +static EGLint +egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) { - struct egl_g3d_context *gctx = egl_g3d_context(context_private); - egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base); + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + const struct native_config **native_configs; + enum pipe_format depth_stencil_formats[8]; + int num_formats, num_configs, i, j; + + native_configs = gdpy->native->get_configs(gdpy->native, &num_configs); + if (!num_configs) { + if (native_configs) + FREE(native_configs); + return id; + } + + num_formats = egl_g3d_fill_depth_stencil_formats(dpy, + depth_stencil_formats); + + for (i = 0; i < num_configs; i++) { + for (j = 0; j < num_formats; j++) { + struct egl_g3d_config *gconf; + + gconf = CALLOC_STRUCT(egl_g3d_config); + if (gconf) { + _eglInitConfig(&gconf->base, dpy, id); + if (!egl_g3d_init_config(drv, dpy, &gconf->base, + native_configs[i], depth_stencil_formats[j])) { + FREE(gconf); + break; + } + + _eglAddConfig(dpy, &gconf->base); + id++; + } + } + } + + FREE(native_configs); + return id; } static void @@ -539,11 +414,15 @@ egl_g3d_invalid_surface(struct native_display *ndpy, { /* XXX not thread safe? */ struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data); - struct egl_g3d_context *gctx = egl_g3d_context(gsurf->base.CurrentContext); - - /* set force_validate to skip an unnecessary check */ + struct egl_g3d_context *gctx; + + /* + * Some functions such as egl_g3d_copy_buffers create a temporary native + * surface. There is no gsurf associated with it. + */ + gctx = (gsurf) ? egl_g3d_context(gsurf->base.CurrentContext) : NULL; if (gctx) - gctx->force_validate = TRUE; + gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi); } static struct native_event_handler egl_g3d_native_event_handler = { @@ -559,19 +438,25 @@ egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) _eglReleaseDisplayResources(drv, dpy); _eglCleanupDisplay(dpy); + if (gdpy->pipe) + gdpy->pipe->destroy(gdpy->pipe); + if (dpy->Screens) { for (i = 0; i < dpy->NumScreens; i++) { struct egl_g3d_screen *gscr = egl_g3d_screen(dpy->Screens[i]); - free(gscr->native_modes); - free(gscr); + FREE(gscr->native_modes); + FREE(gscr); } - free(dpy->Screens); + FREE(dpy->Screens); } + if (gdpy->smapi) + egl_g3d_destroy_st_manager(gdpy->smapi); + if (gdpy->native) gdpy->native->destroy(gdpy->native); - free(gdpy); + FREE(gdpy); dpy->DriverData = NULL; return EGL_TRUE; @@ -602,12 +487,17 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, } gdpy->native->user_data = (void *) dpy; - gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer; - gdpy->native->screen->update_buffer = egl_g3d_update_buffer; egl_g3d_init_st(&gdrv->base); dpy->ClientAPIsMask = gdrv->api_mask; + gdpy->smapi = egl_g3d_create_st_manager(dpy); + if (!gdpy->smapi) { + _eglError(EGL_NOT_INITIALIZED, + "eglInitialize(failed to create st manager)"); + goto fail; + } + #ifdef EGL_MESA_screen_surface /* enable MESA_screen_surface before adding (and validating) configs */ if (gdpy->native->modeset) { @@ -636,449 +526,6 @@ fail: return EGL_FALSE; } -static _EGLContext * -egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - _EGLContext *share, const EGLint *attribs) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_context *gshare = egl_g3d_context(share); - struct egl_g3d_config *gconf = egl_g3d_config(conf); - struct egl_g3d_context *gctx; - const __GLcontextModes *mode; - - gctx = CALLOC_STRUCT(egl_g3d_context); - if (!gctx) { - _eglError(EGL_BAD_ALLOC, "eglCreateContext"); - return NULL; - } - - if (!_eglInitContext(&gctx->base, dpy, conf, attribs)) { - free(gctx); - return NULL; - } - - gctx->stapi = egl_g3d_choose_st(drv, &gctx->base); - if (!gctx->stapi) { - free(gctx); - return NULL; - } - - mode = &gconf->native->mode; - - gctx->pipe = gdpy->native->screen->context_create( - gdpy->native->screen, - (void *) &gctx->base); - - if (!gctx->pipe) { - free(gctx); - return NULL; - } - - gctx->st_ctx = gctx->stapi->st_create_context(gctx->pipe, mode, - (gshare) ? gshare->st_ctx : NULL); - if (!gctx->st_ctx) { - gctx->pipe->destroy(gctx->pipe); - free(gctx); - return NULL; - } - - return &gctx->base; -} - -/** - * Destroy a context. - */ -static void -destroy_context(_EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - - /* FIXME a context might live longer than its display */ - if (!dpy->Initialized) - _eglLog(_EGL_FATAL, "destroy a context with an unitialized display"); - - egl_g3d_realloc_context(dpy, &gctx->base); - /* it will destroy the associated pipe context */ - gctx->stapi->st_destroy_context(gctx->st_ctx); - - free(gctx); -} - -static EGLBoolean -egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) -{ - if (!_eglIsContextBound(ctx)) - destroy_context(dpy, ctx); - return EGL_TRUE; -} - -struct egl_g3d_create_surface_arg { - EGLint type; - union { - EGLNativeWindowType win; - EGLNativePixmapType pix; - } u; -}; - -static _EGLSurface * -egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - struct egl_g3d_create_surface_arg *arg, - const EGLint *attribs) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_config *gconf = egl_g3d_config(conf); - struct egl_g3d_surface *gsurf; - struct native_surface *nsurf; - const char *err; - - switch (arg->type) { - case EGL_WINDOW_BIT: - err = "eglCreateWindowSurface"; - break; - case EGL_PIXMAP_BIT: - err = "eglCreatePixmapSurface"; - break; - case EGL_PBUFFER_BIT: - err = "eglCreatePBufferSurface"; - break; -#ifdef EGL_MESA_screen_surface - case EGL_SCREEN_BIT_MESA: - err = "eglCreateScreenSurface"; - break; -#endif - default: - err = "eglCreateUnknownSurface"; - break; - } - - gsurf = CALLOC_STRUCT(egl_g3d_surface); - if (!gsurf) { - _eglError(EGL_BAD_ALLOC, err); - return NULL; - } - - if (!_eglInitSurface(&gsurf->base, dpy, arg->type, conf, attribs)) { - free(gsurf); - return NULL; - } - - /* create the native surface */ - switch (arg->type) { - case EGL_WINDOW_BIT: - nsurf = gdpy->native->create_window_surface(gdpy->native, - arg->u.win, gconf->native); - break; - case EGL_PIXMAP_BIT: - nsurf = gdpy->native->create_pixmap_surface(gdpy->native, - arg->u.pix, gconf->native); - break; - case EGL_PBUFFER_BIT: - nsurf = gdpy->native->create_pbuffer_surface(gdpy->native, - gconf->native, gsurf->base.Width, gsurf->base.Height); - break; -#ifdef EGL_MESA_screen_surface - case EGL_SCREEN_BIT_MESA: - /* prefer back buffer (move to _eglInitSurface?) */ - gsurf->base.RenderBuffer = EGL_BACK_BUFFER; - nsurf = gdpy->native->modeset->create_scanout_surface(gdpy->native, - gconf->native, gsurf->base.Width, gsurf->base.Height); - break; -#endif - default: - nsurf = NULL; - break; - } - - if (!nsurf) { - free(gsurf); - return NULL; - } - /* initialize the geometry */ - if (!nsurf->validate(nsurf, 0x0, &gsurf->sequence_number, NULL, - &gsurf->base.Width, &gsurf->base.Height)) { - nsurf->destroy(nsurf); - free(gsurf); - return NULL; - } - - nsurf->user_data = &gsurf->base; - gsurf->native = nsurf; - - gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) ? - NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; - if (!gconf->native->mode.doubleBufferMode) - gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT; - - return &gsurf->base; -} - -static _EGLSurface * -egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLConfig *conf, EGLNativeWindowType win, - const EGLint *attribs) -{ - struct egl_g3d_create_surface_arg arg; - - memset(&arg, 0, sizeof(arg)); - arg.type = EGL_WINDOW_BIT; - arg.u.win = win; - - return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); -} - -static _EGLSurface * -egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLConfig *conf, EGLNativePixmapType pix, - const EGLint *attribs) -{ - struct egl_g3d_create_surface_arg arg; - - memset(&arg, 0, sizeof(arg)); - arg.type = EGL_PIXMAP_BIT; - arg.u.pix = pix; - - return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); -} - -static _EGLSurface * -egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLConfig *conf, const EGLint *attribs) -{ - struct egl_g3d_create_surface_arg arg; - - memset(&arg, 0, sizeof(arg)); - arg.type = EGL_PBUFFER_BIT; - - return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); -} - -/** - * Destroy a surface. - */ -static void -destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) -{ - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - - /* FIXME a surface might live longer than its display */ - if (!dpy->Initialized) - _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display"); - - pipe_surface_reference(&gsurf->render_surface, NULL); - gsurf->native->destroy(gsurf->native); - free(gsurf); -} - -static EGLBoolean -egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) -{ - if (!_eglIsSurfaceBound(surf)) - destroy_surface(dpy, surf); - return EGL_TRUE; -} - -static EGLBoolean -egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - struct egl_g3d_surface *gdraw = egl_g3d_surface(draw); - struct egl_g3d_context *old_gctx; - EGLBoolean ok = EGL_TRUE; - - /* bind the new context and return the "orphaned" one */ - if (!_eglBindContext(&ctx, &draw, &read)) - return EGL_FALSE; - old_gctx = egl_g3d_context(ctx); - - if (old_gctx) { - /* flush old context */ - old_gctx->stapi->st_flush(old_gctx->st_ctx, - PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); - - /* - * The old context is no longer current, and egl_g3d_realloc_context() - * should be called to destroy the framebuffers. However, it is possible - * that it will be made current again with the same draw/read surfaces. - * It might be better to keep it around. - */ - } - - if (gctx) { - ok = egl_g3d_realloc_context(dpy, &gctx->base); - if (ok) { - ok = gctx->stapi->st_make_current(gctx->st_ctx, - gctx->draw.st_fb, gctx->read.st_fb); - if (ok) { - egl_g3d_validate_context(dpy, &gctx->base); - if (gdraw->base.Type == EGL_WINDOW_BIT) { - gctx->base.WindowRenderBuffer = - (gdraw->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) ? - EGL_SINGLE_BUFFER : EGL_BACK_BUFFER; - } - } - } - } - else if (old_gctx) { - ok = old_gctx->stapi->st_make_current(NULL, NULL, NULL); - old_gctx->base.WindowRenderBuffer = EGL_NONE; - } - - if (ctx && !_eglIsContextLinked(ctx)) - destroy_context(dpy, ctx); - if (draw && !_eglIsSurfaceLinked(draw)) - destroy_surface(dpy, draw); - if (read && read != draw && !_eglIsSurfaceLinked(read)) - destroy_surface(dpy, read); - - return ok; -} - -static EGLBoolean -egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) -{ - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - _EGLContext *ctx = _eglGetCurrentContext(); - struct egl_g3d_context *gctx = NULL; - - /* no-op for pixmap or pbuffer surface */ - if (gsurf->base.Type == EGL_PIXMAP_BIT || - gsurf->base.Type == EGL_PBUFFER_BIT) - return EGL_TRUE; - - /* or when the surface is single-buffered */ - if (gsurf->render_att == NATIVE_ATTACHMENT_FRONT_LEFT) - return EGL_TRUE; - - if (ctx && ctx->DrawSurface == surf) - gctx = egl_g3d_context(ctx); - - /* flush if the surface is current */ - if (gctx) - gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb); - - return gsurf->native->swap_buffers(gsurf->native); -} - -/** - * Find a config that supports the pixmap. - */ -_EGLConfig * -egl_g3d_find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_config *gconf; - EGLint i; - - for (i = 0; i < dpy->NumConfigs; i++) { - gconf = egl_g3d_config(dpy->Configs[i]); - if (gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native)) - break; - } - - return (i < dpy->NumConfigs) ? &gconf->base : NULL; -} - -/** - * Get the pipe surface of the given attachment of the native surface. - */ -static struct pipe_surface * -get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf, - enum native_attachment natt) -{ - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; - struct pipe_surface *psurf; - - textures[natt] = NULL; - nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL); - if (!textures[natt]) - return NULL; - - psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt], - 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE); - pipe_texture_reference(&textures[natt], NULL); - - return psurf; -} - -static EGLBoolean -egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, - EGLNativePixmapType target) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - _EGLContext *ctx = _eglGetCurrentContext(); - struct egl_g3d_config *gconf; - struct native_surface *nsurf; - struct pipe_screen *screen = gdpy->native->screen; - struct pipe_surface *psurf; - - if (!gsurf->render_surface) - return EGL_TRUE; - - gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, target)); - if (!gconf) - return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); - - nsurf = gdpy->native->create_pixmap_surface(gdpy->native, - target, gconf->native); - if (!nsurf) - return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); - - /* flush if the surface is current */ - if (ctx && ctx->DrawSurface == &gsurf->base) { - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - gctx->stapi->st_flush(gctx->st_ctx, - PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); - } - - psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); - if (psurf) { - struct pipe_context pipe; - - /** - * XXX This is hacky. If we might allow the EGLDisplay to create a pipe - * context of its own and use the blitter context for this. - */ - memset(&pipe, 0, sizeof(pipe)); - pipe.screen = screen; - - util_surface_copy(&pipe, FALSE, psurf, 0, 0, - gsurf->render_surface, 0, 0, psurf->width, psurf->height); - - pipe_surface_reference(&psurf, NULL); - nsurf->flush_frontbuffer(nsurf); - } - - nsurf->destroy(nsurf); - - return EGL_TRUE; -} - -static EGLBoolean -egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) -{ - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - gctx->stapi->st_finish(gctx->st_ctx); - return EGL_TRUE; -} - -static EGLBoolean -egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine) -{ - _EGLContext *ctx = _eglGetCurrentContext(); - - if (engine != EGL_CORE_NATIVE_ENGINE) - return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); - - if (ctx && ctx->DrawSurface) { - struct egl_g3d_surface *gsurf = egl_g3d_surface(ctx->DrawSurface); - gsurf->native->wait(gsurf->native); - } - - return EGL_TRUE; -} - static _EGLProc egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) { @@ -1089,10 +536,10 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) /* in case this is called before a display is initialized */ egl_g3d_init_st(&gdrv->base); - for (i = 0; i < NUM_EGL_G3D_STS; i++) { - const struct egl_g3d_st *stapi = gdrv->stapis[i]; + for (i = 0; i < ST_API_COUNT; i++) { + struct st_api *stapi = gdrv->stapis[i]; if (stapi) { - proc = (_EGLProc) stapi->st_get_proc_address(procname); + proc = (_EGLProc) stapi->get_proc_address(stapi, procname); if (proc) return proc; } @@ -1101,161 +548,6 @@ egl_g3d_get_proc_address(_EGLDriver *drv, const char *procname) return (_EGLProc) NULL; } -static EGLBoolean -egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLSurface *surf, EGLint buffer) -{ - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API); - struct egl_g3d_context *gctx; - enum pipe_format target_format; - int target; - - if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT) - return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); - if (buffer != EGL_BACK_BUFFER) - return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); - if (gsurf->base.BoundToTexture) - return _eglError(EGL_BAD_ACCESS, "eglBindTexImage"); - - switch (gsurf->base.TextureFormat) { - case EGL_TEXTURE_RGB: - target_format = PIPE_FORMAT_R8G8B8_UNORM; - break; - case EGL_TEXTURE_RGBA: - target_format = PIPE_FORMAT_B8G8R8A8_UNORM; - break; - default: - return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); - } - - switch (gsurf->base.TextureTarget) { - case EGL_TEXTURE_2D: - target = ST_TEXTURE_2D; - break; - default: - return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); - } - - if (!es1) - return EGL_TRUE; - if (!gsurf->render_surface) - return EGL_FALSE; - - /* flush properly if the surface is bound */ - if (gsurf->base.CurrentContext) { - gctx = egl_g3d_context(gsurf->base.CurrentContext); - gctx->stapi->st_flush(gctx->st_ctx, - PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); - } - - gctx = egl_g3d_context(es1); - gctx->stapi->st_bind_texture_surface(gsurf->render_surface, - target, gsurf->base.MipmapLevel, target_format); - - gsurf->base.BoundToTexture = EGL_TRUE; - - return EGL_TRUE; -} - -static EGLBoolean -egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLSurface *surf, EGLint buffer) -{ - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - - if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT || - !gsurf->base.BoundToTexture) - return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); - if (buffer != EGL_BACK_BUFFER) - return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); - - if (gsurf->render_surface) { - _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API); - struct egl_g3d_context *gctx = egl_g3d_context(ctx); - - /* what if the context the surface binds to is no longer current? */ - if (gctx) - gctx->stapi->st_unbind_texture_surface(gsurf->render_surface, - ST_TEXTURE_2D, gsurf->base.MipmapLevel); - } - - gsurf->base.BoundToTexture = EGL_FALSE; - - return EGL_TRUE; -} - -#ifdef EGL_MESA_screen_surface - -static _EGLSurface * -egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLConfig *conf, const EGLint *attribs) -{ - struct egl_g3d_create_surface_arg arg; - - memset(&arg, 0, sizeof(arg)); - arg.type = EGL_SCREEN_BIT_MESA; - - return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); -} - -static EGLBoolean -egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLScreen *scr, _EGLSurface *surf, - _EGLMode *mode) -{ - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_screen *gscr = egl_g3d_screen(scr); - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - struct native_surface *nsurf; - const struct native_mode *nmode; - EGLBoolean changed; - - if (gsurf) { - EGLint idx; - - if (!mode) - return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA"); - if (gsurf->base.Type != EGL_SCREEN_BIT_MESA) - return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA"); - if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height) - return _eglError(EGL_BAD_MATCH, - "eglShowSurfaceMESA(surface smaller than mode size)"); - - /* find the index of the mode */ - for (idx = 0; idx < gscr->base.NumModes; idx++) - if (mode == &gscr->base.Modes[idx]) - break; - if (idx >= gscr->base.NumModes) { - return _eglError(EGL_BAD_MODE_MESA, - "eglShowSurfaceMESA(unknown mode)"); - } - - nsurf = gsurf->native; - nmode = gscr->native_modes[idx]; - } - else { - if (mode) - return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA"); - - /* disable the screen */ - nsurf = NULL; - nmode = NULL; - } - - /* TODO surface panning by CRTC choosing */ - changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf, - gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode); - if (changed) { - gscr->base.CurrentSurface = &gsurf->base; - gscr->base.CurrentMode = mode; - } - - return changed; -} - -#endif /* EGL_MESA_screen_surface */ - static EGLint egl_g3d_probe(_EGLDriver *drv, _EGLDisplay *dpy) { @@ -1289,9 +581,15 @@ static void egl_g3d_unload(_EGLDriver *drv) { struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + EGLint i; + + for (i = 0; i < ST_API_COUNT; i++) { + if (gdrv->stapis[i]) + gdrv->stapis[i]->destroy(gdrv->stapis[i]); + } egl_g3d_destroy_probe(drv, NULL); - free(gdrv); + FREE(gdrv); } _EGLDriver * @@ -1300,41 +598,18 @@ _eglMain(const char *args) static char driver_name[64]; struct egl_g3d_driver *gdrv; - snprintf(driver_name, sizeof(driver_name), + util_snprintf(driver_name, sizeof(driver_name), "Gallium/%s", native_get_name()); gdrv = CALLOC_STRUCT(egl_g3d_driver); if (!gdrv) return NULL; - _eglInitDriverFallbacks(&gdrv->base); - + egl_g3d_init_driver_api(&gdrv->base); gdrv->base.API.Initialize = egl_g3d_initialize; gdrv->base.API.Terminate = egl_g3d_terminate; - gdrv->base.API.CreateContext = egl_g3d_create_context; - gdrv->base.API.DestroyContext = egl_g3d_destroy_context; - gdrv->base.API.CreateWindowSurface = egl_g3d_create_window_surface; - gdrv->base.API.CreatePixmapSurface = egl_g3d_create_pixmap_surface; - gdrv->base.API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface; - gdrv->base.API.DestroySurface = egl_g3d_destroy_surface; - gdrv->base.API.MakeCurrent = egl_g3d_make_current; - gdrv->base.API.SwapBuffers = egl_g3d_swap_buffers; - gdrv->base.API.CopyBuffers = egl_g3d_copy_buffers; - gdrv->base.API.WaitClient = egl_g3d_wait_client; - gdrv->base.API.WaitNative = egl_g3d_wait_native; gdrv->base.API.GetProcAddress = egl_g3d_get_proc_address; - gdrv->base.API.BindTexImage = egl_g3d_bind_tex_image; - gdrv->base.API.ReleaseTexImage = egl_g3d_release_tex_image; - - gdrv->base.API.CreateImageKHR = egl_g3d_create_image; - gdrv->base.API.DestroyImageKHR = egl_g3d_destroy_image; - -#ifdef EGL_MESA_screen_surface - gdrv->base.API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface; - gdrv->base.API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface; -#endif - gdrv->base.Name = driver_name; gdrv->base.Probe = egl_g3d_probe; gdrv->base.Unload = egl_g3d_unload; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h index e3e55e46d3..5a3c80b968 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d.h @@ -14,12 +14,13 @@ * 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, + * 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 - * BRIAN PAUL 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. + * 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. */ #ifndef _EGL_G3D_H_ @@ -39,11 +40,11 @@ #include "eglmode.h" #include "native.h" -#include "egl_st.h" +#include "egl_g3d_st.h" struct egl_g3d_driver { _EGLDriver base; - const struct egl_g3d_st *stapis[NUM_EGL_G3D_STS]; + struct st_api *stapis[ST_API_COUNT]; EGLint api_mask; EGLint probe_key; @@ -51,40 +52,41 @@ struct egl_g3d_driver { struct egl_g3d_display { struct native_display *native; -}; -struct egl_g3d_buffer { - struct st_framebuffer *st_fb; - uint attachment_mask; + struct st_manager *smapi; + struct pipe_context *pipe; }; struct egl_g3d_context { _EGLContext base; - const struct egl_g3d_st *stapi; - struct pipe_context *pipe; + struct st_api *stapi; - struct st_context *st_ctx; - EGLBoolean force_validate; - struct egl_g3d_buffer draw, read; + struct st_context_iface *stctxi; }; struct egl_g3d_surface { _EGLSurface base; + + struct st_visual stvis; + struct st_framebuffer_iface *stfbi; + + /* the native surface; NULL for pbuffers */ struct native_surface *native; - enum native_attachment render_att; - struct pipe_surface *render_surface; + struct pipe_resource *render_texture; + unsigned int sequence_number; }; struct egl_g3d_config { _EGLConfig base; const struct native_config *native; + struct st_visual stvis; }; struct egl_g3d_image { _EGLImage base; - struct pipe_texture *texture; + struct pipe_resource *texture; unsigned face; unsigned level; unsigned zslice; @@ -101,8 +103,4 @@ _EGL_DRIVER_STANDARD_TYPECASTS(egl_g3d) _EGL_DRIVER_TYPECAST(egl_g3d_screen, _EGLScreen, obj) _EGL_DRIVER_TYPECAST(egl_g3d_image, _EGLImage, obj) - -_EGLConfig * -egl_g3d_find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix); - #endif /* _EGL_G3D_H_ */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c new file mode 100644 index 0000000000..478516453c --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c @@ -0,0 +1,731 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> + * + * 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. + */ + +#include "egldriver.h" +#include "eglcurrent.h" +#include "egllog.h" + +#include "pipe/p_screen.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" + +#include "egl_g3d.h" +#include "egl_g3d_api.h" +#include "egl_g3d_image.h" +#include "egl_g3d_st.h" +#include "native.h" + +/** + * Return the state tracker for the given context. + */ +static struct st_api * +egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + struct st_api *stapi; + EGLint idx = -1; + + switch (ctx->ClientAPI) { + case EGL_OPENGL_ES_API: + switch (ctx->ClientVersion) { + case 1: + idx = ST_API_OPENGL_ES1; + break; + case 2: + idx = ST_API_OPENGL_ES2; + break; + default: + _eglLog(_EGL_WARNING, "unknown client version %d", + ctx->ClientVersion); + break; + } + break; + case EGL_OPENVG_API: + idx = ST_API_OPENVG; + break; + case EGL_OPENGL_API: + idx = ST_API_OPENGL; + break; + default: + _eglLog(_EGL_WARNING, "unknown client API 0x%04x", ctx->ClientAPI); + break; + } + + stapi = (idx >= 0) ? gdrv->stapis[idx] : NULL; + return stapi; +} + +static _EGLContext * +egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + _EGLContext *share, const EGLint *attribs) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_context *gshare = egl_g3d_context(share); + struct egl_g3d_config *gconf = egl_g3d_config(conf); + struct egl_g3d_context *gctx; + + gctx = CALLOC_STRUCT(egl_g3d_context); + if (!gctx) { + _eglError(EGL_BAD_ALLOC, "eglCreateContext"); + return NULL; + } + + if (!_eglInitContext(&gctx->base, dpy, conf, attribs)) { + FREE(gctx); + return NULL; + } + + gctx->stapi = egl_g3d_choose_st(drv, &gctx->base); + if (!gctx->stapi) { + FREE(gctx); + return NULL; + } + + gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi, + &gconf->stvis, (gshare) ? gshare->stctxi : NULL); + if (!gctx->stctxi) { + FREE(gctx); + return NULL; + } + + gctx->stctxi->st_manager_private = (void *) &gctx->base; + + return &gctx->base; +} + +/** + * Destroy a context. + */ +static void +destroy_context(_EGLDisplay *dpy, _EGLContext *ctx) +{ + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + + /* FIXME a context might live longer than its display */ + if (!dpy->Initialized) + _eglLog(_EGL_FATAL, "destroy a context with an unitialized display"); + + gctx->stctxi->destroy(gctx->stctxi); + + FREE(gctx); +} + +static EGLBoolean +egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +{ + if (!_eglIsContextBound(ctx)) + destroy_context(dpy, ctx); + return EGL_TRUE; +} + +struct egl_g3d_create_surface_arg { + EGLint type; + union { + EGLNativeWindowType win; + EGLNativePixmapType pix; + } u; +}; + +static _EGLSurface * +egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + struct egl_g3d_create_surface_arg *arg, + const EGLint *attribs) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_config *gconf = egl_g3d_config(conf); + struct egl_g3d_surface *gsurf; + struct native_surface *nsurf; + const char *err; + + switch (arg->type) { + case EGL_WINDOW_BIT: + err = "eglCreateWindowSurface"; + break; + case EGL_PIXMAP_BIT: + err = "eglCreatePixmapSurface"; + break; +#ifdef EGL_MESA_screen_surface + case EGL_SCREEN_BIT_MESA: + err = "eglCreateScreenSurface"; + break; +#endif + default: + err = "eglCreateUnknownSurface"; + break; + } + + gsurf = CALLOC_STRUCT(egl_g3d_surface); + if (!gsurf) { + _eglError(EGL_BAD_ALLOC, err); + return NULL; + } + + if (!_eglInitSurface(&gsurf->base, dpy, arg->type, conf, attribs)) { + FREE(gsurf); + return NULL; + } + + /* create the native surface */ + switch (arg->type) { + case EGL_WINDOW_BIT: + nsurf = gdpy->native->create_window_surface(gdpy->native, + arg->u.win, gconf->native); + break; + case EGL_PIXMAP_BIT: + nsurf = gdpy->native->create_pixmap_surface(gdpy->native, + arg->u.pix, gconf->native); + break; +#ifdef EGL_MESA_screen_surface + case EGL_SCREEN_BIT_MESA: + /* prefer back buffer (move to _eglInitSurface?) */ + gsurf->base.RenderBuffer = EGL_BACK_BUFFER; + nsurf = gdpy->native->modeset->create_scanout_surface(gdpy->native, + gconf->native, gsurf->base.Width, gsurf->base.Height); + break; +#endif + default: + nsurf = NULL; + break; + } + + if (!nsurf) { + FREE(gsurf); + return NULL; + } + /* initialize the geometry */ + if (!nsurf->validate(nsurf, 0x0, &gsurf->sequence_number, NULL, + &gsurf->base.Width, &gsurf->base.Height)) { + nsurf->destroy(nsurf); + FREE(gsurf); + return NULL; + } + + gsurf->stvis = gconf->stvis; + if (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) + gsurf->stvis.render_buffer = ST_ATTACHMENT_FRONT_LEFT; + + gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base); + if (!gsurf->stfbi) { + nsurf->destroy(nsurf); + FREE(gsurf); + return NULL; + } + + nsurf->user_data = &gsurf->base; + gsurf->native = nsurf; + + return &gsurf->base; +} + +static _EGLSurface * +egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, EGLNativeWindowType win, + const EGLint *attribs) +{ + struct egl_g3d_create_surface_arg arg; + + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_WINDOW_BIT; + arg.u.win = win; + + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); +} + +static _EGLSurface * +egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, EGLNativePixmapType pix, + const EGLint *attribs) +{ + struct egl_g3d_create_surface_arg arg; + + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_PIXMAP_BIT; + arg.u.pix = pix; + + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); +} + +static _EGLSurface * +egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, const EGLint *attribs) +{ + struct egl_g3d_config *gconf = egl_g3d_config(conf); + struct egl_g3d_surface *gsurf; + + gsurf = CALLOC_STRUCT(egl_g3d_surface); + if (!gsurf) { + _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); + return NULL; + } + + if (!_eglInitSurface(&gsurf->base, dpy, EGL_PBUFFER_BIT, conf, attribs)) { + FREE(gsurf); + return NULL; + } + + gsurf->stvis = gconf->stvis; + + gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base); + if (!gsurf->stfbi) { + FREE(gsurf); + return NULL; + } + + return &gsurf->base; +} + +/** + * Destroy a surface. + */ +static void +destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + + /* FIXME a surface might live longer than its display */ + if (!dpy->Initialized) + _eglLog(_EGL_FATAL, "destroy a surface with an unitialized display"); + + pipe_resource_reference(&gsurf->render_texture, NULL); + egl_g3d_destroy_st_framebuffer(gsurf->stfbi); + if (gsurf->native) + gsurf->native->destroy(gsurf->native); + FREE(gsurf); +} + +static EGLBoolean +egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) +{ + if (!_eglIsSurfaceBound(surf)) + destroy_surface(dpy, surf); + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLSurface *draw, _EGLSurface *read, _EGLContext *ctx) +{ + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + struct egl_g3d_surface *gdraw = egl_g3d_surface(draw); + struct egl_g3d_surface *gread = egl_g3d_surface(read); + struct egl_g3d_context *old_gctx; + EGLBoolean ok = EGL_TRUE; + + /* bind the new context and return the "orphaned" one */ + if (!_eglBindContext(&ctx, &draw, &read)) + return EGL_FALSE; + old_gctx = egl_g3d_context(ctx); + + if (old_gctx) { + /* flush old context */ + old_gctx->stctxi->flush(old_gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + } + + if (gctx) { + ok = gctx->stapi->make_current(gctx->stapi, gctx->stctxi, + (gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL); + if (ok) { + gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, gdraw->stfbi); + if (gread != gdraw) { + gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, + gread->stfbi); + } + + if (gdraw->base.Type == EGL_WINDOW_BIT) { + gctx->base.WindowRenderBuffer = + (gdraw->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) ? + EGL_SINGLE_BUFFER : EGL_BACK_BUFFER; + } + } + } + else if (old_gctx) { + ok = old_gctx->stapi->make_current(old_gctx->stapi, NULL, NULL, NULL); + old_gctx->base.WindowRenderBuffer = EGL_NONE; + } + + if (ctx && !_eglIsContextLinked(ctx)) + destroy_context(dpy, ctx); + if (draw && !_eglIsSurfaceLinked(draw)) + destroy_surface(dpy, draw); + if (read && read != draw && !_eglIsSurfaceLinked(read)) + destroy_surface(dpy, read); + + return ok; +} + +static EGLBoolean +egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + _EGLContext *ctx = _eglGetCurrentContext(); + struct egl_g3d_context *gctx = NULL; + + /* no-op for pixmap or pbuffer surface */ + if (gsurf->base.Type == EGL_PIXMAP_BIT || + gsurf->base.Type == EGL_PBUFFER_BIT) + return EGL_TRUE; + + /* or when the surface is single-buffered */ + if (gsurf->stvis.render_buffer == ST_ATTACHMENT_FRONT_LEFT) + return EGL_TRUE; + + if (ctx && ctx->DrawSurface == surf) + gctx = egl_g3d_context(ctx); + + /* flush if the surface is current */ + if (gctx) { + gctx->stctxi->flush(gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + } + + return gsurf->native->swap_buffers(gsurf->native); +} + +/** + * Get the pipe surface of the given attachment of the native surface. + */ +static struct pipe_surface * +get_pipe_surface(struct native_display *ndpy, struct native_surface *nsurf, + enum native_attachment natt, + unsigned bind) +{ + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; + struct pipe_surface *psurf; + + textures[natt] = NULL; + nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL); + if (!textures[natt]) + return NULL; + + psurf = ndpy->screen->get_tex_surface(ndpy->screen, textures[natt], + 0, 0, 0, bind); + pipe_resource_reference(&textures[natt], NULL); + + return psurf; +} + +static EGLBoolean +egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, + EGLNativePixmapType target) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + _EGLContext *ctx = _eglGetCurrentContext(); + struct egl_g3d_config *gconf; + struct native_surface *nsurf; + struct pipe_screen *screen = gdpy->native->screen; + struct pipe_surface *psurf; + + if (!gsurf->render_texture) + return EGL_TRUE; + + gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, target)); + if (!gconf) + return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); + + nsurf = gdpy->native->create_pixmap_surface(gdpy->native, + target, gconf->native); + if (!nsurf) + return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); + + /* flush if the surface is current */ + if (ctx && ctx->DrawSurface == &gsurf->base) { + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + gctx->stctxi->flush(gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + } + + /* create a pipe context to copy surfaces */ + if (!gdpy->pipe) { + gdpy->pipe = + gdpy->native->screen->context_create(gdpy->native->screen, NULL); + if (!gdpy->pipe) + return EGL_FALSE; + } + + psurf = get_pipe_surface(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT, + PIPE_BIND_BLIT_DESTINATION); + if (psurf) { + struct pipe_surface *psrc; + + psrc = screen->get_tex_surface(screen, gsurf->render_texture, + 0, 0, 0, PIPE_BIND_BLIT_SOURCE); + if (psrc) { + gdpy->pipe->surface_copy(gdpy->pipe, psurf, 0, 0, + psrc, 0, 0, psurf->width, psurf->height); + pipe_surface_reference(&psrc, NULL); + + nsurf->flush_frontbuffer(nsurf); + } + + pipe_surface_reference(&psurf, NULL); + } + + nsurf->destroy(nsurf); + + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_wait_client(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + struct pipe_screen *screen = gdpy->native->screen; + struct pipe_fence_handle *fence = NULL; + + gctx->stctxi->flush(gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence); + screen->fence_finish(screen, fence, 0); + screen->fence_reference(screen, &fence, NULL); + + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_wait_native(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine) +{ + _EGLContext *ctx = _eglGetCurrentContext(); + + if (engine != EGL_CORE_NATIVE_ENGINE) + return _eglError(EGL_BAD_PARAMETER, "eglWaitNative"); + + if (ctx && ctx->DrawSurface) { + struct egl_g3d_surface *gsurf = egl_g3d_surface(ctx->DrawSurface); + + if (gsurf->native) + gsurf->native->wait(gsurf->native); + } + + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLSurface *surf, EGLint buffer) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + _EGLContext *es1 = _eglGetAPIContext(EGL_OPENGL_ES_API); + struct egl_g3d_context *gctx; + enum pipe_format internal_format; + enum st_texture_type target; + + if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT) + return _eglError(EGL_BAD_SURFACE, "eglBindTexImage"); + if (buffer != EGL_BACK_BUFFER) + return _eglError(EGL_BAD_PARAMETER, "eglBindTexImage"); + if (gsurf->base.BoundToTexture) + return _eglError(EGL_BAD_ACCESS, "eglBindTexImage"); + + switch (gsurf->base.TextureFormat) { + case EGL_TEXTURE_RGB: + internal_format = PIPE_FORMAT_R8G8B8_UNORM; + break; + case EGL_TEXTURE_RGBA: + internal_format = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + default: + return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); + } + + switch (gsurf->base.TextureTarget) { + case EGL_TEXTURE_2D: + target = ST_TEXTURE_2D; + break; + default: + return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); + } + + if (!es1) + return EGL_TRUE; + if (!gsurf->render_texture) + return EGL_FALSE; + + /* flush properly if the surface is bound */ + if (gsurf->base.CurrentContext) { + gctx = egl_g3d_context(gsurf->base.CurrentContext); + gctx->stctxi->flush(gctx->stctxi, + PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); + } + + gctx = egl_g3d_context(es1); + if (gctx->stctxi->teximage) { + if (!gctx->stctxi->teximage(gctx->stctxi, target, + gsurf->base.MipmapLevel, internal_format, + gsurf->render_texture, gsurf->base.MipmapTexture)) + return EGL_FALSE; + gsurf->base.BoundToTexture = EGL_TRUE; + } + + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_release_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLSurface *surf, EGLint buffer) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + + if (!gsurf || gsurf->base.Type != EGL_PBUFFER_BIT || + !gsurf->base.BoundToTexture) + return _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage"); + if (buffer != EGL_BACK_BUFFER) + return _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage"); + + if (gsurf->render_texture) { + _EGLContext *ctx = _eglGetAPIContext(EGL_OPENGL_ES_API); + struct egl_g3d_context *gctx = egl_g3d_context(ctx); + + /* what if the context the surface binds to is no longer current? */ + if (gctx) { + gctx->stctxi->teximage(gctx->stctxi, ST_TEXTURE_2D, + gsurf->base.MipmapLevel, PIPE_FORMAT_NONE, NULL, FALSE); + } + } + + gsurf->base.BoundToTexture = EGL_FALSE; + + return EGL_TRUE; +} + +#ifdef EGL_MESA_screen_surface + +static _EGLSurface * +egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, const EGLint *attribs) +{ + struct egl_g3d_create_surface_arg arg; + + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_SCREEN_BIT_MESA; + + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); +} + +static EGLBoolean +egl_g3d_show_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLScreen *scr, _EGLSurface *surf, + _EGLMode *mode) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_screen *gscr = egl_g3d_screen(scr); + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + struct native_surface *nsurf; + const struct native_mode *nmode; + EGLBoolean changed; + + if (gsurf) { + EGLint idx; + + if (!mode) + return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA"); + if (gsurf->base.Type != EGL_SCREEN_BIT_MESA) + return _eglError(EGL_BAD_SURFACE, "eglShowScreenSurfaceMESA"); + if (gsurf->base.Width < mode->Width || gsurf->base.Height < mode->Height) + return _eglError(EGL_BAD_MATCH, + "eglShowSurfaceMESA(surface smaller than mode size)"); + + /* find the index of the mode */ + for (idx = 0; idx < gscr->base.NumModes; idx++) + if (mode == &gscr->base.Modes[idx]) + break; + if (idx >= gscr->base.NumModes) { + return _eglError(EGL_BAD_MODE_MESA, + "eglShowSurfaceMESA(unknown mode)"); + } + + nsurf = gsurf->native; + nmode = gscr->native_modes[idx]; + } + else { + if (mode) + return _eglError(EGL_BAD_MATCH, "eglShowSurfaceMESA"); + + /* disable the screen */ + nsurf = NULL; + nmode = NULL; + } + + /* TODO surface panning by CRTC choosing */ + changed = gdpy->native->modeset->program(gdpy->native, 0, nsurf, + gscr->base.OriginX, gscr->base.OriginY, &gscr->native, 1, nmode); + if (changed) { + gscr->base.CurrentSurface = &gsurf->base; + gscr->base.CurrentMode = mode; + } + + return changed; +} + +#endif /* EGL_MESA_screen_surface */ + +/** + * Find a config that supports the pixmap. + */ +_EGLConfig * +egl_g3d_find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_config *gconf; + EGLint i; + + for (i = 0; i < dpy->NumConfigs; i++) { + gconf = egl_g3d_config(dpy->Configs[i]); + if (gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native)) + break; + } + + return (i < dpy->NumConfigs) ? &gconf->base : NULL; +} + +void +egl_g3d_init_driver_api(_EGLDriver *drv) +{ + _eglInitDriverFallbacks(drv); + + drv->API.CreateContext = egl_g3d_create_context; + drv->API.DestroyContext = egl_g3d_destroy_context; + drv->API.CreateWindowSurface = egl_g3d_create_window_surface; + drv->API.CreatePixmapSurface = egl_g3d_create_pixmap_surface; + drv->API.CreatePbufferSurface = egl_g3d_create_pbuffer_surface; + drv->API.DestroySurface = egl_g3d_destroy_surface; + drv->API.MakeCurrent = egl_g3d_make_current; + drv->API.SwapBuffers = egl_g3d_swap_buffers; + drv->API.CopyBuffers = egl_g3d_copy_buffers; + drv->API.WaitClient = egl_g3d_wait_client; + drv->API.WaitNative = egl_g3d_wait_native; + + drv->API.BindTexImage = egl_g3d_bind_tex_image; + drv->API.ReleaseTexImage = egl_g3d_release_tex_image; + + drv->API.CreateImageKHR = egl_g3d_create_image; + drv->API.DestroyImageKHR = egl_g3d_destroy_image; + +#ifdef EGL_MESA_screen_surface + drv->API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface; + drv->API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface; +#endif +} diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.h b/src/gallium/state_trackers/egl/common/egl_g3d_api.h new file mode 100644 index 0000000000..d5196c12fe --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.h @@ -0,0 +1,37 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> + * + * 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. + */ + +#ifndef _EGL_G3D_API_H_ +#define _EGL_G3D_API_H_ + +#include "egl_g3d.h" + +void +egl_g3d_init_driver_api(_EGLDriver *drv); + +_EGLConfig * +egl_g3d_find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix); + +#endif /* _EGL_G3D_API_H_ */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c index d701f9c9a8..b1fe30a776 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c @@ -14,39 +14,39 @@ * 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, + * 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 - * BRIAN PAUL 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. + * 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 <olv@lunarg.com> */ -#include <assert.h> #include "pipe/p_screen.h" #include "util/u_memory.h" #include "util/u_rect.h" #include "util/u_inlines.h" #include "eglcurrent.h" -#include "egllog.h" #include "native.h" #include "egl_g3d.h" +#include "egl_g3d_api.h" #include "egl_g3d_image.h" /** * Reference and return the front left buffer of the native pixmap. */ -static struct pipe_texture * +static struct pipe_resource * egl_g3d_reference_native_pixmap(_EGLDisplay *dpy, EGLNativePixmapType pix) { struct egl_g3d_display *gdpy = egl_g3d_display(dpy); struct egl_g3d_config *gconf; struct native_surface *nsurf; - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; enum native_attachment natt; gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, pix)); @@ -72,7 +72,7 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attribs) { - struct pipe_texture *ptex; + struct pipe_resource *ptex; struct egl_g3d_image *gimg; unsigned face = 0, level = 0, zslice = 0; @@ -83,7 +83,7 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, } if (!_eglInitImage(&gimg->base, dpy, attribs)) { - free(gimg); + FREE(gimg); return NULL; } @@ -98,20 +98,20 @@ egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, } if (!ptex) { - free(gimg); + FREE(gimg); return NULL; } if (level > ptex->last_level) { _eglError(EGL_BAD_MATCH, "eglCreateEGLImageKHR"); - pipe_texture_reference(&gimg->texture, NULL); - free(gimg); + pipe_resource_reference(&gimg->texture, NULL); + FREE(gimg); return NULL; } if (zslice > ptex->depth0) { _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); - pipe_texture_reference(&gimg->texture, NULL); - free(gimg); + pipe_resource_reference(&gimg->texture, NULL); + FREE(gimg); return NULL; } @@ -129,8 +129,8 @@ egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img) { struct egl_g3d_image *gimg = egl_g3d_image(img); - pipe_texture_reference(&gimg->texture, NULL); - free(gimg); + pipe_resource_reference(&gimg->texture, NULL); + FREE(gimg); return EGL_TRUE; } diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.h b/src/gallium/state_trackers/egl/common/egl_g3d_image.h index c199c46645..adda933371 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_image.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.h @@ -14,12 +14,13 @@ * 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, + * 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 - * BRIAN PAUL 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. + * 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 <olv@lunarg.com> diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.c b/src/gallium/state_trackers/egl/common/egl_g3d_st.c new file mode 100644 index 0000000000..9744547868 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.c @@ -0,0 +1,312 @@ +/* + * 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 <olv@lunarg.com> + */ + +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_dl.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; +} + +struct st_api * +egl_g3d_create_st_api(enum st_api_type api) +{ + struct util_dl_library *lib; + const char *proc_name; + struct st_api * (*proc)(void) = NULL; + + switch (api) { + case ST_API_OPENGL: + proc_name = ST_CREATE_OPENGL_SYMBOL; + break; + case ST_API_OPENGL_ES1: + proc_name = ST_CREATE_OPENGL_ES1_SYMBOL; + break; + case ST_API_OPENGL_ES2: + proc_name = ST_CREATE_OPENGL_ES2_SYMBOL; + break; + case ST_API_OPENVG: + proc_name = ST_CREATE_OPENVG_SYMBOL; + break; + default: + assert(!"Unknown API Type\n"); + return NULL; + } + + lib = util_dl_open(NULL); + if (lib) { + proc = util_dl_get_proc_address(lib, proc_name); + debug_printf("%s: %s %p\n", __func__, proc_name, proc); + util_dl_close(lib); + } + + if (!proc) + return NULL; + + return proc(); +} + +static boolean +egl_g3d_st_manager_get_egl_image(struct st_manager *smapi, + struct st_egl_image *stimg) +{ + struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); + EGLImageKHR handle = (EGLImageKHR) stimg->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); + + stimg->texture = NULL; + pipe_resource_reference(&stimg->texture, gimg->texture); + stimg->face = gimg->face; + stimg->level = gimg->level; + stimg->zslice = gimg->zslice; + + _eglUnlockMutex(&gsmapi->display->Mutex); + + return TRUE; +} + +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; + } + + 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 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); + struct pipe_resource templ; + unsigned i; + + for (i = 0; i < count; i++) { + out[i] = NULL; + + if (gsurf->stvis.render_buffer != statts[i]) + continue; + + if (!gsurf->render_texture) { + struct egl_g3d_display *gdpy = + egl_g3d_display(gsurf->base.Resource.Display); + struct pipe_screen *screen = gdpy->native->screen; + + 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.format = gsurf->stvis.color_format; + templ.bind = PIPE_BIND_RENDER_TARGET; + + gsurf->render_texture = screen->resource_create(screen, &templ); + } + + 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); + + return gsurf->native->flush_frontbuffer(gsurf->native); +} + +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; + 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); +} diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.h b/src/gallium/state_trackers/egl/common/egl_g3d_st.h new file mode 100644 index 0000000000..c82681a22d --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.h @@ -0,0 +1,80 @@ +/* + * 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 <olv@lunarg.com> + */ + +#ifndef _EGL_G3D_ST_H_ +#define _EGL_G3D_ST_H_ + +#include "pipe/p_compiler.h" +#include "state_tracker/st_api.h" +#include "egltypedefs.h" + +struct st_api * +egl_g3d_create_st_api(enum st_api_type api); + +struct st_manager * +egl_g3d_create_st_manager(_EGLDisplay *dpy); + +void +egl_g3d_destroy_st_manager(struct st_manager *smapi); + +struct st_framebuffer_iface * +egl_g3d_create_st_framebuffer(_EGLSurface *surf); + +void +egl_g3d_destroy_st_framebuffer(struct st_framebuffer_iface *stfbi); + +/** + * Return the EGL_<api>_BIT of the st api. + */ +static INLINE int +egl_g3d_st_api_bit(enum st_api_type api) +{ + int bit; + + switch (api) { + case ST_API_OPENGL: + bit = EGL_OPENGL_BIT; + break; + case ST_API_OPENGL_ES1: + bit = EGL_OPENGL_ES_BIT; + break; + case ST_API_OPENGL_ES2: + bit = EGL_OPENGL_ES2_BIT; + break; + case ST_API_OPENVG: + bit = EGL_OPENVG_BIT; + break; + default: + bit = 0; + break; + } + + return bit; +} + +#endif /* _EGL_G3D_ST_H_ */ diff --git a/src/gallium/state_trackers/egl/common/egl_st.c b/src/gallium/state_trackers/egl/common/egl_st.c deleted file mode 100644 index a88ff911cd..0000000000 --- a/src/gallium/state_trackers/egl/common/egl_st.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 7.8 - * - * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> - * - * 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 - * BRIAN PAUL 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. - */ - -#include <dlfcn.h> -#include "pipe/p_compiler.h" -#include "util/u_memory.h" -#include "egllog.h" -#include "EGL/egl.h" /* for EGL_api_BIT */ - -#include "egl_st.h" - -#ifndef HAVE_DLADDR -#define HAVE_DLADDR 1 -#endif - -#if HAVE_DLADDR - -static const char * -egl_g3d_st_names[] = { -#define ST_PUBLIC(name, ...) #name, -#include "st_public_tmp.h" - NULL -}; - -static boolean -egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym) -{ - st_proc *procs = (st_proc *) stapi; - void *handle; - Dl_info info; - const char **name; - - if (!dladdr(sym, &info)) - return FALSE; - handle = dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE); - if (!handle) - return FALSE; - - for (name = egl_g3d_st_names; *name; name++) { - st_proc proc = (st_proc) dlsym(handle, *name); - if (!proc) { - _eglLog(_EGL_WARNING, "%s is missing in %s", *name, info.dli_fname); - memset(stapi, 0, sizeof(*stapi)); - dlclose(handle); - return FALSE; - } - *procs++ = proc; - } - - dlclose(handle); - return TRUE; -} - -#else /* HAVE_DLADDR */ - -static boolean -egl_g3d_fill_st(struct egl_g3d_st *stapi, void *sym) -{ -#define ST_PUBLIC(name, ...) stapi->name = name; -#include "st_public_tmp.h" - return TRUE; -} - -#endif /* HAVE_DLADDR */ - -static boolean -egl_g3d_init_st(struct egl_g3d_st *stapi, const char *api) -{ - void *handle, *sym; - boolean res = FALSE; - - /* already initialized */ - if (stapi->st_notify_swapbuffers != NULL) - return TRUE; - - handle = dlopen(NULL, RTLD_LAZY | RTLD_LOCAL); - if (!handle) - return FALSE; - - sym = dlsym(handle, api); - if (sym && egl_g3d_fill_st(stapi, sym)) - res = TRUE; - - dlclose(handle); - return res; -} - -static struct { - const char *symbol; - EGLint api_bit; -} egl_g3d_st_info[NUM_EGL_G3D_STS] = { - { "st_api_OpenGL_ES1", EGL_OPENGL_ES_BIT }, - { "st_api_OpenVG", EGL_OPENVG_BIT }, - { "st_api_OpenGL_ES2", EGL_OPENGL_ES2_BIT }, - { "st_api_OpenGL", EGL_OPENGL_BIT }, -}; - -const struct egl_g3d_st * -egl_g3d_get_st(enum egl_g3d_st_api api) -{ - static struct egl_g3d_st all_trackers[NUM_EGL_G3D_STS]; - - if (egl_g3d_init_st(&all_trackers[api], egl_g3d_st_info[api].symbol)) { - all_trackers[api].api_bit = egl_g3d_st_info[api].api_bit; - return &all_trackers[api]; - } - else { - return NULL; - } -} diff --git a/src/gallium/state_trackers/egl/common/egl_st.h b/src/gallium/state_trackers/egl/common/egl_st.h deleted file mode 100644 index 8fb464bd3d..0000000000 --- a/src/gallium/state_trackers/egl/common/egl_st.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 7.8 - * - * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> - * - * 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 - * BRIAN PAUL 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. - */ - -#ifndef _EGL_ST_H_ -#define _EGL_ST_H_ - -#include "GL/gl.h" /* for GL types */ -#include "GL/internal/glcore.h" /* for __GLcontextModes */ - -#include "pipe/p_compiler.h" -#include "pipe/p_format.h" -#include "pipe/p_context.h" - -/* avoid calling st functions directly */ -#if 1 - -#define ST_SURFACE_FRONT_LEFT 0 -#define ST_SURFACE_BACK_LEFT 1 -#define ST_SURFACE_FRONT_RIGHT 2 -#define ST_SURFACE_BACK_RIGHT 3 - -#define ST_TEXTURE_2D 0x2 - -struct st_context; -struct st_framebuffer; -typedef void (*st_proc)(); - -#else -#include "state_tracker/st_public.h" -#endif - -/* remember to update egl_g3d_get_st() when update the enums */ -enum egl_g3d_st_api { - EGL_G3D_ST_OPENGL_ES = 0, - EGL_G3D_ST_OPENVG, - EGL_G3D_ST_OPENGL_ES2, - EGL_G3D_ST_OPENGL, - - NUM_EGL_G3D_STS -}; - -struct egl_g3d_st { -#define ST_PUBLIC(name, ret, ...) ret (*name)(__VA_ARGS__); -#include "st_public_tmp.h" - /* fields must be added here */ - EGLint api_bit; -}; - -const struct egl_g3d_st * -egl_g3d_get_st(enum egl_g3d_st_api api); - -#endif /* _EGL_ST_H_ */ diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h index 9c22ff3e43..3f60348c48 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -14,26 +14,26 @@ * 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, + * 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 - * BRIAN PAUL 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. + * 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. */ #ifndef _NATIVE_H_ #define _NATIVE_H_ #include "EGL/egl.h" /* for EGL native types */ -#include "GL/gl.h" /* for GL types needed by __GLcontextModes */ -#include "GL/internal/glcore.h" /* for __GLcontextModes */ #include "pipe/p_compiler.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "native_probe.h" #include "native_modeset.h" /** @@ -57,27 +57,6 @@ enum native_param_type { NATIVE_PARAM_USE_NATIVE_BUFFER }; -/** - * Enumerations for probe results. - */ -enum native_probe_result { - NATIVE_PROBE_UNKNOWN, - NATIVE_PROBE_FALLBACK, - NATIVE_PROBE_SUPPORTED, - NATIVE_PROBE_EXACT, -}; - -/** - * A probe object for display probe. - */ -struct native_probe { - int magic; - EGLNativeDisplayType display; - void *data; - - void (*destroy)(struct native_probe *nprobe); -}; - struct native_surface { /** * Available for caller's use. @@ -112,7 +91,7 @@ struct native_surface { * behavior might change in the future. */ boolean (*validate)(struct native_surface *nsurf, uint attachment_mask, - unsigned int *seq_num, struct pipe_texture **textures, + unsigned int *seq_num, struct pipe_resource **textures, int *width, int *height); /** @@ -121,15 +100,26 @@ struct native_surface { void (*wait)(struct native_surface *nsurf); }; +/** + * Describe a native display config. + */ struct native_config { - /* __GLcontextModes should go away some day */ - __GLcontextModes mode; + /* available buffers and their format */ + uint buffer_mask; enum pipe_format color_format; - enum pipe_format depth_format; - enum pipe_format stencil_format; - /* treat it as an additional flag to mode.drawableType */ + /* supported surface types */ + boolean window_bit; + boolean pixmap_bit; boolean scanout_bit; + + int native_visual_id; + int native_visual_type; + int level; + int samples; + boolean slow_config; + boolean transparent_rgb; + int transparent_rgb_values[3]; }; /** @@ -140,9 +130,6 @@ struct native_config { struct native_display { /** * The pipe screen of the native display. - * - * Note that the "flush_frontbuffer" and "update_buffer" callbacks will be - * overridden. */ struct pipe_screen *screen; @@ -163,18 +150,14 @@ struct native_display { /** * Get the supported configs. The configs are owned by the display, but - * the returned array should be free()ed. - * - * The configs will be converted to EGL config by - * _eglConfigFromContextModesRec and validated by _eglValidateConfig. - * Those failing to pass the test will be skipped. + * the returned array should be FREE()ed. */ const struct native_config **(*get_configs)(struct native_display *ndpy, int *num_configs); /** * Test if a pixmap is supported by the given config. Required unless no - * config has GLX_PIXMAP_BIT set. + * config has pixmap_bit set. * * This function is usually called to find a config that supports a given * pixmap. Thus, it is usually called with the same pixmap in a row. @@ -185,29 +168,19 @@ struct native_display { /** - * Create a window surface. Required unless no config has GLX_WINDOW_BIT - * set. + * Create a window surface. Required unless no config has window_bit set. */ struct native_surface *(*create_window_surface)(struct native_display *ndpy, EGLNativeWindowType win, const struct native_config *nconf); /** - * Create a pixmap surface. Required unless no config has GLX_PIXMAP_BIT - * set. + * Create a pixmap surface. Required unless no config has pixmap_bit set. */ struct native_surface *(*create_pixmap_surface)(struct native_display *ndpy, EGLNativePixmapType pix, const struct native_config *nconf); - /** - * Create a pbuffer surface. Required unless no config has GLX_PBUFFER_BIT - * set. - */ - struct native_surface *(*create_pbuffer_surface)(struct native_display *ndpy, - const struct native_config *nconf, - uint width, uint height); - const struct native_display_modeset *modeset; }; @@ -234,22 +207,6 @@ native_attachment_mask_test(uint mask, enum native_attachment att) return !!(mask & (1 << att)); } -/** - * Return a probe object for the given display. - * - * Note that the returned object may be cached and used by different native - * display modules. It allows fast probing when multiple modules probe the - * same display. - */ -struct native_probe * -native_create_probe(EGLNativeDisplayType dpy); - -/** - * Probe the probe object. - */ -enum native_probe_result -native_get_probe_result(struct native_probe *nprobe); - const char * native_get_name(void); diff --git a/src/gallium/state_trackers/egl/common/native_modeset.h b/src/gallium/state_trackers/egl/common/native_modeset.h index 71dc3ec860..dee757b3a8 100644 --- a/src/gallium/state_trackers/egl/common/native_modeset.h +++ b/src/gallium/state_trackers/egl/common/native_modeset.h @@ -14,12 +14,13 @@ * 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, + * 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 - * BRIAN PAUL 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. + * 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. */ #ifndef _NATIVE_MODESET_H_ @@ -63,8 +64,8 @@ struct native_display_modeset { int *num_modes); /** - * Create a scan-out surface. Required unless no config has - * GLX_SCREEN_BIT_MESA set. + * Create a scan-out surface. Required unless no config has scanout_bit + * set. */ struct native_surface *(*create_scanout_surface)(struct native_display *ndpy, const struct native_config *nconf, diff --git a/src/gallium/state_trackers/egl/common/native_probe.h b/src/gallium/state_trackers/egl/common/native_probe.h new file mode 100644 index 0000000000..aeed9f85dd --- /dev/null +++ b/src/gallium/state_trackers/egl/common/native_probe.h @@ -0,0 +1,68 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> + * + * 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. + */ + +#ifndef _NATIVE_PROBE_H_ +#define _NATIVE_PROBE_H_ + +#include "EGL/egl.h" /* for EGL native types */ + +/** + * Enumerations for probe results. + */ +enum native_probe_result { + NATIVE_PROBE_UNKNOWN, + NATIVE_PROBE_FALLBACK, + NATIVE_PROBE_SUPPORTED, + NATIVE_PROBE_EXACT, +}; + +/** + * A probe object for display probe. + */ +struct native_probe { + int magic; + EGLNativeDisplayType display; + void *data; + + void (*destroy)(struct native_probe *nprobe); +}; + +/** + * Return a probe object for the given display. + * + * Note that the returned object may be cached and used by different native + * display modules. It allows fast probing when multiple modules probe the + * same display. + */ +struct native_probe * +native_create_probe(EGLNativeDisplayType dpy); + +/** + * Probe the probe object. + */ +enum native_probe_result +native_get_probe_result(struct native_probe *nprobe); + +#endif /* _NATIVE_PROBE_H_ */ diff --git a/src/gallium/state_trackers/egl/common/st_public_tmp.h b/src/gallium/state_trackers/egl/common/st_public_tmp.h deleted file mode 100644 index 507a0ec402..0000000000 --- a/src/gallium/state_trackers/egl/common/st_public_tmp.h +++ /dev/null @@ -1,20 +0,0 @@ -ST_PUBLIC(st_create_context, struct st_context *, struct pipe_context *pipe, const __GLcontextModes *visual, struct st_context *share) -ST_PUBLIC(st_destroy_context, void, struct st_context *st) -ST_PUBLIC(st_copy_context_state, void, struct st_context *dst, struct st_context *src, uint mask) -ST_PUBLIC(st_create_framebuffer, struct st_framebuffer *, const __GLcontextModes *visual, enum pipe_format colorFormat, enum pipe_format depthFormat, enum pipe_format stencilFormat, uint width, uint height, void *privateData) -ST_PUBLIC(st_resize_framebuffer, void, struct st_framebuffer *stfb, uint width, uint height) -ST_PUBLIC(st_set_framebuffer_surface, void, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface *surf) -ST_PUBLIC(st_get_framebuffer_dimensions, void, struct st_framebuffer *stfb, uint *width, uint *height) -ST_PUBLIC(st_get_framebuffer_surface, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_surface **surface) -ST_PUBLIC(st_get_framebuffer_texture, int, struct st_framebuffer *stfb, uint surfIndex, struct pipe_texture **texture) -ST_PUBLIC(st_framebuffer_private, void *, struct st_framebuffer *stfb) -ST_PUBLIC(st_unreference_framebuffer, void, struct st_framebuffer *stfb) -ST_PUBLIC(st_make_current, GLboolean, struct st_context *st, struct st_framebuffer *draw, struct st_framebuffer *read) -ST_PUBLIC(st_get_current, struct st_context *, void) -ST_PUBLIC(st_flush, void, struct st_context *st, uint pipeFlushFlags, struct pipe_fence_handle **fence) -ST_PUBLIC(st_finish, void, struct st_context *st) -ST_PUBLIC(st_notify_swapbuffers, void, struct st_framebuffer *stfb) -ST_PUBLIC(st_bind_texture_surface, int, struct pipe_surface *ps, int target, int level, enum pipe_format format) -ST_PUBLIC(st_unbind_texture_surface, int, struct pipe_surface *ps, int target, int level) -ST_PUBLIC(st_get_proc_address, st_proc, const char *procname) -#undef ST_PUBLIC |