X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fstate_trackers%2Fegl%2Fcommon%2Fegl_g3d_api.c;h=a73859c0b9da44a8304a2b5cccb2899fc77a8b45;hb=d7522ed13052a3d30bc4faedce04685263f57933;hp=7a0d6a40e1da768fdce7e9ef98e18da3d7419484;hpb=31520548b763947da6b70b6debe38820835c5bcc;p=mesa.git 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 7a0d6a40e1d..a73859c0b9d 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c @@ -39,6 +39,10 @@ #include "egl_g3d_st.h" #include "native.h" +#ifdef EGL_WL_bind_wayland_display +#include +#endif + /** * Return the state tracker for the given context. */ @@ -86,11 +90,18 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx, return stapi; } +struct egl_g3d_choose_config_data { + _EGLConfig criteria; + enum pipe_format format; +}; + static int egl_g3d_compare_config(const _EGLConfig *conf1, const _EGLConfig *conf2, void *priv_data) { - const _EGLConfig *criteria = (const _EGLConfig *) priv_data; + struct egl_g3d_choose_config_data *data = + (struct egl_g3d_choose_config_data *) priv_data; + const _EGLConfig *criteria = &data->criteria;; /* EGL_NATIVE_VISUAL_TYPE ignored? */ return _eglCompareConfigs(conf1, conf2, criteria, EGL_TRUE); @@ -99,36 +110,39 @@ egl_g3d_compare_config(const _EGLConfig *conf1, const _EGLConfig *conf2, static EGLBoolean egl_g3d_match_config(const _EGLConfig *conf, void *priv_data) { - const _EGLConfig *criteria = (const _EGLConfig *) priv_data; + struct egl_g3d_choose_config_data *data = + (struct egl_g3d_choose_config_data *) priv_data; + struct egl_g3d_config *gconf = egl_g3d_config(conf); - if (!_eglMatchConfig(conf, criteria)) + if (data->format != PIPE_FORMAT_NONE && + data->format != gconf->native->color_format) 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; + return _eglMatchConfig(conf, &data->criteria); } static EGLBoolean egl_g3d_choose_config(_EGLDriver *drv, _EGLDisplay *dpy, const EGLint *attribs, EGLConfig *configs, EGLint size, EGLint *num_configs) { - _EGLConfig criteria; + struct egl_g3d_choose_config_data data; - if (!_eglParseConfigAttribList(&criteria, dpy, attribs)) + if (!_eglParseConfigAttribList(&data.criteria, dpy, attribs)) return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); + data.format = PIPE_FORMAT_NONE; + if (data.criteria.MatchNativePixmap != EGL_NONE && + data.criteria.MatchNativePixmap != EGL_DONT_CARE) { + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + + if (!gdpy->native->get_pixmap_format(gdpy->native, + (EGLNativePixmapType) data.criteria.MatchNativePixmap, + &data.format)) + return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglChooseConfig"); + } + return _eglFilterConfigArray(dpy->Configs, configs, size, num_configs, - egl_g3d_match_config, egl_g3d_compare_config, &criteria); + egl_g3d_match_config, egl_g3d_compare_config, &data); } static _EGLContext * @@ -140,6 +154,7 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, struct egl_g3d_config *gconf = egl_g3d_config(conf); struct egl_g3d_context *gctx; struct st_context_attribs stattribs; + enum st_context_error ctx_err = 0; gctx = CALLOC_STRUCT(egl_g3d_context); if (!gctx) { @@ -162,8 +177,8 @@ egl_g3d_create_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, return NULL; } - gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi, - &stattribs, (gshare) ? gshare->stctxi : NULL); + gctx->stctxi = gctx->stapi->create_context(gctx->stapi, gdpy->smapi, + &stattribs, &ctx_err, (gshare) ? gshare->stctxi : NULL); if (!gctx->stctxi) { FREE(gctx); return NULL; @@ -286,6 +301,10 @@ egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, gconf->stvis.buffer_mask & ST_ATTACHMENT_FRONT_LEFT_MASK) gsurf->stvis.render_buffer = ST_ATTACHMENT_FRONT_LEFT; + /* surfaces can always be posted when the display supports it */ + if (dpy->Extensions.NV_post_sub_buffer) + gsurf->base.PostSubBufferSupportedNV = EGL_TRUE; + gsurf->stfbi = egl_g3d_create_st_framebuffer(&gsurf->base); if (!gsurf->stfbi) { nsurf->destroy(nsurf); @@ -494,19 +513,12 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, (gdraw) ? gdraw->stfbi : NULL, (gread) ? gread->stfbi : NULL); if (ok) { if (gdraw) { - gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, - gdraw->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; } } - if (gread && gread != gdraw) { - gctx->stctxi->notify_invalid_framebuffer(gctx->stctxi, - gread->stfbi); - } } } else if (old_gctx) { @@ -543,11 +555,13 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy, } static EGLBoolean -egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) +swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, + EGLint num_rects, const EGLint *rects, EGLBoolean preserve) { struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); _EGLContext *ctx = _eglGetCurrentContext(); struct egl_g3d_context *gctx = NULL; + struct native_present_control ctrl; /* no-op for pixmap or pbuffer surface */ if (gsurf->base.Type == EGL_PIXMAP_BIT || @@ -566,10 +580,61 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) gctx->stctxi->flush(gctx->stctxi, ST_FLUSH_FRONT, NULL); } - return gsurf->native->present(gsurf->native, - NATIVE_ATTACHMENT_BACK_LEFT, - gsurf->base.SwapBehavior == EGL_BUFFER_PRESERVED, - gsurf->base.SwapInterval); + memset(&ctrl, 0, sizeof(ctrl)); + ctrl.natt = NATIVE_ATTACHMENT_BACK_LEFT; + ctrl.preserve = preserve; + ctrl.swap_interval = gsurf->base.SwapInterval; + ctrl.premultiplied_alpha = (gsurf->base.VGAlphaFormat == EGL_VG_ALPHA_FORMAT_PRE); + ctrl.num_rects = num_rects; + ctrl.rects = rects; + + return gsurf->native->present(gsurf->native, &ctrl); +} + +static EGLBoolean +egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) +{ + struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); + + return swap_buffers(drv, dpy, surf, 0, NULL, + (gsurf->base.SwapBehavior == EGL_BUFFER_PRESERVED)); +} + +#ifdef EGL_NOK_swap_region +static EGLBoolean +egl_g3d_swap_buffers_region(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, + EGLint num_rects, const EGLint *rects) +{ + /* Note: y=0=top */ + return swap_buffers(drv, dpy, surf, num_rects, rects, EGL_TRUE); +} +#endif /* EGL_NOK_swap_region */ + +static EGLBoolean +egl_g3d_post_sub_buffer(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, + EGLint x, EGLint y, EGLint width, EGLint height) +{ + EGLint rect[4]; + + if (x < 0 || y < 0 || width < 0 || height < 0) + return _eglError(EGL_BAD_PARAMETER, "eglPostSubBufferNV"); + + /* clamp */ + if (x + width > surf->Width) + width = surf->Width - x; + if (y + height > surf->Height) + height = surf->Height - y; + + if (width <= 0 || height <= 0) + return EGL_TRUE; + + rect[0] = x; + /* Note: y=0=bottom */ + rect[1] = surf->Height - y - height; + rect[2] = width; + rect[3] = height; + + return swap_buffers(drv, dpy, surf, 1, rect, EGL_TRUE); } static EGLBoolean @@ -812,6 +877,39 @@ egl_g3d_unbind_wayland_display_wl(_EGLDriver *drv, _EGLDisplay *dpy, return gdpy->native->wayland_bufmgr->unbind_display(gdpy->native, wl_dpy); } +static EGLBoolean +egl_g3d_query_wayland_buffer_wl(_EGLDriver *drv, _EGLDisplay *dpy, + struct wl_buffer *_buffer, + EGLint attribute, EGLint *value) +{ + struct wl_drm_buffer *buffer = (struct wl_drm_buffer *) _buffer; + struct pipe_resource *resource = buffer->driver_buffer; + + if (!wayland_buffer_is_drm(&buffer->buffer)) + return EGL_FALSE; + + switch (attribute) { + case EGL_TEXTURE_FORMAT: + switch (resource->format) { + case PIPE_FORMAT_B8G8R8A8_UNORM: + *value = EGL_TEXTURE_RGBA; + return EGL_TRUE; + case PIPE_FORMAT_B8G8R8X8_UNORM: + *value = EGL_TEXTURE_RGB; + return EGL_TRUE; + default: + return EGL_FALSE; + } + case EGL_WIDTH: + *value = buffer->buffer.width; + return EGL_TRUE; + case EGL_HEIGHT: + *value = buffer->buffer.height; + return EGL_TRUE; + default: + return EGL_FALSE; + } +} #endif /* EGL_WL_bind_wayland_display */ void @@ -846,18 +944,22 @@ egl_g3d_init_driver_api(_EGLDriver *drv) #ifdef EGL_WL_bind_wayland_display drv->API.BindWaylandDisplayWL = egl_g3d_bind_wayland_display_wl; drv->API.UnbindWaylandDisplayWL = egl_g3d_unbind_wayland_display_wl; - + drv->API.QueryWaylandBufferWL = egl_g3d_query_wayland_buffer_wl; #endif -#ifdef EGL_KHR_reusable_sync drv->API.CreateSyncKHR = egl_g3d_create_sync; drv->API.DestroySyncKHR = egl_g3d_destroy_sync; drv->API.ClientWaitSyncKHR = egl_g3d_client_wait_sync; drv->API.SignalSyncKHR = egl_g3d_signal_sync; -#endif #ifdef EGL_MESA_screen_surface drv->API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface; drv->API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface; #endif + +#ifdef EGL_NOK_swap_region + drv->API.SwapBuffersRegionNOK = egl_g3d_swap_buffers_region; +#endif + + drv->API.PostSubBufferNV = egl_g3d_post_sub_buffer; }