diff options
Diffstat (limited to 'src/gallium/state_trackers/egl')
25 files changed, 2325 insertions, 2279 deletions
diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile index 794785006f5..1768241352f 100644 --- a/src/gallium/state_trackers/egl/Makefile +++ b/src/gallium/state_trackers/egl/Makefile @@ -16,6 +16,7 @@ x11_INCLUDES = \ -I$(TOP)/src/gallium/drivers \ -I$(TOP)/src/glx \ -I$(TOP)/src/mesa \ + $(X11_CFLAGS) \ $(shell pkg-config --cflags-only-I libdrm) x11_SOURCES = $(wildcard x11/*.c) \ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index 04268c71c5a..3ab72dce2f3 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -14,276 +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_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. @@ -298,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) @@ -350,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 @@ -392,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; } @@ -407,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; } @@ -437,100 +160,275 @@ 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; + } + } + + fmt += n; + } - if (gsurf) - gsurf->native->flush_frontbuffer(gsurf->native); + return count; } /** - * Re-validate the context. + * Add configs to display and return the next config ID. */ +static EGLint +egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) +{ + 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 -egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private) +egl_g3d_invalid_surface(struct native_display *ndpy, + struct native_surface *nsurf, + unsigned int seq_num) { - struct egl_g3d_context *gctx = egl_g3d_context(context_private); - egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base); + /* XXX not thread safe? */ + struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data); + 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->stctxi->notify_invalid_framebuffer(gctx->stctxi, gsurf->stfbi); } +static struct native_event_handler egl_g3d_native_event_handler = { + .invalid_surface = egl_g3d_invalid_surface +}; + static EGLBoolean egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) { @@ -540,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; @@ -575,18 +479,25 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, } dpy->DriverData = gdpy; - gdpy->native = native_create_display(dpy->NativeDisplay); + gdpy->native = native_create_display(dpy->NativeDisplay, + &egl_g3d_native_event_handler); if (!gdpy->native) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); goto fail; } - gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer; - gdpy->native->screen->update_buffer = egl_g3d_update_buffer; + gdpy->native->user_data = (void *) dpy; 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) { @@ -595,6 +506,10 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, } #endif + dpy->Extensions.KHR_image_base = EGL_TRUE; + if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER)) + dpy->Extensions.KHR_image_pixmap = EGL_TRUE; + if (egl_g3d_add_configs(drv, dpy, 1) == 1) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); goto fail; @@ -611,448 +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; - } - - 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. - */ -static _EGLConfig * -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(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) { @@ -1063,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; } @@ -1075,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) { @@ -1263,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 * @@ -1274,38 +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; - -#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 5d2d9c481ab..5a3c80b9689 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_ @@ -34,15 +35,16 @@ #include "eglcontext.h" #include "eglsurface.h" #include "eglconfig.h" +#include "eglimage.h" #include "eglscreen.h" #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; @@ -50,35 +52,44 @@ 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_resource *texture; + unsigned face; + unsigned level; + unsigned zslice; }; struct egl_g3d_screen { @@ -90,5 +101,6 @@ struct egl_g3d_screen { /* standard typecasts */ _EGL_DRIVER_STANDARD_TYPECASTS(egl_g3d) _EGL_DRIVER_TYPECAST(egl_g3d_screen, _EGLScreen, obj) +_EGL_DRIVER_TYPECAST(egl_g3d_image, _EGLImage, obj) #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 00000000000..478516453ce --- /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 <[email protected]> + * + * 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 00000000000..d5196c12fe9 --- /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 <[email protected]> + * + * 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 new file mode 100644 index 00000000000..b1fe30a776c --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c @@ -0,0 +1,136 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * 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 <[email protected]> + */ + +#include "pipe/p_screen.h" +#include "util/u_memory.h" +#include "util/u_rect.h" +#include "util/u_inlines.h" +#include "eglcurrent.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_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_resource *textures[NUM_NATIVE_ATTACHMENTS]; + enum native_attachment natt; + + gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, pix)); + if (!gconf) + return NULL; + + nsurf = gdpy->native->create_pixmap_surface(gdpy->native, + pix, gconf->native); + if (!nsurf) + return NULL; + + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + if (!nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL)) + textures[natt] = NULL; + + nsurf->destroy(nsurf); + + return textures[natt]; +} + +_EGLImage * +egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, + EGLenum target, EGLClientBuffer buffer, + const EGLint *attribs) +{ + struct pipe_resource *ptex; + struct egl_g3d_image *gimg; + unsigned face = 0, level = 0, zslice = 0; + + gimg = CALLOC_STRUCT(egl_g3d_image); + if (!gimg) { + _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); + return NULL; + } + + if (!_eglInitImage(&gimg->base, dpy, attribs)) { + FREE(gimg); + return NULL; + } + + switch (target) { + case EGL_NATIVE_PIXMAP_KHR: + ptex = egl_g3d_reference_native_pixmap(dpy, + (EGLNativePixmapType) buffer); + break; + default: + ptex = NULL; + break; + } + + if (!ptex) { + FREE(gimg); + return NULL; + } + + if (level > ptex->last_level) { + _eglError(EGL_BAD_MATCH, "eglCreateEGLImageKHR"); + pipe_resource_reference(&gimg->texture, NULL); + FREE(gimg); + return NULL; + } + if (zslice > ptex->depth0) { + _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); + pipe_resource_reference(&gimg->texture, NULL); + FREE(gimg); + return NULL; + } + + /* transfer the ownership to the image */ + gimg->texture = ptex; + gimg->face = face; + gimg->level = level; + gimg->zslice = zslice; + + return &gimg->base; +} + +EGLBoolean +egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img) +{ + struct egl_g3d_image *gimg = egl_g3d_image(img); + + 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 new file mode 100644 index 00000000000..adda9333715 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.h @@ -0,0 +1,42 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * 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 <[email protected]> + */ + +#ifndef _EGL_G3D_IMAGE_H_ +#define _EGL_G3D_IMAGE_H_ + +#include "egl_g3d.h" + +_EGLImage * +egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, + EGLenum target, EGLClientBuffer buffer, + const EGLint *attribs); + +EGLBoolean +egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image); + +#endif /* _EGL_G3D_IMAGE_H_ */ 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 00000000000..97445478684 --- /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 <[email protected]> + */ + +#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 00000000000..c82681a22d8 --- /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 <[email protected]> + */ + +#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 a88ff911cd5..00000000000 --- 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 <[email protected]> - * - * 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 8fb464bd3d7..00000000000 --- 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 <[email protected]> - * - * 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 4f9758545ab..3f60348c489 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -14,26 +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. */ #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" + /** * Only color buffers are listed. The others are allocated privately through, * for example, st_renderbuffer_alloc_storage(). @@ -47,28 +49,20 @@ enum native_attachment { NUM_NATIVE_ATTACHMENTS }; -/** - * 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); +enum native_param_type { + /* + * Return TRUE if window/pixmap surfaces use the buffers of the native + * types. + */ + NATIVE_PARAM_USE_NATIVE_BUFFER }; struct native_surface { + /** + * Available for caller's use. + */ + void *user_data; + void (*destroy)(struct native_surface *nsurf); /** @@ -97,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); /** @@ -106,29 +100,28 @@ 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; -}; -struct native_connector { - int dummy; + int native_visual_id; + int native_visual_type; + int level; + int samples; + boolean slow_config; + boolean transparent_rgb; + int transparent_rgb_values[3]; }; -struct native_mode { - const char *desc; - int width, height; - int refresh_rate; -}; - -struct native_display_modeset; - /** * A pipe winsys abstracts the OS. A pipe screen abstracts the graphcis * hardware. A native display consists of a pipe winsys, a pipe screen, and @@ -137,28 +130,34 @@ struct native_display_modeset; 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; + /** + * Available for caller's use. + */ + void *user_data; + void (*destroy)(struct native_display *ndpy); /** - * Get the supported configs. The configs are owned by the display, but - * the returned array should be free()ed. + * Query the parameters of the native display. * - * The configs will be converted to EGL config by - * _eglConfigFromContextModesRec and validated by _eglValidateConfig. - * Those failing to pass the test will be skipped. + * The return value is defined by the parameter. + */ + int (*get_param)(struct native_display *ndpy, + enum native_param_type param); + + /** + * Get the supported configs. The configs are owned by the display, but + * 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. @@ -169,73 +168,34 @@ 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; }; /** - * Mode setting interface of the native display. It exposes the mode setting - * capabilities of the underlying graphics hardware. + * The handler for events that a native display may generate. The events are + * generated asynchronously and the handler may be called by any thread at any + * time. */ -struct native_display_modeset { - /** - * Get the available physical connectors and the number of CRTCs. - */ - const struct native_connector **(*get_connectors)(struct native_display *ndpy, - int *num_connectors, - int *num_crtcs); - - /** - * Get the current supported modes of a connector. The returned modes may - * change every time this function is called and those from previous calls - * might become invalid. - */ - const struct native_mode **(*get_modes)(struct native_display *ndpy, - const struct native_connector *nconn, - int *num_modes); - +struct native_event_handler { /** - * Create a scan-out surface. Required unless no config has - * GLX_SCREEN_BIT_MESA set. + * This function is called when a surface needs to be validated. */ - struct native_surface *(*create_scanout_surface)(struct native_display *ndpy, - const struct native_config *nconf, - uint width, uint height); - - /** - * Program the CRTC to output the surface to the given connectors with the - * given mode. When surface is not given, the CRTC is disabled. - * - * This interface does not export a way to query capabilities of the CRTCs. - * The native display usually needs to dynamically map the index to a CRTC - * that supports the given connectors. - */ - boolean (*program)(struct native_display *ndpy, int crtc_idx, - struct native_surface *nsurf, uint x, uint y, - const struct native_connector **nconns, int num_nconns, - const struct native_mode *nmode); + void (*invalid_surface)(struct native_display *ndpy, + struct native_surface *nsurf, + unsigned int seq_num); }; /** @@ -247,26 +207,11 @@ 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); struct native_display * -native_create_display(EGLNativeDisplayType dpy); +native_create_display(EGLNativeDisplayType dpy, + struct native_event_handler *handler); #endif /* _NATIVE_H_ */ diff --git a/src/gallium/state_trackers/egl/common/native_modeset.h b/src/gallium/state_trackers/egl/common/native_modeset.h new file mode 100644 index 00000000000..dee757b3a88 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/native_modeset.h @@ -0,0 +1,88 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu <[email protected]> + * + * 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_MODESET_H_ +#define _NATIVE_MODESET_H_ + +#include "pipe/p_compiler.h" + +struct native_display; +struct native_surface; +struct native_config; + +struct native_connector { + int dummy; +}; + +struct native_mode { + const char *desc; + int width, height; + int refresh_rate; +}; + +/** + * Mode setting interface of the native display. It exposes the mode setting + * capabilities of the underlying graphics hardware. + */ +struct native_display_modeset { + /** + * Get the available physical connectors and the number of CRTCs. + */ + const struct native_connector **(*get_connectors)(struct native_display *ndpy, + int *num_connectors, + int *num_crtcs); + + /** + * Get the current supported modes of a connector. The returned modes may + * change every time this function is called and those from previous calls + * might become invalid. + */ + const struct native_mode **(*get_modes)(struct native_display *ndpy, + const struct native_connector *nconn, + int *num_modes); + + /** + * 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, + uint width, uint height); + + /** + * Program the CRTC to output the surface to the given connectors with the + * given mode. When surface is not given, the CRTC is disabled. + * + * This interface does not export a way to query capabilities of the CRTCs. + * The native display usually needs to dynamically map the index to a CRTC + * that supports the given connectors. + */ + boolean (*program)(struct native_display *ndpy, int crtc_idx, + struct native_surface *nsurf, uint x, uint y, + const struct native_connector **nconns, int num_nconns, + const struct native_mode *nmode); +}; + +#endif /* _NATIVE_MODESET_H_ */ 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 00000000000..aeed9f85dd5 --- /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 <[email protected]> + * + * 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 507a0ec4027..00000000000 --- 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 diff --git a/src/gallium/state_trackers/egl/kms/native_kms.c b/src/gallium/state_trackers/egl/kms/native_kms.c index aedf3d430ca..cf7188dfdb7 100644 --- a/src/gallium/state_trackers/egl/kms/native_kms.c +++ b/src/gallium/state_trackers/egl/kms/native_kms.c @@ -14,35 +14,34 @@ * 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 <stdio.h> -#include <string.h> - #include "pipe/p_screen.h" #include "pipe/p_context.h" #include "util/u_debug.h" #include "util/u_memory.h" #include "util/u_inlines.h" +#include "util/u_string.h" #include "egllog.h" #include "native_kms.h" static boolean kms_surface_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) { struct kms_surface *ksurf = kms_surface(nsurf); struct kms_display *kdpy = ksurf->kdpy; struct pipe_screen *screen = kdpy->base.screen; - struct pipe_texture templ, *ptex; + struct pipe_resource templ, *ptex; int att; if (attachment_mask) { @@ -53,9 +52,7 @@ kms_surface_validate(struct native_surface *nsurf, uint attachment_mask, templ.height0 = ksurf->height; templ.depth0 = 1; templ.format = ksurf->color_format; - templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - if (ksurf->type == KMS_SURFACE_TYPE_SCANOUT) - templ.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; + templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SCANOUT; } /* create textures */ @@ -66,13 +63,13 @@ kms_surface_validate(struct native_surface *nsurf, uint attachment_mask, ptex = ksurf->textures[att]; if (!ptex) { - ptex = screen->texture_create(screen, &templ); + ptex = screen->resource_create(screen, &templ); ksurf->textures[att] = ptex; } if (textures) { textures[att] = NULL; - pipe_texture_reference(&textures[att], ptex); + pipe_resource_reference(&textures[att], ptex); } } @@ -100,7 +97,7 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) for (i = 0; i < num_framebuffers; i++) { struct kms_framebuffer *fb; enum native_attachment natt; - unsigned int handle, stride; + struct winsys_handle whandle; uint block_bits; if (i == 0) { @@ -118,7 +115,7 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) if (!ksurf->textures[natt]) return FALSE; - pipe_texture_reference(&fb->texture, ksurf->textures[natt]); + pipe_resource_reference(&fb->texture, ksurf->textures[natt]); } /* already initialized */ @@ -128,13 +125,17 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) /* TODO detect the real value */ fb->is_passive = TRUE; - if (!kdpy->api->local_handle_from_texture(kdpy->api, - kdpy->base.screen, fb->texture, &stride, &handle)) + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_KMS; + + if (!kdpy->base.screen->resource_get_handle(kdpy->base.screen, + fb->texture, &whandle)) return FALSE; block_bits = util_format_get_blocksizebits(ksurf->color_format); err = drmModeAddFB(kdpy->fd, ksurf->width, ksurf->height, - block_bits, block_bits, stride, handle, &fb->buffer_id); + block_bits, block_bits, whandle.stride, whandle.handle, + &fb->buffer_id); if (err) { fb->buffer_id = 0; return FALSE; @@ -151,10 +152,6 @@ kms_surface_flush_frontbuffer(struct native_surface *nsurf) struct kms_surface *ksurf = kms_surface(nsurf); struct kms_display *kdpy = ksurf->kdpy; - /* pbuffer is private */ - if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER) - return TRUE; - if (ksurf->front_fb.is_passive) drmModeDirtyFB(kdpy->fd, ksurf->front_fb.buffer_id, NULL, 0); #endif @@ -169,13 +166,9 @@ kms_surface_swap_buffers(struct native_surface *nsurf) struct kms_crtc *kcrtc = &ksurf->current_crtc; struct kms_display *kdpy = ksurf->kdpy; struct kms_framebuffer tmp_fb; - struct pipe_texture *tmp_texture; + struct pipe_resource *tmp_texture; int err; - /* pbuffer is private */ - if (ksurf->type == KMS_SURFACE_TYPE_PBUFFER) - return TRUE; - if (!ksurf->back_fb.buffer_id) { if (!kms_surface_init_framebuffers(&ksurf->base, TRUE)) return FALSE; @@ -201,6 +194,8 @@ kms_surface_swap_buffers(struct native_surface *nsurf) /* the front/back textures are swapped */ ksurf->sequence_number++; + kdpy->event_handler->invalid_surface(&kdpy->base, + &ksurf->base, ksurf->sequence_number); return TRUE; } @@ -222,23 +217,22 @@ kms_surface_destroy(struct native_surface *nsurf) if (ksurf->front_fb.buffer_id) drmModeRmFB(ksurf->kdpy->fd, ksurf->front_fb.buffer_id); - pipe_texture_reference(&ksurf->front_fb.texture, NULL); + pipe_resource_reference(&ksurf->front_fb.texture, NULL); if (ksurf->back_fb.buffer_id) drmModeRmFB(ksurf->kdpy->fd, ksurf->back_fb.buffer_id); - pipe_texture_reference(&ksurf->back_fb.texture, NULL); + pipe_resource_reference(&ksurf->back_fb.texture, NULL); for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct pipe_texture *ptex = ksurf->textures[i]; - pipe_texture_reference(&ptex, NULL); + struct pipe_resource *ptex = ksurf->textures[i]; + pipe_resource_reference(&ptex, NULL); } - free(ksurf); + FREE(ksurf); } static struct kms_surface * kms_display_create_surface(struct native_display *ndpy, - enum kms_surface_type type, const struct native_config *nconf, uint width, uint height) { @@ -251,7 +245,6 @@ kms_display_create_surface(struct native_display *ndpy, return NULL; ksurf->kdpy = kdpy; - ksurf->type = type; ksurf->color_format = kconf->base.color_format; ksurf->width = width; ksurf->height = height; @@ -469,7 +462,7 @@ kms_display_get_modes(struct native_display *ndpy, /* delete old data */ if (kconn->connector) { drmModeFreeConnector(kconn->connector); - free(kconn->kms_modes); + FREE(kconn->kms_modes); kconn->connector = NULL; kconn->kms_modes = NULL; @@ -482,7 +475,7 @@ kms_display_get_modes(struct native_display *ndpy, return NULL; count = kconn->connector->count_modes; - kconn->kms_modes = calloc(count, sizeof(*kconn->kms_modes)); + kconn->kms_modes = CALLOC(count, sizeof(*kconn->kms_modes)); if (!kconn->kms_modes) { drmModeFreeConnector(kconn->connector); kconn->connector = NULL; @@ -505,7 +498,7 @@ kms_display_get_modes(struct native_display *ndpy, kmode->base.refresh_rate = (kmode->base.refresh_rate + 500) / 1000; } - nmodes_return = malloc(count * sizeof(*nmodes_return)); + nmodes_return = MALLOC(count * sizeof(*nmodes_return)); if (nmodes_return) { for (i = 0; i < count; i++) nmodes_return[i] = &kconn->kms_modes[i].base; @@ -526,7 +519,7 @@ kms_display_get_connectors(struct native_display *ndpy, int *num_connectors, if (!kdpy->connectors) { kdpy->connectors = - calloc(kdpy->resources->count_connectors, sizeof(*kdpy->connectors)); + CALLOC(kdpy->resources->count_connectors, sizeof(*kdpy->connectors)); if (!kdpy->connectors) return NULL; @@ -540,7 +533,7 @@ kms_display_get_connectors(struct native_display *ndpy, int *num_connectors, kdpy->num_connectors = kdpy->resources->count_connectors; } - connectors = malloc(kdpy->num_connectors * sizeof(*connectors)); + connectors = MALLOC(kdpy->num_connectors * sizeof(*connectors)); if (connectors) { for (i = 0; i < kdpy->num_connectors; i++) connectors[i] = &kdpy->connectors[i].base; @@ -561,32 +554,18 @@ kms_display_create_scanout_surface(struct native_display *ndpy, { struct kms_surface *ksurf; - ksurf = kms_display_create_surface(ndpy, - KMS_SURFACE_TYPE_SCANOUT, nconf, width, height); - return &ksurf->base; -} - -static struct native_surface * -kms_display_create_pbuffer_surface(struct native_display *ndpy, - const struct native_config *nconf, - uint width, uint height) -{ - struct kms_surface *ksurf; - - ksurf = kms_display_create_surface(ndpy, - KMS_SURFACE_TYPE_PBUFFER, nconf, width, height); + ksurf = kms_display_create_surface(ndpy, nconf, width, height); return &ksurf->base; } - static boolean kms_display_is_format_supported(struct native_display *ndpy, enum pipe_format fmt, boolean is_color) { return ndpy->screen->is_format_supported(ndpy->screen, fmt, PIPE_TEXTURE_2D, - (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET : - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); + (is_color) ? PIPE_BIND_RENDER_TARGET : + PIPE_BIND_DEPTH_STENCIL, 0); } static const struct native_config ** @@ -600,14 +579,15 @@ kms_display_get_configs(struct native_display *ndpy, int *num_configs) struct native_config *nconf; enum pipe_format format; - kdpy->config = calloc(1, sizeof(*kdpy->config)); + kdpy->config = CALLOC(1, sizeof(*kdpy->config)); if (!kdpy->config) return NULL; nconf = &kdpy->config->base; - /* always double-buffered */ - nconf->mode.doubleBufferMode = TRUE; + nconf->buffer_mask = + (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | + (1 << NATIVE_ATTACHMENT_BACK_LEFT); format = PIPE_FORMAT_B8G8R8A8_UNORM; if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) { @@ -615,45 +595,18 @@ kms_display_get_configs(struct native_display *ndpy, int *num_configs) if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) format = PIPE_FORMAT_NONE; } - if (format == PIPE_FORMAT_NONE) + if (format == PIPE_FORMAT_NONE) { + FREE(kdpy->config); + kdpy->config = NULL; return NULL; + } nconf->color_format = format; - nconf->mode.redBits = 8; - nconf->mode.greenBits = 8; - nconf->mode.blueBits = 8; - nconf->mode.alphaBits = 8; - nconf->mode.rgbBits = 32; - - format = PIPE_FORMAT_Z24S8_UNORM; - if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) { - format = PIPE_FORMAT_S8Z24_UNORM; - if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) - format = PIPE_FORMAT_NONE; - } - if (format != PIPE_FORMAT_NONE) { - nconf->depth_format = format; - nconf->stencil_format = format; - - nconf->mode.depthBits = 24; - nconf->mode.stencilBits = 8; - nconf->mode.haveDepthBuffer = TRUE; - nconf->mode.haveStencilBuffer = TRUE; - } nconf->scanout_bit = TRUE; - nconf->mode.drawableType = GLX_PBUFFER_BIT; - nconf->mode.swapMethod = GLX_SWAP_EXCHANGE_OML; - - nconf->mode.visualID = 0; - nconf->mode.visualType = EGL_NONE; - - nconf->mode.renderType = GLX_RGBA_BIT; - nconf->mode.rgbMode = TRUE; - nconf->mode.xRenderable = FALSE; } - configs = malloc(sizeof(*configs)); + configs = MALLOC(sizeof(*configs)); if (configs) { configs[0] = &kdpy->config->base; if (num_configs) @@ -663,6 +616,21 @@ kms_display_get_configs(struct native_display *ndpy, int *num_configs) return configs; } +static int +kms_display_get_param(struct native_display *ndpy, + enum native_param_type param) +{ + int val; + + switch (param) { + default: + val = 0; + break; + } + + return val; +} + static void kms_display_destroy(struct native_display *ndpy) { @@ -670,21 +638,21 @@ kms_display_destroy(struct native_display *ndpy) int i; if (kdpy->config) - free(kdpy->config); + FREE(kdpy->config); if (kdpy->connectors) { for (i = 0; i < kdpy->num_connectors; i++) { struct kms_connector *kconn = &kdpy->connectors[i]; if (kconn->connector) { drmModeFreeConnector(kconn->connector); - free(kconn->kms_modes); + FREE(kconn->kms_modes); } } - free(kdpy->connectors); + FREE(kdpy->connectors); } if (kdpy->shown_surfaces) - free(kdpy->shown_surfaces); + FREE(kdpy->shown_surfaces); if (kdpy->saved_crtcs) { for (i = 0; i < kdpy->resources->count_crtcs; i++) { @@ -700,7 +668,7 @@ kms_display_destroy(struct native_display *ndpy) drmModeFreeCrtc(kcrtc->crtc); } } - free(kdpy->saved_crtcs); + FREE(kdpy->saved_crtcs); } if (kdpy->resources) @@ -712,9 +680,9 @@ kms_display_destroy(struct native_display *ndpy) if (kdpy->fd >= 0) drmClose(kdpy->fd); - if (kdpy->api) + if (kdpy->api && kdpy->api->destroy) kdpy->api->destroy(kdpy->api); - free(kdpy); + FREE(kdpy); } /** @@ -724,10 +692,9 @@ static boolean kms_display_init_screen(struct native_display *ndpy) { struct kms_display *kdpy = kms_display(ndpy); - struct drm_create_screen_arg arg; int fd; - fd = drmOpen(kdpy->api->name, NULL); + fd = drmOpen(kdpy->api->driver_name, NULL); if (fd < 0) { _eglLog(_EGL_WARNING, "failed to open DRM device"); return FALSE; @@ -740,9 +707,7 @@ kms_display_init_screen(struct native_display *ndpy) } #endif - memset(&arg, 0, sizeof(arg)); - arg.mode = DRM_CREATE_NORMAL; - kdpy->base.screen = kdpy->api->create_screen(kdpy->api, fd, &arg); + kdpy->base.screen = kdpy->api->create_screen(kdpy->api, fd, NULL); if (!kdpy->base.screen) { _eglLog(_EGL_WARNING, "failed to create DRM screen"); drmClose(fd); @@ -762,7 +727,9 @@ static struct native_display_modeset kms_display_modeset = { }; static struct native_display * -kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api) +kms_create_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler, + struct drm_api *api) { struct kms_display *kdpy; @@ -770,10 +737,12 @@ kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api) if (!kdpy) return NULL; + kdpy->event_handler = event_handler; + kdpy->api = api; if (!kdpy->api) { _eglLog(_EGL_WARNING, "failed to create DRM API"); - free(kdpy); + FREE(kdpy); return NULL; } @@ -791,22 +760,22 @@ kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api) } kdpy->saved_crtcs = - calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs)); + CALLOC(kdpy->resources->count_crtcs, sizeof(*kdpy->saved_crtcs)); if (!kdpy->saved_crtcs) { kms_display_destroy(&kdpy->base); return NULL; } kdpy->shown_surfaces = - calloc(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces)); + CALLOC(kdpy->resources->count_crtcs, sizeof(*kdpy->shown_surfaces)); if (!kdpy->shown_surfaces) { kms_display_destroy(&kdpy->base); return NULL; } kdpy->base.destroy = kms_display_destroy; + kdpy->base.get_param = kms_display_get_param; kdpy->base.get_configs = kms_display_get_configs; - kdpy->base.create_pbuffer_surface = kms_display_create_pbuffer_surface; kdpy->base.modeset = &kms_display_modeset; @@ -837,15 +806,16 @@ native_get_name(void) drm_api = drm_api_create(); if (drm_api) - snprintf(kms_name, sizeof(kms_name), "KMS/%s", drm_api->name); + util_snprintf(kms_name, sizeof(kms_name), "KMS/%s", drm_api->name); else - snprintf(kms_name, sizeof(kms_name), "KMS"); + util_snprintf(kms_name, sizeof(kms_name), "KMS"); return kms_name; } struct native_display * -native_create_display(EGLNativeDisplayType dpy) +native_create_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler) { struct native_display *ndpy = NULL; @@ -853,7 +823,7 @@ native_create_display(EGLNativeDisplayType dpy) drm_api = drm_api_create(); if (drm_api) - ndpy = kms_create_display(dpy, drm_api); + ndpy = kms_create_display(dpy, event_handler, drm_api); return ndpy; } diff --git a/src/gallium/state_trackers/egl/kms/native_kms.h b/src/gallium/state_trackers/egl/kms/native_kms.h index 095186e3cf3..3b08e930c52 100644 --- a/src/gallium/state_trackers/egl/kms/native_kms.h +++ b/src/gallium/state_trackers/egl/kms/native_kms.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_KMS_H_ @@ -35,11 +36,6 @@ #include "common/native.h" -enum kms_surface_type { - KMS_SURFACE_TYPE_PBUFFER, - KMS_SURFACE_TYPE_SCANOUT -}; - struct kms_config; struct kms_connector; struct kms_mode; @@ -53,6 +49,8 @@ struct kms_crtc { struct kms_display { struct native_display base; + struct native_event_handler *event_handler; + int fd; struct drm_api *api; drmModeResPtr resources; @@ -67,7 +65,7 @@ struct kms_display { }; struct kms_framebuffer { - struct pipe_texture *texture; + struct pipe_resource *texture; boolean is_passive; uint32_t buffer_id; @@ -75,12 +73,11 @@ struct kms_framebuffer { struct kms_surface { struct native_surface base; - enum kms_surface_type type; enum pipe_format color_format; struct kms_display *kdpy; int width, height; - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; unsigned int sequence_number; struct kms_framebuffer front_fb, back_fb; diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c index 74d3d104b94..d37f66da07e 100644 --- a/src/gallium/state_trackers/egl/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -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. */ #include "util/u_memory.h" @@ -40,7 +41,6 @@ enum dri2_surface_type { DRI2_SURFACE_TYPE_WINDOW, DRI2_SURFACE_TYPE_PIXMAP, - DRI2_SURFACE_TYPE_PBUFFER }; struct dri2_display { @@ -48,6 +48,8 @@ struct dri2_display { Display *dpy; boolean own_dpy; + struct native_event_handler *event_handler; + struct drm_api *api; struct x11_screen *xscr; int xscr_number; @@ -70,7 +72,7 @@ struct dri2_surface { unsigned int server_stamp; unsigned int client_stamp; int width, height; - struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; uint valid_mask; boolean have_back, have_fake; @@ -111,13 +113,14 @@ dri2_surface_process_drawable_buffers(struct native_surface *nsurf, { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; - struct pipe_texture templ; + struct pipe_resource templ; + struct winsys_handle whandle; uint valid_mask; int i; /* free the old textures */ for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) - pipe_texture_reference(&dri2surf->textures[i], NULL); + pipe_resource_reference(&dri2surf->textures[i], NULL); dri2surf->valid_mask = 0x0; dri2surf->have_back = FALSE; @@ -133,7 +136,7 @@ dri2_surface_process_drawable_buffers(struct native_surface *nsurf, templ.height0 = dri2surf->height; templ.depth0 = 1; templ.format = dri2surf->color_format; - templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; + templ.bind = PIPE_BIND_RENDER_TARGET; valid_mask = 0x0; for (i = 0; i < num_xbufs; i++) { @@ -169,9 +172,11 @@ dri2_surface_process_drawable_buffers(struct native_surface *nsurf, continue; } - dri2surf->textures[natt] = - dri2dpy->api->texture_from_shared_handle(dri2dpy->api, - dri2dpy->base.screen, &templ, desc, xbuf->pitch, xbuf->name); + memset(&whandle, 0, sizeof(whandle)); + whandle.stride = xbuf->pitch; + whandle.handle = xbuf->name; + dri2surf->textures[natt] = dri2dpy->base.screen->resource_from_handle( + dri2dpy->base.screen, &templ, &whandle); if (dri2surf->textures[natt]) valid_mask |= 1 << natt; } @@ -187,9 +192,19 @@ dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; - unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS]; + unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS * 2]; int num_ins, num_outs, att; struct x11_drawable_buffer *xbufs; + uint bpp = util_format_get_blocksizebits(dri2surf->color_format); + boolean with_format = FALSE; /* never ask for depth/stencil */ + + /* We must get the front on servers which doesn't support with format + * due to a silly bug in core dri2. You can't copy to/from a buffer + * that you haven't requested and you recive BadValue errors */ + if (dri2surf->dri2dpy->dri_minor < 1) { + with_format = FALSE; + buffer_mask |= (1 << NATIVE_ATTACHMENT_FRONT_LEFT); + } /* prepare the attachments */ num_ins = 0; @@ -216,19 +231,22 @@ dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) break; } - dri2atts[num_ins] = dri2att; - num_ins++; + dri2atts[num_ins++] = dri2att; + if (with_format) + dri2atts[num_ins++] = bpp; } } + if (with_format) + num_ins /= 2; xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable, &dri2surf->width, &dri2surf->height, - dri2atts, FALSE, num_ins, &num_outs); + dri2atts, with_format, num_ins, &num_outs); /* we should be able to do better... */ if (xbufs && dri2surf->last_num_xbufs == num_outs && memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) { - free(xbufs); + FREE(xbufs); dri2surf->client_stamp = dri2surf->server_stamp; return; } @@ -239,7 +257,7 @@ dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) dri2surf->client_stamp = dri2surf->server_stamp; if (dri2surf->last_xbufs) - free(dri2surf->last_xbufs); + FREE(dri2surf->last_xbufs); dri2surf->last_xbufs = xbufs; dri2surf->last_num_xbufs = num_outs; } @@ -252,47 +270,8 @@ static boolean dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) { struct dri2_surface *dri2surf = dri2_surface(nsurf); - struct dri2_display *dri2dpy = dri2surf->dri2dpy; - - /* create textures for pbuffer */ - if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) { - struct pipe_screen *screen = dri2dpy->base.screen; - struct pipe_texture templ; - uint new_valid = 0x0; - int att; - - buffer_mask &= ~dri2surf->valid_mask; - if (!buffer_mask) - return TRUE; - - memset(&templ, 0, sizeof(templ)); - templ.target = PIPE_TEXTURE_2D; - templ.last_level = 0; - templ.width0 = dri2surf->width; - templ.height0 = dri2surf->height; - templ.depth0 = 1; - templ.format = dri2surf->color_format; - templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - - for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { - if (native_attachment_mask_test(buffer_mask, att)) { - assert(!dri2surf->textures[att]); - dri2surf->textures[att] = screen->texture_create(screen, &templ); - if (!dri2surf->textures[att]) - break; - - new_valid |= 1 << att; - if (new_valid == buffer_mask) - break; - } - } - dri2surf->valid_mask |= new_valid; - /* no need to update the stamps */ - } - else { - dri2_surface_get_buffers(&dri2surf->base, buffer_mask); - } + dri2_surface_get_buffers(&dri2surf->base, buffer_mask); return ((dri2surf->valid_mask & buffer_mask) == buffer_mask); } @@ -313,10 +292,6 @@ dri2_surface_flush_frontbuffer(struct native_surface *nsurf) struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; - /* pbuffer is private */ - if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) - return TRUE; - /* copy to real front buffer */ if (dri2surf->have_fake) x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, @@ -324,8 +299,11 @@ dri2_surface_flush_frontbuffer(struct native_surface *nsurf) DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); /* force buffers to be updated in next validation call */ - if (!dri2_surface_receive_events(&dri2surf->base)) + if (!dri2_surface_receive_events(&dri2surf->base)) { dri2surf->server_stamp++; + dri2dpy->event_handler->invalid_surface(&dri2dpy->base, + &dri2surf->base, dri2surf->server_stamp); + } return TRUE; } @@ -336,10 +314,6 @@ dri2_surface_swap_buffers(struct native_surface *nsurf) struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; - /* pbuffer is private */ - if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) - return TRUE; - /* copy to front buffer */ if (dri2surf->have_back) x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, @@ -353,15 +327,18 @@ dri2_surface_swap_buffers(struct native_surface *nsurf) DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); /* force buffers to be updated in next validation call */ - if (!dri2_surface_receive_events(&dri2surf->base)) + if (!dri2_surface_receive_events(&dri2surf->base)) { dri2surf->server_stamp++; + dri2dpy->event_handler->invalid_surface(&dri2dpy->base, + &dri2surf->base, dri2surf->server_stamp); + } return TRUE; } static boolean dri2_surface_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) { struct dri2_surface *dri2surf = dri2_surface(nsurf); @@ -379,10 +356,10 @@ dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, int att; for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { if (native_attachment_mask_test(attachment_mask, att)) { - struct pipe_texture *ptex = dri2surf->textures[att]; + struct pipe_resource *ptex = dri2surf->textures[att]; textures[att] = NULL; - pipe_texture_reference(&textures[att], ptex); + pipe_resource_reference(&textures[att], ptex); } } } @@ -415,11 +392,11 @@ dri2_surface_destroy(struct native_surface *nsurf) int i; if (dri2surf->last_xbufs) - free(dri2surf->last_xbufs); + FREE(dri2surf->last_xbufs); for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct pipe_texture *ptex = dri2surf->textures[i]; - pipe_texture_reference(&ptex, NULL); + struct pipe_resource *ptex = dri2surf->textures[i]; + pipe_resource_reference(&ptex, NULL); } if (dri2surf->drawable) { @@ -429,7 +406,7 @@ dri2_surface_destroy(struct native_surface *nsurf) util_hash_table_remove(dri2surf->dri2dpy->surfaces, (void *) dri2surf->drawable); } - free(dri2surf); + FREE(dri2surf); } static struct dri2_surface * @@ -493,22 +470,6 @@ dri2_display_create_pixmap_surface(struct native_display *ndpy, return (dri2surf) ? &dri2surf->base : NULL; } -static struct native_surface * -dri2_display_create_pbuffer_surface(struct native_display *ndpy, - const struct native_config *nconf, - uint width, uint height) -{ - struct dri2_surface *dri2surf; - - dri2surf = dri2_display_create_surface(ndpy, DRI2_SURFACE_TYPE_PBUFFER, - (Drawable) None, nconf); - if (dri2surf) { - dri2surf->width = width; - dri2surf->height = height; - } - return (dri2surf) ? &dri2surf->base : NULL; -} - static int choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32]) { @@ -535,43 +496,13 @@ choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32]) return count; } -static int -choose_depth_stencil_format(const __GLcontextModes *mode, - enum pipe_format formats[32]) -{ - int count = 0; - - switch (mode->depthBits) { - case 32: - formats[count++] = PIPE_FORMAT_Z32_UNORM; - break; - case 24: - if (mode->stencilBits) { - formats[count++] = PIPE_FORMAT_Z24S8_UNORM; - formats[count++] = PIPE_FORMAT_S8Z24_UNORM; - } - else { - formats[count++] = PIPE_FORMAT_Z24X8_UNORM; - formats[count++] = PIPE_FORMAT_X8Z24_UNORM; - } - break; - case 16: - formats[count++] = PIPE_FORMAT_Z16_UNORM; - break; - default: - break; - } - - return count; -} - static boolean is_format_supported(struct pipe_screen *screen, enum pipe_format fmt, boolean is_color) { return screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D, - (is_color) ? PIPE_TEXTURE_USAGE_RENDER_TARGET : - PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); + (is_color) ? PIPE_BIND_RENDER_TARGET : + PIPE_BIND_DEPTH_STENCIL, 0); } static boolean @@ -589,30 +520,18 @@ dri2_display_convert_config(struct native_display *ndpy, if (!mode->doubleBufferMode) return FALSE; - nconf->mode = *mode; - nconf->mode.renderType = GLX_RGBA_BIT; - nconf->mode.rgbMode = TRUE; - /* pbuffer is allocated locally and is always supported */ - nconf->mode.drawableType |= GLX_PBUFFER_BIT; - /* the swap method is always copy */ - nconf->mode.swapMethod = GLX_SWAP_COPY_OML; - - /* fix up */ - nconf->mode.rgbBits = - nconf->mode.redBits + nconf->mode.greenBits + - nconf->mode.blueBits + nconf->mode.alphaBits; - if (!(nconf->mode.drawableType & GLX_WINDOW_BIT)) { - nconf->mode.visualID = 0; - nconf->mode.visualType = GLX_NONE; - } - if (!(nconf->mode.drawableType & GLX_PBUFFER_BIT)) { - nconf->mode.bindToTextureRgb = FALSE; - nconf->mode.bindToTextureRgba = FALSE; - } + /* only interested in native renderable configs */ + if (!mode->xRenderable || !mode->drawableType) + return FALSE; - nconf->color_format = PIPE_FORMAT_NONE; - nconf->depth_format = PIPE_FORMAT_NONE; - nconf->stencil_format = PIPE_FORMAT_NONE; + nconf->buffer_mask = 1 << NATIVE_ATTACHMENT_FRONT_LEFT; + if (mode->doubleBufferMode) + nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_LEFT; + if (mode->stereoMode) { + nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_FRONT_RIGHT; + if (mode->doubleBufferMode) + nconf->buffer_mask |= 1 << NATIVE_ATTACHMENT_BACK_RIGHT; + } /* choose color format */ num_formats = choose_color_format(mode, formats); @@ -625,18 +544,24 @@ dri2_display_convert_config(struct native_display *ndpy, if (nconf->color_format == PIPE_FORMAT_NONE) return FALSE; - /* choose depth/stencil format */ - num_formats = choose_depth_stencil_format(mode, formats); - for (i = 0; i < num_formats; i++) { - if (is_format_supported(ndpy->screen, formats[i], FALSE)) { - nconf->depth_format = formats[i]; - nconf->stencil_format = formats[i]; - break; - } + if (mode->drawableType & GLX_WINDOW_BIT) + nconf->window_bit = TRUE; + if (mode->drawableType & GLX_PIXMAP_BIT) + nconf->pixmap_bit = TRUE; + + nconf->native_visual_id = mode->visualID; + nconf->native_visual_type = mode->visualType; + nconf->level = mode->level; + nconf->samples = mode->samples; + + nconf->slow_config = (mode->visualRating == GLX_SLOW_CONFIG); + + if (mode->transparentPixel == GLX_TRANSPARENT_RGB) { + nconf->transparent_rgb = TRUE; + nconf->transparent_rgb_values[0] = mode->transparentRed; + nconf->transparent_rgb_values[1] = mode->transparentGreen; + nconf->transparent_rgb_values[2] = mode->transparentBlue; } - if ((nconf->mode.depthBits && nconf->depth_format == PIPE_FORMAT_NONE) || - (nconf->mode.stencilBits && nconf->stencil_format == PIPE_FORMAT_NONE)) - return FALSE; return TRUE; } @@ -658,7 +583,7 @@ dri2_display_get_configs(struct native_display *ndpy, int *num_configs) return NULL; num_modes = x11_context_modes_count(modes); - dri2dpy->configs = calloc(num_modes, sizeof(*dri2dpy->configs)); + dri2dpy->configs = CALLOC(num_modes, sizeof(*dri2dpy->configs)); if (!dri2dpy->configs) return NULL; @@ -673,7 +598,7 @@ dri2_display_get_configs(struct native_display *ndpy, int *num_configs) dri2dpy->num_configs = count; } - configs = malloc(dri2dpy->num_configs * sizeof(*configs)); + configs = MALLOC(dri2dpy->num_configs * sizeof(*configs)); if (configs) { for (i = 0; i < dri2dpy->num_configs; i++) configs[i] = (const struct native_config *) &dri2dpy->configs[i]; @@ -699,13 +624,32 @@ dri2_display_is_pixmap_supported(struct native_display *ndpy, return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth)); } +static int +dri2_display_get_param(struct native_display *ndpy, + enum native_param_type param) +{ + int val; + + switch (param) { + case NATIVE_PARAM_USE_NATIVE_BUFFER: + /* DRI2GetBuffers use the native buffers */ + val = TRUE; + break; + default: + val = 0; + break; + } + + return val; +} + static void dri2_display_destroy(struct native_display *ndpy) { struct dri2_display *dri2dpy = dri2_display(ndpy); if (dri2dpy->configs) - free(dri2dpy->configs); + FREE(dri2dpy->configs); if (dri2dpy->base.screen) dri2dpy->base.screen->destroy(dri2dpy->base.screen); @@ -719,7 +663,7 @@ dri2_display_destroy(struct native_display *ndpy) XCloseDisplay(dri2dpy->dpy); if (dri2dpy->api && dri2dpy->api->destroy) dri2dpy->api->destroy(dri2dpy->api); - free(dri2dpy); + FREE(dri2dpy); } static void @@ -737,7 +681,10 @@ dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable, return; dri2surf = dri2_surface(nsurf); + dri2surf->server_stamp++; + dri2dpy->event_handler->invalid_surface(&dri2dpy->base, + &dri2surf->base, dri2surf->server_stamp); } /** @@ -748,7 +695,6 @@ dri2_display_init_screen(struct native_display *ndpy) { struct dri2_display *dri2dpy = dri2_display(ndpy); const char *driver = dri2dpy->api->name; - struct drm_create_screen_arg arg; int fd; if (!x11_screen_support(dri2dpy->xscr, X11_SCREEN_EXTENSION_DRI2) || @@ -771,9 +717,7 @@ dri2_display_init_screen(struct native_display *ndpy) if (fd < 0) return FALSE; - memset(&arg, 0, sizeof(arg)); - arg.mode = DRM_CREATE_NORMAL; - dri2dpy->base.screen = dri2dpy->api->create_screen(dri2dpy->api, fd, &arg); + dri2dpy->base.screen = dri2dpy->api->create_screen(dri2dpy->api, fd, NULL); if (!dri2dpy->base.screen) { _eglLog(_EGL_WARNING, "failed to create DRM screen"); return FALSE; @@ -796,7 +740,9 @@ dri2_display_hash_table_compare(void *key1, void *key2) } struct native_display * -x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api) +x11_create_dri2_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler, + struct drm_api *api) { struct dri2_display *dri2dpy; @@ -804,6 +750,7 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api) if (!dri2dpy) return NULL; + dri2dpy->event_handler = event_handler; dri2dpy->api = api; dri2dpy->dpy = dpy; @@ -836,11 +783,11 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api) } dri2dpy->base.destroy = dri2_display_destroy; + dri2dpy->base.get_param = dri2_display_get_param; dri2dpy->base.get_configs = dri2_display_get_configs; dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported; dri2dpy->base.create_window_surface = dri2_display_create_window_surface; dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface; - dri2dpy->base.create_pbuffer_surface = dri2_display_create_pbuffer_surface; return &dri2dpy->base; } diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c index 3add95d0aca..b6d51bbf9fb 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.c +++ b/src/gallium/state_trackers/egl/x11/native_x11.c @@ -14,18 +14,19 @@ * 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 <stdio.h> #include <string.h> #include "util/u_debug.h" #include "util/u_memory.h" +#include "util/u_string.h" #include "state_tracker/drm_api.h" #include "egllog.h" @@ -40,8 +41,8 @@ static void x11_probe_destroy(struct native_probe *nprobe) { if (nprobe->data) - free(nprobe->data); - free(nprobe); + FREE(nprobe->data); + FREE(nprobe); } struct native_probe * @@ -61,7 +62,7 @@ native_create_probe(EGLNativeDisplayType dpy) if (!xdpy) { xdpy = XOpenDisplay(NULL); if (!xdpy) { - free(nprobe); + FREE(nprobe); return NULL; } } @@ -118,15 +119,16 @@ native_get_name(void) api = drm_api_create(); if (api) - snprintf(x11_name, sizeof(x11_name), "X11/%s", api->name); + util_snprintf(x11_name, sizeof(x11_name), "X11/%s", api->name); else - snprintf(x11_name, sizeof(x11_name), "X11"); + util_snprintf(x11_name, sizeof(x11_name), "X11"); return x11_name; } struct native_display * -native_create_display(EGLNativeDisplayType dpy) +native_create_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler) { struct native_display *ndpy = NULL; boolean force_sw; @@ -136,21 +138,14 @@ native_create_display(EGLNativeDisplayType dpy) force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE); if (api && !force_sw) { - ndpy = x11_create_dri2_display(dpy, api); + ndpy = x11_create_dri2_display(dpy, event_handler, api); } if (!ndpy) { EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING; - boolean use_shm; - - /* - * XXX st/mesa calls pipe_screen::update_buffer in st_validate_state. - * When SHM is used, there is a good chance that the shared memory - * segment is detached before the softpipe tile cache is flushed. - */ - use_shm = FALSE; - _eglLog(level, "use software%s fallback", (use_shm) ? " (SHM)" : ""); - ndpy = x11_create_ximage_display(dpy, use_shm); + + _eglLog(level, "use software fallback"); + ndpy = x11_create_ximage_display(dpy, event_handler); } return ndpy; diff --git a/src/gallium/state_trackers/egl/x11/native_x11.h b/src/gallium/state_trackers/egl/x11/native_x11.h index 622ddac5df6..1678403b459 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.h +++ b/src/gallium/state_trackers/egl/x11/native_x11.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_X11_H_ @@ -29,9 +30,12 @@ #include "common/native.h" struct native_display * -x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm); +x11_create_ximage_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler); struct native_display * -x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api); +x11_create_dri2_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler, + struct drm_api *api); #endif /* _NATIVE_X11_H_ */ diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c index a8633b1501e..47f5423b67e 100644 --- a/src/gallium/state_trackers/egl/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl/x11/native_ximage.c @@ -14,38 +14,35 @@ * 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 <sys/ipc.h> -#include <sys/types.h> -#include <sys/shm.h> #include <X11/Xlib.h> #include <X11/Xutil.h> -#include <X11/extensions/XShm.h> #include "util/u_memory.h" #include "util/u_math.h" #include "util/u_format.h" #include "pipe/p_compiler.h" -#include "util/u_simple_screen.h" #include "util/u_inlines.h" -#include "softpipe/sp_winsys.h" +#include "state_tracker/xlib_sw_winsys.h" +#include "target-helpers/wrap_screen.h" +#include "util/u_debug.h" +#include "softpipe/sp_public.h" +#include "llvmpipe/lp_public.h" #include "egllog.h" -#include "sw_winsys.h" #include "native_x11.h" #include "x11_screen.h" enum ximage_surface_type { XIMAGE_SURFACE_TYPE_WINDOW, XIMAGE_SURFACE_TYPE_PIXMAP, - XIMAGE_SURFACE_TYPE_PBUFFER }; struct ximage_display { @@ -53,22 +50,18 @@ struct ximage_display { Display *dpy; boolean own_dpy; + struct native_event_handler *event_handler; + struct x11_screen *xscr; int xscr_number; - boolean use_xshm; - - struct pipe_winsys *winsys; struct ximage_config *configs; int num_configs; }; struct ximage_buffer { - XImage *ximage; - - struct pipe_texture *texture; - XShmSegmentInfo *shm_info; - boolean xshm_attached; + struct pipe_resource *texture; + struct xlib_drawable xdraw; }; struct ximage_surface { @@ -79,13 +72,13 @@ struct ximage_surface { XVisualInfo visual; struct ximage_display *xdpy; - GC gc; - unsigned int server_stamp; unsigned int client_stamp; int width, height; struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS]; uint valid_mask; + + struct pipe_surface *draw_surface; }; struct ximage_config { @@ -118,19 +111,7 @@ ximage_surface_free_buffer(struct native_surface *nsurf, struct ximage_surface *xsurf = ximage_surface(nsurf); struct ximage_buffer *xbuf = &xsurf->buffers[which]; - pipe_texture_reference(&xbuf->texture, NULL); - - if (xbuf->shm_info) { - if (xbuf->xshm_attached) - XShmDetach(xsurf->xdpy->dpy, xbuf->shm_info); - if (xbuf->shm_info->shmaddr != (void *) -1) - shmdt(xbuf->shm_info->shmaddr); - if (xbuf->shm_info->shmid != -1) - shmctl(xbuf->shm_info->shmid, IPC_RMID, 0); - - xbuf->shm_info->shmaddr = (void *) -1; - xbuf->shm_info->shmid = -1; - } + pipe_resource_reference(&xbuf->texture, NULL); } static boolean @@ -140,7 +121,7 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf, struct ximage_surface *xsurf = ximage_surface(nsurf); struct ximage_buffer *xbuf = &xsurf->buffers[which]; struct pipe_screen *screen = xsurf->xdpy->base.screen; - struct pipe_texture templ; + struct pipe_resource templ; /* free old data */ if (xbuf->texture) @@ -152,42 +133,25 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf, templ.width0 = xsurf->width; templ.height0 = xsurf->height; templ.depth0 = 1; - templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - - if (xbuf->shm_info) { - struct pipe_buffer *pbuf; - unsigned stride, size; - void *addr = NULL; - - stride = util_format_get_stride(xsurf->color_format, xsurf->width); - /* alignment should depend on visual? */ - stride = align(stride, 4); - size = stride * xsurf->height; - - /* create and attach shm object */ - xbuf->shm_info->shmid = shmget(IPC_PRIVATE, size, 0755); - if (xbuf->shm_info->shmid != -1) { - xbuf->shm_info->shmaddr = - shmat(xbuf->shm_info->shmid, NULL, 0); - if (xbuf->shm_info->shmaddr != (void *) -1) { - if (XShmAttach(xsurf->xdpy->dpy, xbuf->shm_info)) { - addr = xbuf->shm_info->shmaddr; - xbuf->xshm_attached = TRUE; - } - } - } + templ.bind = PIPE_BIND_RENDER_TARGET; - if (addr) { - pbuf = screen->user_buffer_create(screen, addr, size); - if (pbuf) { - xbuf->texture = - screen->texture_blanket(screen, &templ, &stride, pbuf); - pipe_buffer_reference(&pbuf, NULL); - } - } + switch (which) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + case NATIVE_ATTACHMENT_FRONT_RIGHT: + templ.bind |= PIPE_BIND_SCANOUT; + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + case NATIVE_ATTACHMENT_BACK_RIGHT: + templ.bind |= PIPE_BIND_DISPLAY_TARGET; + break; + default: + break; } - else { - xbuf->texture = screen->texture_create(screen, &templ); + xbuf->texture = screen->resource_create(screen, &templ); + if (xbuf->texture) { + xbuf->xdraw.visual = xsurf->visual.visual; + xbuf->xdraw.depth = xsurf->visual.depth; + xbuf->xdraw.drawable = xsurf->drawable; } /* clean up the buffer if allocation failed */ @@ -211,10 +175,6 @@ ximage_surface_update_geometry(struct native_surface *nsurf) unsigned int w, h, border, depth; boolean updated = FALSE; - /* pbuffer has fixed geometry */ - if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER) - return FALSE; - ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable, &root, &x, &y, &w, &h, &border, &depth); if (ok && (xsurf->width != w || xsurf->height != h)) { @@ -228,6 +188,16 @@ ximage_surface_update_geometry(struct native_surface *nsurf) return updated; } +static void +ximage_surface_notify_invalid(struct native_surface *nsurf) +{ + struct ximage_surface *xsurf = ximage_surface(nsurf); + struct ximage_display *xdpy = xsurf->xdpy; + + xdpy->event_handler->invalid_surface(&xdpy->base, + &xsurf->base, xsurf->server_stamp); +} + /** * Update the buffers of the surface. It is a slow function due to the * round-trip to the server. @@ -257,18 +227,10 @@ ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) new_valid = 0x0; for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { if (native_attachment_mask_test(buffer_mask, att)) { - struct ximage_buffer *xbuf = &xsurf->buffers[att]; - /* reallocate the texture */ if (!ximage_surface_alloc_buffer(&xsurf->base, att)) break; - /* update ximage */ - if (xbuf->ximage) { - xbuf->ximage->width = xsurf->width; - xbuf->ximage->height = xsurf->height; - } - new_valid |= (1 << att); if (buffer_mask == new_valid) break; @@ -288,43 +250,23 @@ ximage_surface_draw_buffer(struct native_surface *nsurf, struct ximage_surface *xsurf = ximage_surface(nsurf); struct ximage_buffer *xbuf = &xsurf->buffers[which]; struct pipe_screen *screen = xsurf->xdpy->base.screen; - struct pipe_transfer *transfer; + struct pipe_surface *psurf; - if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER) - return TRUE; + assert(xsurf->drawable && xbuf->texture); - assert(xsurf->drawable && xbuf->ximage && xbuf->texture); + psurf = xsurf->draw_surface; + if (!psurf || psurf->texture != xbuf->texture) { + pipe_surface_reference(&xsurf->draw_surface, NULL); - transfer = screen->get_tex_transfer(screen, xbuf->texture, - 0, 0, 0, PIPE_TRANSFER_READ, 0, 0, xsurf->width, xsurf->height); - if (!transfer) - return FALSE; + psurf = screen->get_tex_surface(screen, + xbuf->texture, 0, 0, 0, PIPE_BIND_DISPLAY_TARGET); + if (!psurf) + return FALSE; - xbuf->ximage->bytes_per_line = transfer->stride; - xbuf->ximage->data = screen->transfer_map(screen, transfer); - if (!xbuf->ximage->data) { - screen->tex_transfer_destroy(transfer); - return FALSE; + xsurf->draw_surface = psurf; } - - if (xbuf->shm_info) - XShmPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc, - xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height, False); - else - XPutImage(xsurf->xdpy->dpy, xsurf->drawable, xsurf->gc, - xbuf->ximage, 0, 0, 0, 0, xsurf->width, xsurf->height); - - xbuf->ximage->data = NULL; - screen->transfer_unmap(screen, transfer); - - /* - * softpipe allows the pipe transfer to be re-used, but we don't want to - * rely on that behavior. - */ - screen->tex_transfer_destroy(transfer); - - XSync(xsurf->xdpy->dpy, FALSE); + screen->flush_frontbuffer(screen, psurf, &xbuf->xdraw); return TRUE; } @@ -339,6 +281,7 @@ ximage_surface_flush_frontbuffer(struct native_surface *nsurf) NATIVE_ATTACHMENT_FRONT_LEFT); /* force buffers to be updated in next validation call */ xsurf->server_stamp++; + ximage_surface_notify_invalid(&xsurf->base); return ret; } @@ -351,27 +294,28 @@ ximage_surface_swap_buffers(struct native_surface *nsurf) boolean ret; /* display the back buffer first */ - ret = ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT); + ret = ximage_surface_draw_buffer(&xsurf->base, + NATIVE_ATTACHMENT_BACK_LEFT); /* force buffers to be updated in next validation call */ xsurf->server_stamp++; + ximage_surface_notify_invalid(&xsurf->base); xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT]; xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT]; - /* skip swapping so that the front buffer is allocated only when needed */ - if (!xfront->texture) - return ret; - - xtmp = *xfront; - *xfront = *xback; - *xback = xtmp; + /* skip swapping unless there is a front buffer */ + if (xfront->texture) { + xtmp = *xfront; + *xfront = *xback; + *xback = xtmp; + } return ret; } static boolean ximage_surface_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) { struct ximage_surface *xsurf = ximage_surface(nsurf); @@ -392,7 +336,7 @@ ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask, struct ximage_buffer *xbuf = &xsurf->buffers[att]; textures[att] = NULL; - pipe_texture_reference(&textures[att], xbuf->texture); + pipe_resource_reference(&textures[att], xbuf->texture); } } } @@ -419,19 +363,12 @@ ximage_surface_destroy(struct native_surface *nsurf) struct ximage_surface *xsurf = ximage_surface(nsurf); int i; - for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct ximage_buffer *xbuf = &xsurf->buffers[i]; + pipe_surface_reference(&xsurf->draw_surface, NULL); + + for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) ximage_surface_free_buffer(&xsurf->base, i); - /* xbuf->shm_info is owned by xbuf->ximage? */ - if (xbuf->ximage) { - XDestroyImage(xbuf->ximage); - xbuf->ximage = NULL; - } - } - if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) - XFreeGC(xsurf->xdpy->dpy, xsurf->gc); - free(xsurf); + FREE(xsurf); } static struct ximage_surface * @@ -443,7 +380,6 @@ ximage_display_create_surface(struct native_display *ndpy, struct ximage_display *xdpy = ximage_display(ndpy); struct ximage_config *xconf = ximage_config(nconf); struct ximage_surface *xsurf; - int i; xsurf = CALLOC_STRUCT(ximage_surface); if (!xsurf) @@ -454,56 +390,10 @@ ximage_display_create_surface(struct native_display *ndpy, xsurf->color_format = xconf->base.color_format; xsurf->drawable = drawable; - if (xsurf->type != XIMAGE_SURFACE_TYPE_PBUFFER) { - xsurf->drawable = drawable; - xsurf->visual = *xconf->visual; - - xsurf->gc = XCreateGC(xdpy->dpy, xsurf->drawable, 0, NULL); - if (!xsurf->gc) { - free(xsurf); - return NULL; - } - - /* initialize the geometry */ - ximage_surface_update_buffers(&xsurf->base, 0x0); - - for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct ximage_buffer *xbuf = &xsurf->buffers[i]; - - if (xdpy->use_xshm) { - xbuf->shm_info = calloc(1, sizeof(*xbuf->shm_info)); - if (xbuf->shm_info) { - /* initialize shm info */ - xbuf->shm_info->shmid = -1; - xbuf->shm_info->shmaddr = (void *) -1; - xbuf->shm_info->readOnly = TRUE; - - xbuf->ximage = XShmCreateImage(xsurf->xdpy->dpy, - xsurf->visual.visual, - xsurf->visual.depth, - ZPixmap, NULL, - xbuf->shm_info, - 0, 0); - } - } - else { - xbuf->ximage = XCreateImage(xsurf->xdpy->dpy, - xsurf->visual.visual, - xsurf->visual.depth, - ZPixmap, 0, /* format, offset */ - NULL, /* data */ - 0, 0, /* size */ - 8, /* bitmap_pad */ - 0); /* bytes_per_line */ - } - - if (!xbuf->ximage) { - XFreeGC(xdpy->dpy, xsurf->gc); - free(xsurf); - return NULL; - } - } - } + xsurf->drawable = drawable; + xsurf->visual = *xconf->visual; + /* initialize the geometry */ + ximage_surface_update_buffers(&xsurf->base, 0x0); xsurf->base.destroy = ximage_surface_destroy; xsurf->base.swap_buffers = ximage_surface_swap_buffers; @@ -538,22 +428,6 @@ ximage_display_create_pixmap_surface(struct native_display *ndpy, return (xsurf) ? &xsurf->base : NULL; } -static struct native_surface * -ximage_display_create_pbuffer_surface(struct native_display *ndpy, - const struct native_config *nconf, - uint width, uint height) -{ - struct ximage_surface *xsurf; - - xsurf = ximage_display_create_surface(ndpy, XIMAGE_SURFACE_TYPE_PBUFFER, - (Drawable) None, nconf); - if (xsurf) { - xsurf->width = width; - xsurf->height = height; - } - return (xsurf) ? &xsurf->base : NULL; -} - static enum pipe_format choose_format(const XVisualInfo *vinfo) { @@ -587,7 +461,7 @@ ximage_display_get_configs(struct native_display *ndpy, int *num_configs) /* first time */ if (!xdpy->configs) { const XVisualInfo *visuals; - int num_visuals, count, j; + int num_visuals, count; visuals = x11_screen_get_visuals(xdpy->xscr, &num_visuals); if (!visuals) @@ -597,57 +471,42 @@ ximage_display_get_configs(struct native_display *ndpy, int *num_configs) * Create two configs for each visual. * One with depth/stencil buffer; one without */ - xdpy->configs = calloc(num_visuals * 2, sizeof(*xdpy->configs)); + xdpy->configs = CALLOC(num_visuals * 2, sizeof(*xdpy->configs)); if (!xdpy->configs) return NULL; count = 0; for (i = 0; i < num_visuals; i++) { - for (j = 0; j < 2; j++) { - struct ximage_config *xconf = &xdpy->configs[count]; - __GLcontextModes *mode = &xconf->base.mode; - - xconf->visual = &visuals[i]; - xconf->base.color_format = choose_format(xconf->visual); - if (xconf->base.color_format == PIPE_FORMAT_NONE) - continue; - - x11_screen_convert_visual(xdpy->xscr, xconf->visual, mode); - /* support double buffer mode */ - mode->doubleBufferMode = TRUE; - - xconf->base.depth_format = PIPE_FORMAT_NONE; - xconf->base.stencil_format = PIPE_FORMAT_NONE; - /* create the second config with depth/stencil buffer */ - if (j == 1) { - xconf->base.depth_format = PIPE_FORMAT_Z24S8_UNORM; - xconf->base.stencil_format = PIPE_FORMAT_Z24S8_UNORM; - mode->depthBits = 24; - mode->stencilBits = 8; - mode->haveDepthBuffer = TRUE; - mode->haveStencilBuffer = TRUE; - } - - mode->maxPbufferWidth = 4096; - mode->maxPbufferHeight = 4096; - mode->maxPbufferPixels = 4096 * 4096; - mode->drawableType = - GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; - mode->swapMethod = GLX_SWAP_EXCHANGE_OML; - - if (mode->alphaBits) - mode->bindToTextureRgba = TRUE; - else - mode->bindToTextureRgb = TRUE; - - count++; - } + struct ximage_config *xconf = &xdpy->configs[count]; + + xconf->visual = &visuals[i]; + xconf->base.color_format = choose_format(xconf->visual); + if (xconf->base.color_format == PIPE_FORMAT_NONE) + continue; + + xconf->base.buffer_mask = + (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | + (1 << NATIVE_ATTACHMENT_BACK_LEFT); + + xconf->base.window_bit = TRUE; + xconf->base.pixmap_bit = TRUE; + + xconf->base.native_visual_id = xconf->visual->visualid; +#if defined(__cplusplus) || defined(c_plusplus) + xconf->base.native_visual_type = xconf->visual->c_class; +#else + xconf->base.native_visual_type = xconf->visual->class; +#endif + + xconf->base.slow_config = TRUE; + + count++; } xdpy->num_configs = count; } - configs = malloc(xdpy->num_configs * sizeof(*configs)); + configs = MALLOC(xdpy->num_configs * sizeof(*configs)); if (configs) { for (i = 0; i < xdpy->num_configs; i++) configs[i] = (const struct native_config *) &xdpy->configs[i]; @@ -685,25 +544,98 @@ ximage_display_is_pixmap_supported(struct native_display *ndpy, return (fmt == nconf->color_format); } +static int +ximage_display_get_param(struct native_display *ndpy, + enum native_param_type param) +{ + int val; + + switch (param) { + case NATIVE_PARAM_USE_NATIVE_BUFFER: + /* private buffers are allocated */ + val = FALSE; + break; + default: + val = 0; + break; + } + + return val; +} + static void ximage_display_destroy(struct native_display *ndpy) { struct ximage_display *xdpy = ximage_display(ndpy); if (xdpy->configs) - free(xdpy->configs); + FREE(xdpy->configs); xdpy->base.screen->destroy(xdpy->base.screen); - free(xdpy->winsys); x11_screen_destroy(xdpy->xscr); if (xdpy->own_dpy) XCloseDisplay(xdpy->dpy); - free(xdpy); + FREE(xdpy); +} + + +/* Helper function to build a subset of a driver stack consisting of + * one of the software rasterizers (cell, llvmpipe, softpipe) and the + * xlib winsys. + * + * This function could be shared, but currently causes headaches for + * the build systems, particularly scons if we try. + * + * Long term, want to avoid having global #defines for things like + * GALLIUM_LLVMPIPE, GALLIUM_CELL, etc. Scons already eliminates + * those #defines, so things that are painful for it now are likely to + * be painful for other build systems in the future. + */ +static struct pipe_screen * +swrast_xlib_create_screen( Display *display ) +{ + struct sw_winsys *winsys; + struct pipe_screen *screen = NULL; + + /* Create the underlying winsys, which performs presents to Xlib + * drawables: + */ + winsys = xlib_create_sw_winsys( display ); + if (winsys == NULL) + return NULL; + + /* Create a software rasterizer on top of that winsys. Use + * llvmpipe if it is available. + */ +#if defined(GALLIUM_LLVMPIPE) + if (screen == NULL && + !debug_get_bool_option("GALLIUM_NO_LLVM", FALSE)) + screen = llvmpipe_create_screen( winsys ); +#endif + + if (screen == NULL) + screen = softpipe_create_screen( winsys ); + + if (screen == NULL) + goto fail; + + /* Inject any wrapping layers we want to here: + */ + return gallium_wrap_screen( screen ); + +fail: + if (winsys) + winsys->destroy( winsys ); + + return NULL; } + + struct native_display * -x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm) +x11_create_ximage_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler) { struct ximage_display *xdpy; @@ -715,32 +647,30 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm) if (!xdpy->dpy) { xdpy->dpy = XOpenDisplay(NULL); if (!xdpy->dpy) { - free(xdpy); + FREE(xdpy); return NULL; } xdpy->own_dpy = TRUE; } + xdpy->event_handler = event_handler; + xdpy->xscr_number = DefaultScreen(xdpy->dpy); xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number); if (!xdpy->xscr) { - free(xdpy); + FREE(xdpy); return NULL; } - xdpy->use_xshm = - (use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM)); - - xdpy->winsys = create_sw_winsys(); - xdpy->base.screen = softpipe_create_screen(xdpy->winsys); + xdpy->base.screen = swrast_xlib_create_screen(xdpy->dpy); xdpy->base.destroy = ximage_display_destroy; + xdpy->base.get_param = ximage_display_get_param; xdpy->base.get_configs = ximage_display_get_configs; xdpy->base.is_pixmap_supported = ximage_display_is_pixmap_supported; xdpy->base.create_window_surface = ximage_display_create_window_surface; xdpy->base.create_pixmap_surface = ximage_display_create_pixmap_surface; - xdpy->base.create_pbuffer_surface = ximage_display_create_pbuffer_surface; return &xdpy->base; } diff --git a/src/gallium/state_trackers/egl/x11/sw_winsys.c b/src/gallium/state_trackers/egl/x11/sw_winsys.c deleted file mode 100644 index 33328aadf26..00000000000 --- a/src/gallium/state_trackers/egl/x11/sw_winsys.c +++ /dev/null @@ -1,231 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * 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, sub license, 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 (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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. - * - **************************************************************************/ - -/** - * Totally software-based winsys layer. - * Note that the one winsys function that we can't implement here - * is flush_frontbuffer(). - * Whoever uses this code will have to provide that. - * - * Authors: Brian Paul - */ - - -#include "util/u_simple_screen.h" -#include "pipe/p_state.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_math.h" -#include "util/u_memory.h" - -#include "sw_winsys.h" - - - -/** Subclass of pipe_winsys */ -struct sw_pipe_winsys -{ - struct pipe_winsys Base; - /* no extra fields for now */ -}; - - -/** subclass of pipe_buffer */ -struct sw_pipe_buffer -{ - struct pipe_buffer Base; - boolean UserBuffer; /** Is this a user-space buffer? */ - void *Data; - void *Mapped; -}; - - -/** cast wrapper */ -static INLINE struct sw_pipe_buffer * -sw_pipe_buffer(struct pipe_buffer *b) -{ - return (struct sw_pipe_buffer *) b; -} - - -static const char * -get_name(struct pipe_winsys *pws) -{ - return "software"; -} - - -/** Create new pipe_buffer and allocate storage of given size */ -static struct pipe_buffer * -buffer_create(struct pipe_winsys *pws, - unsigned alignment, - unsigned usage, - unsigned size) -{ - struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer); - if (!buffer) - return NULL; - - pipe_reference_init(&buffer->Base.reference, 1); - buffer->Base.alignment = alignment; - buffer->Base.usage = usage; - buffer->Base.size = size; - - /* align to 16-byte multiple for Cell */ - buffer->Data = align_malloc(size, MAX2(alignment, 16)); - - return &buffer->Base; -} - - -/** - * Create buffer which wraps user-space data. - */ -static struct pipe_buffer * -user_buffer_create(struct pipe_winsys *pws, void *ptr, unsigned bytes) -{ - struct sw_pipe_buffer *buffer = CALLOC_STRUCT(sw_pipe_buffer); - if (!buffer) - return NULL; - - pipe_reference_init(&buffer->Base.reference, 1); - buffer->Base.size = bytes; - buffer->UserBuffer = TRUE; - buffer->Data = ptr; - - return &buffer->Base; -} - - -static void * -buffer_map(struct pipe_winsys *pws, struct pipe_buffer *buf, unsigned flags) -{ - struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); - buffer->Mapped = buffer->Data; - return buffer->Mapped; -} - - -static void -buffer_unmap(struct pipe_winsys *pws, struct pipe_buffer *buf) -{ - struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); - buffer->Mapped = NULL; -} - - -static void -buffer_destroy(struct pipe_buffer *buf) -{ - struct sw_pipe_buffer *buffer = sw_pipe_buffer(buf); - - if (buffer->Data && !buffer->UserBuffer) { - align_free(buffer->Data); - buffer->Data = NULL; - } - - free(buffer); -} - - -static struct pipe_buffer * -surface_buffer_create(struct pipe_winsys *winsys, - unsigned width, unsigned height, - enum pipe_format format, - unsigned usage, - unsigned tex_usage, - unsigned *stride) -{ - const unsigned alignment = 64; - unsigned nblocksy; - - nblocksy = util_format_get_nblocksy(format, height); - *stride = align(util_format_get_stride(format, width), alignment); - - return winsys->buffer_create(winsys, alignment, - usage, - *stride * nblocksy); -} - - -static void -fence_reference(struct pipe_winsys *sws, struct pipe_fence_handle **ptr, - struct pipe_fence_handle *fence) -{ - /* no-op */ -} - - -static int -fence_signalled(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - /* no-op */ - return 0; -} - - -static int -fence_finish(struct pipe_winsys *sws, struct pipe_fence_handle *fence, - unsigned flag) -{ - /* no-op */ - return 0; -} - - -/** - * Create/return a new pipe_winsys object. - */ -struct pipe_winsys * -create_sw_winsys(void) -{ - struct sw_pipe_winsys *ws = CALLOC_STRUCT(sw_pipe_winsys); - if (!ws) - return NULL; - - /* Fill in this struct with callbacks that pipe will need to - * communicate with the window system, buffer manager, etc. - */ - ws->Base.buffer_create = buffer_create; - ws->Base.user_buffer_create = user_buffer_create; - ws->Base.buffer_map = buffer_map; - ws->Base.buffer_unmap = buffer_unmap; - ws->Base.buffer_destroy = buffer_destroy; - - ws->Base.surface_buffer_create = surface_buffer_create; - - ws->Base.fence_reference = fence_reference; - ws->Base.fence_signalled = fence_signalled; - ws->Base.fence_finish = fence_finish; - - ws->Base.flush_frontbuffer = NULL; /* not implemented here! */ - - ws->Base.get_name = get_name; - - return &ws->Base; -} diff --git a/src/gallium/state_trackers/egl/x11/sw_winsys.h b/src/gallium/state_trackers/egl/x11/sw_winsys.h deleted file mode 100644 index f96c5a14b0a..00000000000 --- a/src/gallium/state_trackers/egl/x11/sw_winsys.h +++ /dev/null @@ -1,40 +0,0 @@ -/************************************************************************** - * - * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. - * All Rights Reserved. - * - * 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, sub license, 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 (including the - * next paragraph) 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 NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS 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 SW_WINSYS_H -#define SW_WINSYS_H - - -struct pipe_winsys; - - -extern struct pipe_winsys * -create_sw_winsys(void); - - -#endif /* SW_WINSYS_H */ diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.c b/src/gallium/state_trackers/egl/x11/x11_screen.c index f4096114844..6bdff26ec08 100644 --- a/src/gallium/state_trackers/egl/x11/x11_screen.c +++ b/src/gallium/state_trackers/egl/x11/x11_screen.c @@ -14,24 +14,24 @@ * 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 <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> +#include <xf86drm.h> #include <X11/Xlibint.h> #include <X11/extensions/XShm.h> + #include "util/u_memory.h" -#include "util/u_math.h" -#include "util/u_format.h" -#include "xf86drm.h" #include "egllog.h" #include "x11_screen.h" @@ -109,7 +109,7 @@ x11_screen_destroy(struct x11_screen *xscr) if (xscr->visuals) XFree(xscr->visuals); - free(xscr); + FREE(xscr); } static boolean @@ -176,63 +176,6 @@ x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals) return xscr->visuals; } -void -x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual, - __GLcontextModes *mode) -{ - int r, g, b, a; - int visual_type; - - r = util_bitcount(visual->red_mask); - g = util_bitcount(visual->green_mask); - b = util_bitcount(visual->blue_mask); - a = visual->depth - (r + g + b); -#if defined(__cplusplus) || defined(c_plusplus) - visual_type = visual->c_class; -#else - visual_type = visual->class; -#endif - - /* convert to GLX visual type */ - switch (visual_type) { - case TrueColor: - visual_type = GLX_TRUE_COLOR; - break; - case DirectColor: - visual_type = GLX_DIRECT_COLOR; - break; - case PseudoColor: - visual_type = GLX_PSEUDO_COLOR; - break; - case StaticColor: - visual_type = GLX_STATIC_COLOR; - break; - case GrayScale: - visual_type = GLX_GRAY_SCALE; - break; - case StaticGray: - visual_type = GLX_STATIC_GRAY; - break; - default: - visual_type = GLX_NONE; - break; - } - - mode->rgbBits = r + g + b + a; - mode->redBits = r; - mode->greenBits = g; - mode->blueBits = b; - mode->alphaBits = a; - mode->visualID = visual->visualid; - mode->visualType = visual_type; - - /* sane defaults */ - mode->renderType = GLX_RGBA_BIT; - mode->rgbMode = TRUE; - mode->visualRating = GLX_SLOW_CONFIG; - mode->xRenderable = TRUE; -} - /** * Return the GLX fbconfigs. */ @@ -435,7 +378,7 @@ x11_context_modes_create(unsigned count) next = &base; for (i = 0; i < count; i++) { - *next = (__GLcontextModes *) calloc(1, size); + *next = (__GLcontextModes *) CALLOC(1, size); if (*next == NULL) { x11_context_modes_destroy(base); base = NULL; @@ -455,7 +398,7 @@ x11_context_modes_destroy(__GLcontextModes *modes) { while (modes != NULL) { __GLcontextModes *next = modes->next; - free(modes); + FREE(modes); modes = next; } } diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.h b/src/gallium/state_trackers/egl/x11/x11_screen.h index 37e8d5a40e6..a3c5ee1491e 100644 --- a/src/gallium/state_trackers/egl/x11/x11_screen.h +++ b/src/gallium/state_trackers/egl/x11/x11_screen.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 _X11_SCREEN_H_ @@ -28,6 +29,8 @@ #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/extensions/dri2tokens.h> +#include "GL/gl.h" /* for GL types needed by __GLcontextModes */ +#include "GL/internal/glcore.h" /* for __GLcontextModes */ #include "pipe/p_compiler.h" #include "common/native.h" @@ -64,10 +67,6 @@ x11_screen_support(struct x11_screen *xscr, enum x11_screen_extension ext); const XVisualInfo * x11_screen_get_visuals(struct x11_screen *xscr, int *num_visuals); -void -x11_screen_convert_visual(struct x11_screen *xscr, const XVisualInfo *visual, - __GLcontextModes *mode); - const __GLcontextModes * x11_screen_get_glx_configs(struct x11_screen *xscr); |