diff options
Diffstat (limited to 'src/gallium/state_trackers/egl')
18 files changed, 439 insertions, 102 deletions
diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile index 8dbfc5b8e5..8cfcef968e 100644 --- a/src/gallium/state_trackers/egl/Makefile +++ b/src/gallium/state_trackers/egl/Makefile @@ -17,7 +17,7 @@ x11_INCLUDES = \ -I$(TOP)/src/mapi \ -I$(TOP)/src/mesa \ $(X11_CFLAGS) \ - $(shell pkg-config --cflags-only-I libdrm) + $(shell pkg-config --cflags-only-I libdrm dri2proto) x11_SOURCES = $(wildcard x11/*.c) \ $(TOP)/src/glx/dri2.c diff --git a/src/gallium/state_trackers/egl/SConscript b/src/gallium/state_trackers/egl/SConscript index efcce25e31..50c7681995 100644 --- a/src/gallium/state_trackers/egl/SConscript +++ b/src/gallium/state_trackers/egl/SConscript @@ -3,34 +3,32 @@ Import('*') -if 'egl' in env['statetrackers']: +env = env.Clone() - env = env.Clone() +env.Append(CPPPATH = [ + '#/src/egl/main', + '#/src/gallium/winsys/sw', + '.', +]) +env.Append(CPPDEFINES = [ + 'HAVE_GDI_BACKEND', +]) - env.Append(CPPPATH = [ - '#/src/egl/main', - '#/src/gallium/winsys/sw', - '.', - ]) - env.Append(CPPDEFINES = [ - 'HAVE_GDI_BACKEND', - ]) +common_sources = [ + 'common/egl_g3d.c', + 'common/egl_g3d_api.c', + 'common/egl_g3d_image.c', + 'common/egl_g3d_st.c', + 'common/egl_g3d_sync.c', + 'common/native_helper.c', +] - common_sources = [ - 'common/egl_g3d.c', - 'common/egl_g3d_api.c', - 'common/egl_g3d_image.c', - 'common/egl_g3d_st.c', - 'common/egl_g3d_sync.c', - 'common/native_helper.c', - ] +gdi_sources = common_sources + [ + 'gdi/native_gdi.c', +] - gdi_sources = common_sources + [ - 'gdi/native_gdi.c', - ] - - st_egl_gdi = env.ConvenienceLibrary( - target = 'st_egl_gdi', - source = gdi_sources, - ) - Export('st_egl_gdi') +st_egl_gdi = env.ConvenienceLibrary( + target = 'st_egl_gdi', + source = gdi_sources, +) +Export('st_egl_gdi') diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index aaa2ff6bb2..a3750ac56f 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -126,24 +126,24 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy) continue; } - _eglInitScreen(&gscr->base); - - for (j = 0; j < num_modes; j++) { + _eglInitScreen(&gscr->base, dpy, num_modes); + for (j = 0; j < gscr->base.NumModes; j++) { const struct native_mode *nmode = native_modes[j]; - _EGLMode *mode; - - mode = _eglAddNewMode(&gscr->base, nmode->width, nmode->height, - nmode->refresh_rate, nmode->desc); - if (!mode) - break; - /* gscr->native_modes and gscr->base.Modes should be consistent */ - assert(mode == &gscr->base.Modes[j]); + _EGLMode *mode = &gscr->base.Modes[j]; + + mode->Width = nmode->width; + mode->Height = nmode->height; + mode->RefreshRate = nmode->refresh_rate; + mode->Optimal = EGL_FALSE; + mode->Interlaced = EGL_FALSE; + /* no need to strdup() */ + mode->Name = nmode->desc; } gscr->native = nconn; gscr->native_modes = native_modes; - _eglAddScreen(dpy, &gscr->base); + _eglLinkScreen(&gscr->base); } FREE(native_connectors); @@ -156,7 +156,8 @@ egl_g3d_add_screens(_EGLDriver *drv, _EGLDisplay *dpy) */ static EGLBoolean init_config_attributes(_EGLConfig *conf, const struct native_config *nconf, - EGLint api_mask, enum pipe_format depth_stencil_format) + EGLint api_mask, enum pipe_format depth_stencil_format, + EGLBoolean preserve_buffer, EGLint max_swap_interval) { uint rgba[4], depth_stencil[2], buffer_size; EGLint surface_type; @@ -238,6 +239,11 @@ init_config_attributes(_EGLConfig *conf, const struct native_config *nconf, conf->TransparentBlueValue = nconf->transparent_rgb_values[2]; } + conf->MinSwapInterval = 0; + conf->MaxSwapInterval = max_swap_interval; + if (preserve_buffer) + conf->SurfaceType |= EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + return _eglValidateConfig(conf, EGL_FALSE); } @@ -247,7 +253,8 @@ init_config_attributes(_EGLConfig *conf, const struct native_config *nconf, static EGLBoolean egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const struct native_config *nconf, - enum pipe_format depth_stencil_format) + enum pipe_format depth_stencil_format, + int preserve_buffer, int max_swap_interval) { struct egl_g3d_config *gconf = egl_g3d_config(conf); EGLint buffer_mask, api_mask; @@ -288,7 +295,8 @@ egl_g3d_init_config(_EGLDriver *drv, _EGLDisplay *dpy, } valid = init_config_attributes(&gconf->base, - nconf, api_mask, depth_stencil_format); + nconf, api_mask, depth_stencil_format, + preserve_buffer, max_swap_interval); if (!valid) { _eglLog(_EGL_DEBUG, "skip invalid config 0x%x", nconf->native_visual_id); return EGL_FALSE; @@ -349,6 +357,7 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) const struct native_config **native_configs; enum pipe_format depth_stencil_formats[8]; int num_formats, num_configs, i, j; + int preserve_buffer, max_swap_interval; native_configs = gdpy->native->get_configs(gdpy->native, &num_configs); if (!num_configs) { @@ -357,6 +366,11 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) return id; } + preserve_buffer = + gdpy->native->get_param(gdpy->native, NATIVE_PARAM_PRESERVE_BUFFER); + max_swap_interval = + gdpy->native->get_param(gdpy->native, NATIVE_PARAM_MAX_SWAP_INTERVAL); + num_formats = egl_g3d_fill_depth_stencil_formats(dpy, depth_stencil_formats); @@ -368,12 +382,13 @@ egl_g3d_add_configs(_EGLDriver *drv, _EGLDisplay *dpy, EGLint id) if (gconf) { _eglInitConfig(&gconf->base, dpy, id); if (!egl_g3d_init_config(drv, dpy, &gconf->base, - native_configs[i], depth_stencil_formats[j])) { + native_configs[i], depth_stencil_formats[j], + preserve_buffer, max_swap_interval)) { FREE(gconf); break; } - _eglAddConfig(dpy, &gconf->base); + _eglLinkConfig(&gconf->base); id++; } } @@ -538,7 +553,8 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, if (dpy->Platform == _EGL_PLATFORM_DRM) { dpy->Extensions.MESA_drm_display = EGL_TRUE; - dpy->Extensions.MESA_drm_image = EGL_TRUE; + if (gdpy->native->buffer) + dpy->Extensions.MESA_drm_image = EGL_TRUE; } if (egl_g3d_add_configs(drv, dpy, 1) == 1) { diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h index be450bbede..72c14f0ac4 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d.h @@ -106,8 +106,6 @@ _EGL_DRIVER_TYPECAST(egl_g3d_image, _EGLImage, obj) struct egl_g3d_sync { _EGLSync base; - int refs; - /* the mutex protects only the condvar, not the struct */ pipe_mutex mutex; pipe_condvar condvar; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c index 3bde39737b..fd7dc8f814 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c @@ -97,6 +97,70 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx, return stapi; } +static int +egl_g3d_compare_config(const _EGLConfig *conf1, const _EGLConfig *conf2, + void *priv_data) +{ + const _EGLConfig *criteria = (const _EGLConfig *) priv_data; + + /* EGL_NATIVE_VISUAL_TYPE ignored? */ + return _eglCompareConfigs(conf1, conf2, criteria, EGL_TRUE); +} + +static EGLBoolean +egl_g3d_match_config(const _EGLConfig *conf, const _EGLConfig *criteria) +{ + if (!_eglMatchConfig(conf, criteria)) + return EGL_FALSE; + + if (criteria->MatchNativePixmap != EGL_NONE && + criteria->MatchNativePixmap != EGL_DONT_CARE) { + struct egl_g3d_display *gdpy = egl_g3d_display(conf->Display); + struct egl_g3d_config *gconf = egl_g3d_config(conf); + EGLNativePixmapType pix = + (EGLNativePixmapType) criteria->MatchNativePixmap; + + if (!gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native)) + return EGL_FALSE; + } + + return EGL_TRUE; +} + +static EGLBoolean +egl_g3d_choose_config(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attribs, + EGLConfig *configs, EGLint size, EGLint *num_configs) +{ + _EGLConfig **tmp_configs, criteria; + EGLint tmp_size, i; + + if (!num_configs) + return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs"); + + if (!_eglParseConfigAttribList(&criteria, dpy, attribs)) + return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); + + tmp_configs = (_EGLConfig **) _eglFilterArray(dpy->Configs, &tmp_size, + (_EGLArrayForEach) egl_g3d_match_config, (void *) &criteria); + if (!tmp_configs) + return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)"); + + /* perform sorting of configs */ + if (tmp_configs && tmp_size) { + _eglSortConfigs((const _EGLConfig **) tmp_configs, tmp_size, + egl_g3d_compare_config, (void *) &criteria); + size = MIN2(tmp_size, size); + for (i = 0; i < size; i++) + configs[i] = _eglGetConfigHandle(tmp_configs[i]); + } + + free(tmp_configs); + + *num_configs = size; + + return EGL_TRUE; +} + static _EGLContext * egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, _EGLContext *share, const EGLint *attribs) @@ -160,7 +224,7 @@ destroy_context(_EGLDisplay *dpy, _EGLContext *ctx) static EGLBoolean egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) { - if (!_eglIsContextBound(ctx)) + if (_eglPutContext(ctx)) destroy_context(dpy, ctx); return EGL_TRUE; } @@ -433,7 +497,7 @@ destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf) static EGLBoolean egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) { - if (!_eglIsSurfaceBound(surf)) + if (_eglPutSurface(surf)) destroy_surface(dpy, surf); return EGL_TRUE; } @@ -446,13 +510,15 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, struct egl_g3d_surface *gdraw = egl_g3d_surface(draw); struct egl_g3d_surface *gread = egl_g3d_surface(read); struct egl_g3d_context *old_gctx; + _EGLContext *old_ctx; + _EGLSurface *old_draw, *old_read; EGLBoolean ok = EGL_TRUE; - /* bind the new context and return the "orphaned" one */ - if (!_eglBindContext(&ctx, &draw, &read)) + /* make new bindings */ + if (!_eglBindContext(ctx, draw, read, &old_ctx, &old_draw, &old_read)) return EGL_FALSE; - old_gctx = egl_g3d_context(ctx); + old_gctx = egl_g3d_context(old_ctx); if (old_gctx) { /* flush old context */ old_gctx->stctxi->flush(old_gctx->stctxi, @@ -481,15 +547,33 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, } else if (old_gctx) { ok = old_gctx->stapi->make_current(old_gctx->stapi, NULL, NULL, NULL); - old_gctx->base.WindowRenderBuffer = EGL_NONE; + if (ok) + 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); + if (ok) { + if (_eglPutContext(old_ctx)) + destroy_context(dpy, old_ctx); + if (_eglPutSurface(old_draw)) + destroy_surface(dpy, old_draw); + if (_eglPutSurface(old_read)) + destroy_surface(dpy, old_read); + } + else { + /* undo the previous _eglBindContext */ + _eglBindContext(old_ctx, old_draw, old_read, &ctx, &draw, &read); + assert(&gctx->base == ctx && + &gdraw->base == draw && + &gread->base == read); + + _eglPutSurface(draw); + _eglPutSurface(read); + _eglPutContext(ctx); + + _eglPutSurface(old_draw); + _eglPutSurface(old_read); + _eglPutContext(old_ctx); + } return ok; } @@ -519,7 +603,10 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL); } - return gsurf->native->swap_buffers(gsurf->native); + return gsurf->native->present(gsurf->native, + NATIVE_ATTACHMENT_BACK_LEFT, + gsurf->base.SwapBehavior == EGL_BUFFER_PRESERVED, + gsurf->base.SwapInterval); } /** @@ -587,8 +674,7 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, if (psrc) { gdpy->pipe->resource_copy_region(gdpy->pipe, ptex, subdst, 0, 0, 0, gsurf->render_texture, subsrc, 0, 0, 0, ptex->width0, ptex->height0); - - nsurf->flush_frontbuffer(nsurf); + nsurf->present(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT, FALSE, 0); } pipe_resource_reference(&ptex, NULL); @@ -818,6 +904,8 @@ egl_g3d_init_driver_api(_EGLDriver *drv) { _eglInitDriverFallbacks(drv); + drv->API.ChooseConfig = egl_g3d_choose_config; + drv->API.CreateContext = egl_g3d_create_context; drv->API.DestroyContext = egl_g3d_destroy_context; drv->API.CreateWindowSurface = egl_g3d_create_window_surface; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c index be9c88e5e4..6a1f8cc697 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c @@ -38,7 +38,7 @@ #include "egl_g3d_api.h" #include "egl_g3d_image.h" -/* move this to native display? */ +/* for struct winsys_handle */ #include "state_tracker/drm_driver.h" /** @@ -137,13 +137,11 @@ egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name, _EGLImage *img, const EGLint *attribs) { struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct pipe_screen *screen = gdpy->native->screen; struct pipe_resource templ; struct winsys_handle wsh; _EGLImageAttribs attrs; EGLint format; - /* winsys_handle is in theory platform-specific */ if (dpy->Platform != _EGL_PLATFORM_DRM) return NULL; @@ -178,9 +176,10 @@ egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name, memset(&wsh, 0, sizeof(wsh)); wsh.handle = (unsigned) name; - wsh.stride = attrs.DRMBufferStrideMESA; + wsh.stride = + attrs.DRMBufferStrideMESA * util_format_get_blocksize(templ.format); - return screen->resource_from_handle(screen, &templ, &wsh); + return gdpy->native->buffer->import_buffer(gdpy->native, &templ, &wsh); } #endif /* EGL_MESA_drm_image */ @@ -302,10 +301,8 @@ egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img, { struct egl_g3d_display *gdpy = egl_g3d_display(dpy); struct egl_g3d_image *gimg = egl_g3d_image(img); - struct pipe_screen *screen = gdpy->native->screen; struct winsys_handle wsh; - /* winsys_handle is in theory platform-specific */ if (dpy->Platform != _EGL_PLATFORM_DRM) return EGL_FALSE; @@ -313,9 +310,9 @@ egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img, if (name) { memset(&handle, 0, sizeof(handle)); wsh.type = DRM_API_HANDLE_TYPE_SHARED; - if (!screen->resource_get_handle(screen, gimg->texture, &wsh)) { + if (!gdpy->native->buffer->export_buffer(gdpy->native, + gimg->texture, &wsh)) return EGL_FALSE; - } *name = wsh.handle; } @@ -324,7 +321,8 @@ egl_g3d_export_drm_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img, if (handle || stride) { memset(&wsh, 0, sizeof(wsh)); wsh.type = DRM_API_HANDLE_TYPE_KMS; - if (!screen->resource_get_handle(screen, gimg->texture, &wsh)) + if (!gdpy->native->buffer->export_buffer(gdpy->native, + gimg->texture, &wsh)) return EGL_FALSE; if (handle) diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_st.c b/src/gallium/state_trackers/egl/common/egl_g3d_st.c index 0affe632cf..25e2999590 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_st.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.c @@ -192,7 +192,8 @@ egl_g3d_st_framebuffer_flush_front(struct st_framebuffer_iface *stfbi, _EGLSurface *surf = (_EGLSurface *) stfbi->st_manager_private; struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - return gsurf->native->flush_frontbuffer(gsurf->native); + return gsurf->native->present(gsurf->native, + NATIVE_ATTACHMENT_FRONT_LEFT, FALSE, 0); } static boolean diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_sync.c b/src/gallium/state_trackers/egl/common/egl_g3d_sync.c index ec74e9eb94..4e6d944c15 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_sync.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_sync.c @@ -128,13 +128,13 @@ egl_g3d_wait_fence_sync(struct egl_g3d_sync *gsync, EGLTimeKHR timeout) static INLINE void egl_g3d_ref_sync(struct egl_g3d_sync *gsync) { - p_atomic_inc(&gsync->refs); + _eglGetSync(&gsync->base); } static INLINE void egl_g3d_unref_sync(struct egl_g3d_sync *gsync) { - if (p_atomic_dec_zero(&gsync->refs)) { + if (_eglPutSync(&gsync->base)) { pipe_condvar_destroy(gsync->condvar); pipe_mutex_destroy(gsync->mutex); @@ -194,7 +194,6 @@ egl_g3d_create_sync(_EGLDriver *drv, _EGLDisplay *dpy, pipe_mutex_init(gsync->mutex); pipe_condvar_init(gsync->condvar); - p_atomic_set(&gsync->refs, 1); return &gsync->base; } diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h index 3c3f57e267..3886ca2056 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -34,6 +34,11 @@ #include "pipe/p_state.h" #include "state_tracker/sw_winsys.h" +#ifdef __cplusplus +extern "C" { +#endif + +#include "native_buffer.h" #include "native_modeset.h" /** @@ -54,7 +59,17 @@ enum native_param_type { * Return TRUE if window/pixmap surfaces use the buffers of the native * types. */ - NATIVE_PARAM_USE_NATIVE_BUFFER + NATIVE_PARAM_USE_NATIVE_BUFFER, + + /** + * Return TRUE if native_surface::present can preserve the buffer. + */ + NATIVE_PARAM_PRESERVE_BUFFER, + + /** + * Return the maximum supported swap interval. + */ + NATIVE_PARAM_MAX_SWAP_INTERVAL }; struct native_surface { @@ -66,17 +81,12 @@ struct native_surface { void (*destroy)(struct native_surface *nsurf); /** - * Swap the front and back buffers so that the back buffer is visible. It - * is no-op if the surface is single-buffered. The contents of the back - * buffer after swapping may or may not be preserved. - */ - boolean (*swap_buffers)(struct native_surface *nsurf); - - /** - * Make the front buffer visible. In some native displays, changes to the - * front buffer might not be visible immediately and require manual flush. + * Present the given buffer to the native engine. */ - boolean (*flush_frontbuffer)(struct native_surface *nsurf); + boolean (*present)(struct native_surface *nsurf, + enum native_attachment natt, + boolean preserve, + uint swap_interval); /** * Validate the buffers of the surface. textures, if not NULL, points to an @@ -181,6 +191,7 @@ struct native_display { EGLNativePixmapType pix, const struct native_config *nconf); + const struct native_display_buffer *buffer; const struct native_display_modeset *modeset; }; @@ -232,4 +243,8 @@ native_get_drm_platform(void); const struct native_platform * native_get_fbdev_platform(void); +#ifdef __cplusplus +} +#endif + #endif /* _NATIVE_H_ */ diff --git a/src/gallium/state_trackers/egl/common/native_buffer.h b/src/gallium/state_trackers/egl/common/native_buffer.h new file mode 100644 index 0000000000..5c29ab9741 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/native_buffer.h @@ -0,0 +1,59 @@ +/* + * Mesa 3-D graphics library + * Version: 7.9 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#ifndef _NATIVE_BUFFER_H_ +#define _NATIVE_BUFFER_H_ + +#include "pipe/p_compiler.h" + +struct native_display; +struct pipe_resource; + +/** + * Buffer interface of the native display. It allows native buffers to be + * imported and exported. + * + * Just like a native window or a native pixmap, a native buffer is another + * native type. Its definition depends on the native display. + * + * For DRM platform, the type of a native buffer is struct winsys_handle. + */ +struct native_display_buffer { + struct pipe_resource *(*import_buffer)(struct native_display *ndpy, + const struct pipe_resource *templ, + void *buf); + + /** + * The resource must be creatred with PIPE_BIND_SHARED. + */ + boolean (*export_buffer)(struct native_display *ndpy, + struct pipe_resource *res, + void *buf); +}; + +#endif /* _NATIVE_BUFFER_H_ */ diff --git a/src/gallium/state_trackers/egl/common/native_modeset.h b/src/gallium/state_trackers/egl/common/native_modeset.h index dee757b3a8..2598082d68 100644 --- a/src/gallium/state_trackers/egl/common/native_modeset.h +++ b/src/gallium/state_trackers/egl/common/native_modeset.h @@ -39,7 +39,7 @@ struct native_connector { struct native_mode { const char *desc; int width, height; - int refresh_rate; + int refresh_rate; /* HZ * 1000 */ }; /** diff --git a/src/gallium/state_trackers/egl/drm/modeset.c b/src/gallium/state_trackers/egl/drm/modeset.c index 06a6077053..0cc06caa2a 100644 --- a/src/gallium/state_trackers/egl/drm/modeset.c +++ b/src/gallium/state_trackers/egl/drm/modeset.c @@ -167,6 +167,32 @@ drm_surface_swap_buffers(struct native_surface *nsurf) return TRUE; } +static boolean +drm_surface_present(struct native_surface *nsurf, + enum native_attachment natt, + boolean preserve, + uint swap_interval) +{ + boolean ret; + + if (preserve || swap_interval) + return FALSE; + + switch (natt) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + ret = drm_surface_flush_frontbuffer(nsurf); + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + ret = drm_surface_swap_buffers(nsurf); + break; + default: + ret = FALSE; + break; + } + + return ret; +} + static void drm_surface_wait(struct native_surface *nsurf) { @@ -225,8 +251,7 @@ drm_display_create_surface(struct native_display *ndpy, resource_surface_set_size(drmsurf->rsurf, drmsurf->width, drmsurf->height); drmsurf->base.destroy = drm_surface_destroy; - drmsurf->base.swap_buffers = drm_surface_swap_buffers; - drmsurf->base.flush_frontbuffer = drm_surface_flush_frontbuffer; + drmsurf->base.present = drm_surface_present; drmsurf->base.validate = drm_surface_validate; drmsurf->base.wait = drm_surface_wait; @@ -469,8 +494,8 @@ drm_display_get_modes(struct native_display *ndpy, drmmode->base.height = drmmode->mode.vdisplay; drmmode->base.refresh_rate = drmmode->mode.vrefresh; /* not all kernels have vrefresh = refresh_rate * 1000 */ - if (drmmode->base.refresh_rate > 1000) - drmmode->base.refresh_rate = (drmmode->base.refresh_rate + 500) / 1000; + if (drmmode->base.refresh_rate < 1000) + drmmode->base.refresh_rate *= 1000; } nmodes_return = MALLOC(count * sizeof(*nmodes_return)); diff --git a/src/gallium/state_trackers/egl/drm/native_drm.c b/src/gallium/state_trackers/egl/drm/native_drm.c index f6dc558437..3759c2a26d 100644 --- a/src/gallium/state_trackers/egl/drm/native_drm.c +++ b/src/gallium/state_trackers/egl/drm/native_drm.c @@ -103,6 +103,9 @@ drm_display_get_param(struct native_display *ndpy, int val; switch (param) { + case NATIVE_PARAM_USE_NATIVE_BUFFER: + case NATIVE_PARAM_PRESERVE_BUFFER: + case NATIVE_PARAM_MAX_SWAP_INTERVAL: default: val = 0; break; @@ -182,6 +185,29 @@ drm_display_init_screen(struct native_display *ndpy) return TRUE; } +static struct pipe_resource * +drm_display_import_buffer(struct native_display *ndpy, + const struct pipe_resource *templ, + void *buf) +{ + return ndpy->screen->resource_from_handle(ndpy->screen, + templ, (struct winsys_handle *) buf); +} + +static boolean +drm_display_export_buffer(struct native_display *ndpy, + struct pipe_resource *res, + void *buf) +{ + return ndpy->screen->resource_get_handle(ndpy->screen, + res, (struct winsys_handle *) buf); +} + +static struct native_display_buffer drm_display_buffer = { + drm_display_import_buffer, + drm_display_export_buffer +}; + static struct native_display * drm_create_display(int fd, struct native_event_handler *event_handler, void *user_data) @@ -205,6 +231,7 @@ drm_create_display(int fd, struct native_event_handler *event_handler, drmdpy->base.get_param = drm_display_get_param; drmdpy->base.get_configs = drm_display_get_configs; + drmdpy->base.buffer = &drm_display_buffer; drm_display_init_modeset(&drmdpy->base); return &drmdpy->base; diff --git a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c index e459402076..1b5ea8bf9d 100644 --- a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c +++ b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c @@ -137,6 +137,32 @@ fbdev_surface_swap_buffers(struct native_surface *nsurf) return ret; } +static boolean +fbdev_surface_present(struct native_surface *nsurf, + enum native_attachment natt, + boolean preserve, + uint swap_interval) +{ + boolean ret; + + if (preserve || swap_interval) + return FALSE; + + switch (natt) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + ret = fbdev_surface_flush_frontbuffer(nsurf); + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + ret = fbdev_surface_swap_buffers(nsurf); + break; + default: + ret = FALSE; + break; + } + + return ret; +} + static void fbdev_surface_wait(struct native_surface *nsurf) { @@ -181,8 +207,7 @@ fbdev_display_create_scanout_surface(struct native_display *ndpy, resource_surface_set_size(fbsurf->rsurf, fbsurf->width, fbsurf->height); fbsurf->base.destroy = fbdev_surface_destroy; - fbsurf->base.swap_buffers = fbdev_surface_swap_buffers; - fbsurf->base.flush_frontbuffer = fbdev_surface_flush_frontbuffer; + fbsurf->base.present = fbdev_surface_present; fbsurf->base.validate = fbdev_surface_validate; fbsurf->base.wait = fbdev_surface_wait; @@ -279,6 +304,9 @@ fbdev_display_get_param(struct native_display *ndpy, int val; switch (param) { + case NATIVE_PARAM_USE_NATIVE_BUFFER: + case NATIVE_PARAM_PRESERVE_BUFFER: + case NATIVE_PARAM_MAX_SWAP_INTERVAL: default: val = 0; break; diff --git a/src/gallium/state_trackers/egl/gdi/native_gdi.c b/src/gallium/state_trackers/egl/gdi/native_gdi.c index 91701e5b7d..d259e6edc8 100644 --- a/src/gallium/state_trackers/egl/gdi/native_gdi.c +++ b/src/gallium/state_trackers/egl/gdi/native_gdi.c @@ -160,6 +160,32 @@ gdi_surface_swap_buffers(struct native_surface *nsurf) } static boolean +gdi_surface_present(struct native_surface *nsurf, + enum native_attachment natt, + boolean preserve, + uint swap_interval) +{ + boolean ret; + + if (preserve || swap_interval) + return FALSE; + + switch (natt) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + ret = gdi_surface_flush_frontbuffer(nsurf); + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + ret = gdi_surface_swap_buffers(nsurf); + break; + default: + ret = FALSE; + break; + } + + return ret; +} + +static boolean gdi_surface_validate(struct native_surface *nsurf, uint attachment_mask, unsigned int *seq_num, struct pipe_resource **textures, int *width, int *height) @@ -231,8 +257,7 @@ gdi_display_create_window_surface(struct native_display *ndpy, gdi_surface_update_geometry(&gsurf->base); gsurf->base.destroy = gdi_surface_destroy; - gsurf->base.swap_buffers = gdi_surface_swap_buffers; - gsurf->base.flush_frontbuffer = gdi_surface_flush_frontbuffer; + gsurf->base.present = gdi_surface_present; gsurf->base.validate = gdi_surface_validate; gsurf->base.wait = gdi_surface_wait; @@ -321,6 +346,8 @@ gdi_display_get_param(struct native_display *ndpy, /* private buffers are allocated */ val = FALSE; break; + case NATIVE_PARAM_PRESERVE_BUFFER: + case NATIVE_PARAM_MAX_SWAP_INTERVAL: default: val = 0; break; diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c index 1169e273c3..331a7de432 100644 --- a/src/gallium/state_trackers/egl/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -338,6 +338,32 @@ dri2_surface_swap_buffers(struct native_surface *nsurf) } static boolean +dri2_surface_present(struct native_surface *nsurf, + enum native_attachment natt, + boolean preserve, + uint swap_interval) +{ + boolean ret; + + if (swap_interval) + return FALSE; + + switch (natt) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + ret = dri2_surface_flush_frontbuffer(nsurf); + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + ret = dri2_surface_swap_buffers(nsurf); + break; + default: + ret = FALSE; + break; + } + + return ret; +} + +static boolean dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, unsigned int *seq_num, struct pipe_resource **textures, int *width, int *height) @@ -430,8 +456,7 @@ dri2_display_create_surface(struct native_display *ndpy, dri2surf->color_format = dri2conf->base.color_format; dri2surf->base.destroy = dri2_surface_destroy; - dri2surf->base.swap_buffers = dri2_surface_swap_buffers; - dri2surf->base.flush_frontbuffer = dri2_surface_flush_frontbuffer; + dri2surf->base.present = dri2_surface_present; dri2surf->base.validate = dri2_surface_validate; dri2surf->base.wait = dri2_surface_wait; @@ -630,9 +655,14 @@ dri2_display_get_param(struct native_display *ndpy, switch (param) { case NATIVE_PARAM_USE_NATIVE_BUFFER: - /* DRI2GetBuffers use the native buffers */ + /* DRI2GetBuffers uses the native buffers */ + val = TRUE; + break; + case NATIVE_PARAM_PRESERVE_BUFFER: + /* DRI2CopyRegion is used */ val = TRUE; break; + case NATIVE_PARAM_MAX_SWAP_INTERVAL: default: val = 0; break; diff --git a/src/gallium/state_trackers/egl/x11/native_x11.h b/src/gallium/state_trackers/egl/x11/native_x11.h index 0b47837e1b..8945117276 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.h +++ b/src/gallium/state_trackers/egl/x11/native_x11.h @@ -27,6 +27,7 @@ #define _NATIVE_X11_H_ #include "common/native.h" +#include <X11/Xlib.h> struct native_display * x11_create_ximage_display(Display *dpy, diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c index 4b32f6e36e..84811fb6e1 100644 --- a/src/gallium/state_trackers/egl/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl/x11/native_ximage.c @@ -175,6 +175,32 @@ ximage_surface_swap_buffers(struct native_surface *nsurf) } static boolean +ximage_surface_present(struct native_surface *nsurf, + enum native_attachment natt, + boolean preserve, + uint swap_interval) +{ + boolean ret; + + if (preserve || swap_interval) + return FALSE; + + switch (natt) { + case NATIVE_ATTACHMENT_FRONT_LEFT: + ret = ximage_surface_flush_frontbuffer(nsurf); + break; + case NATIVE_ATTACHMENT_BACK_LEFT: + ret = ximage_surface_swap_buffers(nsurf); + break; + default: + ret = FALSE; + break; + } + + return ret; +} + +static boolean ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask, unsigned int *seq_num, struct pipe_resource **textures, int *width, int *height) @@ -257,8 +283,7 @@ ximage_display_create_surface(struct native_display *ndpy, xsurf->xdraw.drawable = xsurf->drawable; xsurf->base.destroy = ximage_surface_destroy; - xsurf->base.swap_buffers = ximage_surface_swap_buffers; - xsurf->base.flush_frontbuffer = ximage_surface_flush_frontbuffer; + xsurf->base.present = ximage_surface_present; xsurf->base.validate = ximage_surface_validate; xsurf->base.wait = ximage_surface_wait; @@ -416,6 +441,8 @@ ximage_display_get_param(struct native_display *ndpy, /* private buffers are allocated */ val = FALSE; break; + case NATIVE_PARAM_PRESERVE_BUFFER: + case NATIVE_PARAM_MAX_SWAP_INTERVAL: default: val = 0; break; |