diff options
Diffstat (limited to 'src/gallium/state_trackers/egl')
25 files changed, 787 insertions, 612 deletions
diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile index 763e7b58a49..1c970222c1f 100644 --- a/src/gallium/state_trackers/egl/Makefile +++ b/src/gallium/state_trackers/egl/Makefile @@ -33,7 +33,8 @@ wayland_INCLUDES = \ wayland_SOURCES = $(wildcard wayland/*.c) wayland_OBJECTS = $(wayland_SOURCES:.c=.o) -drm_INCLUDES = -I$(TOP)/src/gallium/winsys $(shell pkg-config --cflags-only-I libdrm) +drm_INCLUDES = -I$(TOP)/src/gallium/winsys $(shell pkg-config --cflags-only-I libdrm) \ + -I$(TOP)/src/gbm/main -I$(TOP)/src/gallium/state_trackers/gbm drm_SOURCES = $(wildcard drm/*.c) drm_OBJECTS = $(drm_SOURCES:.c=.o) diff --git a/src/gallium/state_trackers/egl/SConscript b/src/gallium/state_trackers/egl/SConscript index 9ade76ecbb2..c04fec637c1 100644 --- a/src/gallium/state_trackers/egl/SConscript +++ b/src/gallium/state_trackers/egl/SConscript @@ -40,7 +40,12 @@ else: env.Append(CPPDEFINES = ['GLX_DIRECT_RENDERING']) sources.append(['#/src/glx/dri2.c']) if env['drm']: + env.PkgUseModules('DRM') env.Append(CPPDEFINES = ['HAVE_DRM_BACKEND']) + env.Append(CPPPATH = [ + '#/src/gbm/main', + '#/src/gallium/state_trackers/gbm', + ]) sources.append(['drm/native_drm.c', 'drm/modeset.c']) st_egl = env.ConvenienceLibrary( diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index 29dbbefbf48..6649f02b244 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -31,6 +31,7 @@ #include "util/u_memory.h" #include "util/u_format.h" #include "util/u_string.h" +#include "util/u_atomic.h" #include "egl_g3d.h" #include "egl_g3d_api.h" @@ -45,15 +46,9 @@ egl_g3d_invalid_surface(struct native_display *ndpy, { /* XXX not thread safe? */ struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data); - struct egl_g3d_context *gctx; - - /* - * 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); + + if (gsurf && gsurf->stfbi) + p_atomic_inc(&gsurf->stfbi->stamp); } static struct pipe_screen * @@ -72,10 +67,26 @@ egl_g3d_new_sw_screen(struct native_display *ndpy, struct sw_winsys *ws) return gdpy->loader->create_sw_screen(ws); } -static struct native_event_handler egl_g3d_native_event_handler = { +static struct pipe_resource * +egl_g3d_lookup_egl_image(struct native_display *ndpy, void *egl_image) +{ + _EGLDisplay *dpy = (_EGLDisplay *) ndpy->user_data; + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct st_egl_image img; + struct pipe_resource *resource = NULL; + + memset(&img, 0, sizeof(img)); + if (gdpy->smapi->get_egl_image(gdpy->smapi, egl_image, &img)) + resource = img.texture; + + return resource; +} + +static const struct native_event_handler egl_g3d_native_event_handler = { egl_g3d_invalid_surface, egl_g3d_new_drm_screen, - egl_g3d_new_sw_screen + egl_g3d_new_sw_screen, + egl_g3d_lookup_egl_image }; /** @@ -94,40 +105,38 @@ egl_g3d_get_platform(_EGLDriver *drv, _EGLPlatformType plat) case _EGL_PLATFORM_WINDOWS: plat_name = "Windows"; #ifdef HAVE_GDI_BACKEND - nplat = native_get_gdi_platform(); + nplat = native_get_gdi_platform(&egl_g3d_native_event_handler); #endif break; case _EGL_PLATFORM_X11: plat_name = "X11"; #ifdef HAVE_X11_BACKEND - nplat = native_get_x11_platform(); + nplat = native_get_x11_platform(&egl_g3d_native_event_handler); #endif break; case _EGL_PLATFORM_WAYLAND: plat_name = "wayland"; #ifdef HAVE_WAYLAND_BACKEND - nplat = native_get_wayland_platform(); + nplat = native_get_wayland_platform(&egl_g3d_native_event_handler); #endif break; case _EGL_PLATFORM_DRM: plat_name = "DRM"; #ifdef HAVE_DRM_BACKEND - nplat = native_get_drm_platform(); + nplat = native_get_drm_platform(&egl_g3d_native_event_handler); #endif break; case _EGL_PLATFORM_FBDEV: plat_name = "FBDEV"; #ifdef HAVE_FBDEV_BACKEND - nplat = native_get_fbdev_platform(); + nplat = native_get_fbdev_platform(&egl_g3d_native_event_handler); #endif break; default: break; } - if (nplat) - nplat->set_event_handler(&egl_g3d_native_event_handler); - else + if (!nplat) _eglLog(_EGL_WARNING, "unsupported platform %s", plat_name); gdrv->platforms[plat] = nplat; @@ -504,13 +513,20 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy) gdpy->loader = gdrv->loader; dpy->DriverData = gdpy; - _eglLog(_EGL_INFO, "use %s for display %p", nplat->name, dpy->PlatformDisplay); - gdpy->native = nplat->create_display(dpy->PlatformDisplay, - dpy->Options.UseFallback, (void *) dpy); + _eglLog(_EGL_INFO, "use %s for display %p", + nplat->name, dpy->PlatformDisplay); + gdpy->native = + nplat->create_display(dpy->PlatformDisplay, dpy->Options.UseFallback); if (!gdpy->native) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); goto fail; } + gdpy->native->user_data = (void *) dpy; + if (!gdpy->native->init_screen(gdpy->native)) { + _eglError(EGL_NOT_INITIALIZED, + "eglInitialize(failed to initialize screen)"); + goto fail; + } if (gdpy->loader->profile_masks[ST_API_OPENGL] & ST_PROFILE_DEFAULT_MASK) dpy->ClientAPIs |= EGL_OPENGL_BIT; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h index 301db3128ff..5989a023573 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d.h @@ -126,4 +126,12 @@ _EGL_DRIVER_TYPECAST(egl_g3d_screen, _EGLScreen, obj) #endif /* EGL_MESA_screen_surface */ +static INLINE struct st_api * +egl_g3d_get_st_api(_EGLDriver *drv, enum st_api_type api) +{ + struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); + + return gdrv->loader->get_st_api(api); +} + #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 index 8b1821e0055..f897054a540 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c @@ -37,7 +37,6 @@ #include "egl_g3d_image.h" #include "egl_g3d_sync.h" #include "egl_g3d_st.h" -#include "egl_g3d_loader.h" #include "native.h" /** @@ -47,7 +46,6 @@ static struct st_api * egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx, enum st_profile_type *profile) { - struct egl_g3d_driver *gdrv = egl_g3d_driver(drv); struct st_api *stapi; EGLint api = -1; @@ -81,96 +79,66 @@ egl_g3d_choose_st(_EGLDriver *drv, _EGLContext *ctx, break; } - switch (api) { - case ST_API_OPENGL: - stapi = gdrv->loader->guess_gl_api(*profile); - break; - case ST_API_OPENVG: - stapi = gdrv->loader->get_st_api(api); - break; - default: - stapi = NULL; - break; - } + stapi = egl_g3d_get_st_api(drv, api); if (stapi && !(stapi->profile_mask & (1 << *profile))) stapi = NULL; 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); } static EGLBoolean -egl_g3d_match_config(const _EGLConfig *conf, const _EGLConfig *criteria) +egl_g3d_match_config(const _EGLConfig *conf, void *priv_data) { - 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; + 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 (!gdpy->native->is_pixmap_supported(gdpy->native, pix, gconf->native)) - return EGL_FALSE; - } + if (data->format != PIPE_FORMAT_NONE && + data->format != gconf->native->color_format) + 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 **tmp_configs, criteria; - EGLint tmp_size, i; - - if (!num_configs) - return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs"); + struct egl_g3d_choose_config_data data; - if (!_eglParseConfigAttribList(&criteria, dpy, attribs)) + if (!_eglParseConfigAttribList(&data.criteria, dpy, attribs)) return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); - /* get the number of matched configs */ - tmp_size = _eglFilterArray(dpy->Configs, NULL, 0, - (_EGLArrayForEach) egl_g3d_match_config, (void *) &criteria); - if (!tmp_size) { - *num_configs = tmp_size; - return EGL_TRUE; - } - - tmp_configs = MALLOC(sizeof(tmp_configs[0]) * tmp_size); - if (!tmp_configs) - return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)"); + 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); - /* get the matched configs */ - _eglFilterArray(dpy->Configs, (void **) tmp_configs, tmp_size, - (_EGLArrayForEach) egl_g3d_match_config, (void *) &criteria); - - /* perform sorting of configs */ - if (configs && tmp_size) { - _eglSortConfigs((const _EGLConfig **) tmp_configs, tmp_size, - egl_g3d_compare_config, (void *) &criteria); - tmp_size = MIN2(tmp_size, size); - for (i = 0; i < tmp_size; i++) - configs[i] = _eglGetConfigHandle(tmp_configs[i]); + if (!gdpy->native->get_pixmap_format(gdpy->native, + (EGLNativePixmapType) data.criteria.MatchNativePixmap, + &data.format)) + return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglChooseConfig"); } - FREE(tmp_configs); - - *num_configs = tmp_size; - - return EGL_TRUE; + return _eglFilterConfigArray(dpy->Configs, configs, size, num_configs, + egl_g3d_match_config, egl_g3d_compare_config, &data); } static _EGLContext * @@ -536,19 +504,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) { @@ -614,21 +575,6 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) gsurf->base.SwapInterval); } -/** - * Get the pipe surface of the given attachment of the native surface. - */ -static struct pipe_resource * -get_pipe_resource(struct native_display *ndpy, struct native_surface *nsurf, - enum native_attachment natt) -{ - struct pipe_resource *textures[NUM_NATIVE_ATTACHMENTS]; - - textures[natt] = NULL; - nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL); - - return textures[natt]; -} - static EGLBoolean egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLNativePixmapType target) @@ -636,43 +582,18 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, struct egl_g3d_display *gdpy = egl_g3d_display(dpy); struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); _EGLContext *ctx = _eglGetCurrentContext(); - struct native_surface *nsurf; - struct pipe_resource *ptex; - struct pipe_context *pipe; if (!gsurf->render_texture) return EGL_TRUE; - nsurf = gdpy->native->create_pixmap_surface(gdpy->native, target, NULL); - 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, ST_FLUSH_FRONT, NULL); } - pipe = ndpy_get_copy_context(gdpy->native); - if (!pipe) - return EGL_FALSE; - - ptex = get_pipe_resource(gdpy->native, nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); - if (ptex) { - struct pipe_box src_box; - - u_box_origin_2d(ptex->width0, ptex->height0, &src_box); - pipe->resource_copy_region(pipe, ptex, 0, 0, 0, 0, - gsurf->render_texture, 0, &src_box); - pipe->flush(pipe, NULL); - nsurf->present(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT, FALSE, 0); - - pipe_resource_reference(&ptex, NULL); - } - - nsurf->destroy(nsurf); - - return EGL_TRUE; + return gdpy->native->copy_to_pixmap(gdpy->native, + target, gsurf->render_texture); } static EGLBoolean 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 ce72e27c3d5..7e9a29b0284 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_image.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c @@ -37,9 +37,6 @@ #include "egl_g3d.h" #include "egl_g3d_image.h" -/* for struct winsys_handle */ -#include "state_tracker/drm_driver.h" - /** * Reference and return the front left buffer of the native pixmap. */ @@ -137,10 +134,9 @@ 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_resource templ; - struct winsys_handle wsh; _EGLImageAttribs attrs; EGLint format; + struct native_buffer nbuf; if (!dpy->Extensions.MESA_drm_image) return NULL; @@ -166,21 +162,21 @@ egl_g3d_reference_drm_buffer(_EGLDisplay *dpy, EGLint name, break; } - memset(&templ, 0, sizeof(templ)); - templ.target = PIPE_TEXTURE_2D; - templ.format = format; - templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; - templ.width0 = attrs.Width; - templ.height0 = attrs.Height; - templ.depth0 = 1; - templ.array_size = 1; - - memset(&wsh, 0, sizeof(wsh)); - wsh.handle = (unsigned) name; - wsh.stride = - attrs.DRMBufferStrideMESA * util_format_get_blocksize(templ.format); - - return gdpy->native->buffer->import_buffer(gdpy->native, &templ, &wsh); + memset(&nbuf, 0, sizeof(nbuf)); + nbuf.type = NATIVE_BUFFER_DRM; + nbuf.u.drm.templ.target = PIPE_TEXTURE_2D; + nbuf.u.drm.templ.format = format; + nbuf.u.drm.templ.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + nbuf.u.drm.templ.width0 = attrs.Width; + nbuf.u.drm.templ.height0 = attrs.Height; + nbuf.u.drm.templ.depth0 = 1; + nbuf.u.drm.templ.array_size = 1; + + nbuf.u.drm.name = name; + nbuf.u.drm.stride = + attrs.DRMBufferStrideMESA * util_format_get_blocksize(format); + + return gdpy->native->buffer->import_buffer(gdpy->native, &nbuf); } #endif /* EGL_MESA_drm_image */ @@ -327,35 +323,26 @@ 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 winsys_handle wsh; + struct native_buffer nbuf; if (!dpy->Extensions.MESA_drm_image) return EGL_FALSE; - /* get shared handle */ - if (name) { - memset(&handle, 0, sizeof(handle)); - wsh.type = DRM_API_HANDLE_TYPE_SHARED; - if (!gdpy->native->buffer->export_buffer(gdpy->native, - gimg->texture, &wsh)) - return EGL_FALSE; + memset(&nbuf, 0, sizeof(nbuf)); + nbuf.type = NATIVE_BUFFER_DRM; + if (name) + nbuf.u.drm.templ.bind |= PIPE_BIND_SHARED; - *name = wsh.handle; - } + if (!gdpy->native->buffer->export_buffer(gdpy->native, + gimg->texture, &nbuf)) + return EGL_FALSE; - /* get KMS handle */ - if (handle || stride) { - memset(&wsh, 0, sizeof(wsh)); - wsh.type = DRM_API_HANDLE_TYPE_KMS; - if (!gdpy->native->buffer->export_buffer(gdpy->native, - gimg->texture, &wsh)) - return EGL_FALSE; - - if (handle) - *handle = wsh.handle; - if (stride) - *stride = wsh.stride; - } + if (name) + *name = nbuf.u.drm.name; + if (handle) + *handle = nbuf.u.drm.handle; + if (stride) + *stride = nbuf.u.drm.stride; return EGL_TRUE; } diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_loader.h b/src/gallium/state_trackers/egl/common/egl_g3d_loader.h index 78bfe2131ef..e9403fa293b 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_loader.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d_loader.h @@ -39,7 +39,6 @@ struct sw_winsys; struct egl_g3d_loader { uint profile_masks[ST_API_COUNT]; struct st_api *(*get_st_api)(enum st_api_type api); - struct st_api *(*guess_gl_api)(enum st_profile_type profile); struct pipe_screen *(*create_drm_screen)(const char *name, int fd); struct pipe_screen *(*create_sw_screen)(struct sw_winsys *ws); 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 2b944b521a4..60c3e332ac9 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_st.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_st.c @@ -292,6 +292,8 @@ egl_g3d_create_st_framebuffer(_EGLSurface *surf) return NULL; stfbi->visual = &gsurf->stvis; + p_atomic_set(&stfbi->stamp, 1); + if (gsurf->base.Type != EGL_PBUFFER_BIT) { stfbi->flush_front = egl_g3d_st_framebuffer_flush_front; stfbi->validate = egl_g3d_st_framebuffer_validate; diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h index 8646e52ed7c..fc50ee485fe 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -152,6 +152,11 @@ struct native_display { */ void *user_data; + /** + * Initialize and create the pipe screen. + */ + boolean (*init_screen)(struct native_display *ndpy); + void (*destroy)(struct native_display *ndpy); /** @@ -170,16 +175,21 @@ struct native_display { int *num_configs); /** - * Test if a pixmap is supported by the given config. Required unless no - * 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. + * Get the color format of the pixmap. Required unless no config has + * pixmap_bit set. */ - boolean (*is_pixmap_supported)(struct native_display *ndpy, - EGLNativePixmapType pix, - const struct native_config *nconf); + boolean (*get_pixmap_format)(struct native_display *ndpy, + EGLNativePixmapType pix, + enum pipe_format *format); + /** + * Copy the contents of the resource to the pixmap's front-left attachment. + * This is used to implement eglCopyBuffers. Required unless no config has + * pixmap_bit set. + */ + boolean (*copy_to_pixmap)(struct native_display *ndpy, + EGLNativePixmapType pix, + struct pipe_resource *src); /** * Create a window surface. Required unless no config has window_bit set. @@ -219,6 +229,9 @@ struct native_event_handler { const char *name, int fd); struct pipe_screen *(*new_sw_screen)(struct native_display *ndpy, struct sw_winsys *ws); + + struct pipe_resource *(*lookup_egl_image)(struct native_display *ndpy, + void *egl_image); }; /** @@ -256,26 +269,29 @@ ndpy_uninit(struct native_display *ndpy) struct native_platform { const char *name; - void (*set_event_handler)(struct native_event_handler *handler); - struct native_display *(*create_display)(void *dpy, - boolean use_sw, - void *user_data); + /** + * Create the native display and usually establish a connection to the + * display server. + * + * No event should be generated at this stage. + */ + struct native_display *(*create_display)(void *dpy, boolean use_sw); }; const struct native_platform * -native_get_gdi_platform(void); +native_get_gdi_platform(const struct native_event_handler *event_handler); const struct native_platform * -native_get_x11_platform(void); +native_get_x11_platform(const struct native_event_handler *event_handler); const struct native_platform * -native_get_wayland_platform(void); +native_get_wayland_platform(const struct native_event_handler *event_handler); const struct native_platform * -native_get_drm_platform(void); +native_get_drm_platform(const struct native_event_handler *event_handler); const struct native_platform * -native_get_fbdev_platform(void); +native_get_fbdev_platform(const struct native_event_handler *event_handler); #ifdef __cplusplus } diff --git a/src/gallium/state_trackers/egl/common/native_buffer.h b/src/gallium/state_trackers/egl/common/native_buffer.h index 5c29ab97411..b8a66d17e12 100644 --- a/src/gallium/state_trackers/egl/common/native_buffer.h +++ b/src/gallium/state_trackers/egl/common/native_buffer.h @@ -30,30 +30,43 @@ #define _NATIVE_BUFFER_H_ #include "pipe/p_compiler.h" +#include "pipe/p_state.h" struct native_display; -struct pipe_resource; + +enum native_buffer_type { + NATIVE_BUFFER_DRM, + + NUM_NATIVE_BUFFERS +}; + +struct native_buffer { + enum native_buffer_type type; + + union { + struct { + struct pipe_resource templ; + unsigned name; /**< the name of the GEM object */ + unsigned handle; /**< the handle of the GEM object */ + unsigned stride; + } drm; + } u; +}; /** * 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); + struct native_buffer *buf); /** * The resource must be creatred with PIPE_BIND_SHARED. */ boolean (*export_buffer)(struct native_display *ndpy, struct pipe_resource *res, - void *buf); + struct native_buffer *nbuf); }; #endif /* _NATIVE_BUFFER_H_ */ diff --git a/src/gallium/state_trackers/egl/common/native_helper.c b/src/gallium/state_trackers/egl/common/native_helper.c index ee18cb2025b..cca1e1c6295 100644 --- a/src/gallium/state_trackers/egl/common/native_helper.c +++ b/src/gallium/state_trackers/egl/common/native_helper.c @@ -282,9 +282,9 @@ resource_surface_copy_swap(struct resource_surface *rsurf, btex, 0, &src_box); ret = TRUE; - out_no_ftex: - pipe_resource_reference(&btex, NULL); out_no_btex: + pipe_resource_reference(&btex, NULL); + out_no_ftex: pipe_resource_reference(&ftex, NULL); return ret; @@ -367,3 +367,116 @@ resource_surface_wait(struct resource_surface *rsurf) { while (resource_surface_throttle(rsurf)); } + +boolean +native_display_copy_to_pixmap(struct native_display *ndpy, + EGLNativePixmapType pix, + struct pipe_resource *src) +{ + struct pipe_context *pipe; + struct native_surface *nsurf; + struct pipe_resource *dst; + struct pipe_resource *tmp[NUM_NATIVE_ATTACHMENTS]; + const enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT; + + pipe = ndpy_get_copy_context(ndpy); + if (!pipe) + return FALSE; + + nsurf = ndpy->create_pixmap_surface(ndpy, pix, NULL); + if (!nsurf) + return FALSE; + + /* get the texutre */ + tmp[natt] = NULL; + nsurf->validate(nsurf, 1 << natt, NULL, tmp, NULL, NULL); + dst = tmp[natt]; + + if (dst && dst->format == src->format) { + struct pipe_box src_box; + + u_box_origin_2d(src->width0, src->height0, &src_box); + pipe->resource_copy_region(pipe, dst, 0, 0, 0, 0, src, 0, &src_box); + pipe->flush(pipe, NULL); + nsurf->present(nsurf, natt, FALSE, 0); + } + + if (dst) + pipe_resource_reference(&dst, NULL); + + nsurf->destroy(nsurf); + + return TRUE; +} + +#include "state_tracker/drm_driver.h" +struct pipe_resource * +drm_display_import_native_buffer(struct native_display *ndpy, + struct native_buffer *nbuf) +{ + struct pipe_screen *screen = ndpy->screen; + struct pipe_resource *res = NULL; + + switch (nbuf->type) { + case NATIVE_BUFFER_DRM: + { + struct winsys_handle wsh; + + memset(&wsh, 0, sizeof(wsh)); + wsh.handle = nbuf->u.drm.name; + wsh.stride = nbuf->u.drm.stride; + + res = screen->resource_from_handle(screen, &nbuf->u.drm.templ, &wsh); + } + break; + default: + break; + } + + return res; +} + +boolean +drm_display_export_native_buffer(struct native_display *ndpy, + struct pipe_resource *res, + struct native_buffer *nbuf) +{ + struct pipe_screen *screen = ndpy->screen; + boolean ret = FALSE; + + switch (nbuf->type) { + case NATIVE_BUFFER_DRM: + { + struct winsys_handle wsh; + + if ((nbuf->u.drm.templ.bind & res->bind) != nbuf->u.drm.templ.bind) + break; + + memset(&wsh, 0, sizeof(wsh)); + wsh.type = DRM_API_HANDLE_TYPE_KMS; + if (!screen->resource_get_handle(screen, res, &wsh)) + break; + + nbuf->u.drm.handle = wsh.handle; + nbuf->u.drm.stride = wsh.stride; + + /* get the name of the GEM object */ + if (nbuf->u.drm.templ.bind & PIPE_BIND_SHARED) { + memset(&wsh, 0, sizeof(wsh)); + wsh.type = DRM_API_HANDLE_TYPE_SHARED; + if (!screen->resource_get_handle(screen, res, &wsh)) + break; + + nbuf->u.drm.name = wsh.handle; + } + + nbuf->u.drm.templ = *res; + ret = TRUE; + } + break; + default: + break; + } + + return ret; +} diff --git a/src/gallium/state_trackers/egl/common/native_helper.h b/src/gallium/state_trackers/egl/common/native_helper.h index 39564a04365..e8d91ccb02a 100644 --- a/src/gallium/state_trackers/egl/common/native_helper.h +++ b/src/gallium/state_trackers/egl/common/native_helper.h @@ -105,3 +105,17 @@ resource_surface_flush(struct resource_surface *rsurf, */ void resource_surface_wait(struct resource_surface *rsurf); + +boolean +native_display_copy_to_pixmap(struct native_display *ndpy, + EGLNativePixmapType pix, + struct pipe_resource *src); + +struct pipe_resource * +drm_display_import_native_buffer(struct native_display *ndpy, + struct native_buffer *nbuf); + +boolean +drm_display_export_native_buffer(struct native_display *ndpy, + struct pipe_resource *res, + struct native_buffer *nbuf); diff --git a/src/gallium/state_trackers/egl/drm/modeset.c b/src/gallium/state_trackers/egl/drm/modeset.c index 3fff9540905..73968d1343b 100644 --- a/src/gallium/state_trackers/egl/drm/modeset.c +++ b/src/gallium/state_trackers/egl/drm/modeset.c @@ -290,6 +290,42 @@ drm_display_create_surface(struct native_display *ndpy, return drmsurf; } +struct native_surface * +drm_display_create_surface_from_resource(struct native_display *ndpy, + struct pipe_resource *resource) +{ + struct drm_display *drmdpy = drm_display(ndpy); + struct drm_surface *drmsurf; + enum native_attachment natt = NATIVE_ATTACHMENT_FRONT_LEFT; + + drmsurf = CALLOC_STRUCT(drm_surface); + if (!drmsurf) + return NULL; + + drmsurf->drmdpy = drmdpy; + drmsurf->color_format = resource->format; + drmsurf->width = resource->width0; + drmsurf->height = resource->height0; + drmsurf->have_pageflip = FALSE; + + drmsurf->rsurf = resource_surface_create(drmdpy->base.screen, + drmsurf->color_format, + PIPE_BIND_RENDER_TARGET | + PIPE_BIND_SAMPLER_VIEW | + PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_SCANOUT); + + resource_surface_import_resource(drmsurf->rsurf, natt, resource); + + drmsurf->base.destroy = drm_surface_destroy; + drmsurf->base.present = drm_surface_present; + drmsurf->base.validate = drm_surface_validate; + drmsurf->base.wait = drm_surface_wait; + + return &drmsurf->base; +} + + /** * Choose a CRTC that supports all given connectors. */ diff --git a/src/gallium/state_trackers/egl/drm/native_drm.c b/src/gallium/state_trackers/egl/drm/native_drm.c index 725fe28e4e2..47910de8d3c 100644 --- a/src/gallium/state_trackers/egl/drm/native_drm.c +++ b/src/gallium/state_trackers/egl/drm/native_drm.c @@ -33,6 +33,8 @@ #include "native_drm.h" +#include "gbm_gallium_drmint.h" + #ifdef HAVE_LIBUDEV #include <libudev.h> #endif @@ -125,6 +127,8 @@ drm_display_destroy(struct native_display *ndpy) drm_display_fini_modeset(&drmdpy->base); + /* gbm owns screen */ + ndpy->screen = NULL; ndpy_uninit(ndpy); if (drmdpy->device_name) @@ -136,54 +140,10 @@ drm_display_destroy(struct native_display *ndpy) FREE(drmdpy); } -/** - * Initialize KMS and pipe screen. - */ -static boolean -drm_display_init_screen(struct native_display *ndpy) -{ - struct drm_display *drmdpy = drm_display(ndpy); - drmVersionPtr version; - - version = drmGetVersion(drmdpy->fd); - if (!version) { - _eglLog(_EGL_WARNING, "invalid fd %d", drmdpy->fd); - return FALSE; - } - - drmdpy->base.screen = - drmdpy->event_handler->new_drm_screen(&drmdpy->base, NULL, drmdpy->fd); - drmFreeVersion(version); - - if (!drmdpy->base.screen) { - _eglLog(_EGL_DEBUG, "failed to create DRM screen"); - return FALSE; - } - - 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 + /* use the helpers */ + drm_display_import_native_buffer, + drm_display_export_native_buffer }; static int @@ -281,9 +241,25 @@ static struct native_display_wayland_bufmgr drm_display_wayland_bufmgr = { #endif /* HAVE_WAYLAND_BACKEND */ +static struct native_surface * +drm_create_pixmap_surface(struct native_display *ndpy, + EGLNativePixmapType pix, + const struct native_config *nconf) +{ + struct gbm_gallium_drm_bo *bo = (void *) pix; + + return drm_display_create_surface_from_resource(ndpy, bo->resource); +} + +static boolean +drm_display_init_screen(struct native_display *ndpy) +{ + return TRUE; +} + static struct native_display * -drm_create_display(int fd, struct native_event_handler *event_handler, - void *user_data) +drm_create_display(struct gbm_gallium_drm_device *gbmdrm, + const struct native_event_handler *event_handler) { struct drm_display *drmdpy; @@ -291,20 +267,24 @@ drm_create_display(int fd, struct native_event_handler *event_handler, if (!drmdpy) return NULL; - drmdpy->fd = fd; - drmdpy->device_name = drm_get_device_name(fd); + drmdpy->fd = gbmdrm->base.base.fd; + drmdpy->device_name = drm_get_device_name(drmdpy->fd); + + gbmdrm->lookup_egl_image = (struct pipe_resource *(*)(void *, void *)) + event_handler->lookup_egl_image; + gbmdrm->lookup_egl_image_data = &drmdpy->base; + drmdpy->event_handler = event_handler; - drmdpy->base.user_data = user_data; - if (!drm_display_init_screen(&drmdpy->base)) { - drm_display_destroy(&drmdpy->base); - return NULL; - } + drmdpy->base.screen = gbmdrm->screen; + drmdpy->base.init_screen = drm_display_init_screen; drmdpy->base.destroy = drm_display_destroy; drmdpy->base.get_param = drm_display_get_param; drmdpy->base.get_configs = drm_display_get_configs; + drmdpy->base.create_pixmap_surface = drm_create_pixmap_surface; + drmdpy->base.buffer = &drm_display_buffer; #ifdef HAVE_WAYLAND_BACKEND if (drmdpy->device_name) @@ -315,39 +295,39 @@ drm_create_display(int fd, struct native_event_handler *event_handler, return &drmdpy->base; } -static struct native_event_handler *drm_event_handler; - -static void -native_set_event_handler(struct native_event_handler *event_handler) -{ - drm_event_handler = event_handler; -} +static const struct native_event_handler *drm_event_handler; static struct native_display * -native_create_display(void *dpy, boolean use_sw, void *user_data) +native_create_display(void *dpy, boolean use_sw) { + struct gbm_gallium_drm_device *gbm; int fd; - if (dpy) { - fd = dup((int) pointer_to_intptr(dpy)); - } - else { + gbm = dpy; + + if (gbm == NULL) { fd = open("/dev/dri/card0", O_RDWR); + gbm = gbm_gallium_drm_device(gbm_create_device(fd)); } - if (fd < 0) + + if (gbm == NULL) + return NULL; + + if (strcmp(gbm_device_get_backend_name(&gbm->base.base), "drm") != 0 || + gbm->base.type != GBM_DRM_DRIVER_TYPE_GALLIUM) return NULL; - return drm_create_display(fd, drm_event_handler, user_data); + return drm_create_display(gbm, drm_event_handler); } static const struct native_platform drm_platform = { "DRM", /* name */ - native_set_event_handler, native_create_display }; const struct native_platform * -native_get_drm_platform(void) +native_get_drm_platform(const struct native_event_handler *event_handler) { + drm_event_handler = event_handler; return &drm_platform; } diff --git a/src/gallium/state_trackers/egl/drm/native_drm.h b/src/gallium/state_trackers/egl/drm/native_drm.h index 41cdc4f9d04..675a58a1922 100644 --- a/src/gallium/state_trackers/egl/drm/native_drm.h +++ b/src/gallium/state_trackers/egl/drm/native_drm.h @@ -50,7 +50,7 @@ struct drm_surface; struct drm_display { struct native_display base; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; int fd; char *device_name; @@ -154,4 +154,8 @@ drm_display_init_modeset(struct native_display *ndpy); void drm_display_fini_modeset(struct native_display *ndpy); +struct native_surface * +drm_display_create_surface_from_resource(struct native_display *ndpy, + struct pipe_resource *resource); + #endif /* _NATIVE_DRM_H_ */ diff --git a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c index e2fde00e975..6772d379f73 100644 --- a/src/gallium/state_trackers/egl/fbdev/native_fbdev.c +++ b/src/gallium/state_trackers/egl/fbdev/native_fbdev.c @@ -26,6 +26,21 @@ * Chia-I Wu <[email protected]> */ +/** + * Considering fbdev as an in-kernel window system, + * + * - opening a device opens a connection + * - there is only one window: the framebuffer + * - fb_var_screeninfo decides window position, size, and even color format + * - there is no pixmap + * + * Now EGL is built on top of this window system. So we should have + * + * - the fd as the handle of the native display + * - reject all but one native window: NULL + * - no pixmap support + */ + #include <sys/ioctl.h> #include <sys/types.h> #include <sys/stat.h> @@ -45,16 +60,13 @@ struct fbdev_display { struct native_display base; int fd; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; struct fb_fix_screeninfo finfo; - struct fb_var_screeninfo vinfo; - + struct fb_var_screeninfo config_vinfo; struct native_config config; - struct native_connector connector; - struct native_mode mode; - struct fbdev_surface *current_surface; + boolean assume_fixed_vinfo; }; struct fbdev_surface { @@ -66,7 +78,7 @@ struct fbdev_surface { unsigned int sequence_number; - boolean is_current; + struct fbdev_sw_drawable drawable; }; static INLINE struct fbdev_display * @@ -103,38 +115,70 @@ fbdev_surface_validate(struct native_surface *nsurf, uint attachment_mask, return TRUE; } -static boolean -fbdev_surface_flush_frontbuffer(struct native_surface *nsurf) +static enum pipe_format +vinfo_to_format(const struct fb_var_screeninfo *vinfo) { - struct fbdev_surface *fbsurf = fbdev_surface(nsurf); + enum pipe_format format = PIPE_FORMAT_NONE; - if (!fbsurf->is_current) - return TRUE; + /* should also check channel offsets... */ + switch (vinfo->bits_per_pixel) { + case 32: + if (vinfo->red.length == 8 && + vinfo->green.length == 8 && + vinfo->blue.length == 8) { + format = (vinfo->transp.length == 8) ? + PIPE_FORMAT_B8G8R8A8_UNORM : PIPE_FORMAT_B8G8R8X8_UNORM; + } + break; + case 16: + if (vinfo->red.length == 5 && + vinfo->green.length == 6 && + vinfo->blue.length == 5 && + vinfo->transp.length == 0) + format = PIPE_FORMAT_B5G6R5_UNORM; + break; + default: + break; + } - return resource_surface_present(fbsurf->rsurf, - NATIVE_ATTACHMENT_FRONT_LEFT, NULL); + return format; } static boolean -fbdev_surface_swap_buffers(struct native_surface *nsurf) +fbdev_surface_update_drawable(struct native_surface *nsurf, + const struct fb_var_screeninfo *vinfo) { struct fbdev_surface *fbsurf = fbdev_surface(nsurf); - struct fbdev_display *fbdpy = fbsurf->fbdpy; - boolean ret = TRUE; - - if (fbsurf->is_current) { - ret = resource_surface_present(fbsurf->rsurf, - NATIVE_ATTACHMENT_BACK_LEFT, NULL); + unsigned x, y, width, height; + + x = vinfo->xoffset; + y = vinfo->yoffset; + width = MIN2(vinfo->xres, fbsurf->width); + height = MIN2(vinfo->yres, fbsurf->height); + + /* sanitize the values */ + if (x + width > vinfo->xres_virtual) { + if (x > vinfo->xres_virtual) + width = 0; + else + width = vinfo->xres_virtual - x; + } + if (y + height > vinfo->yres_virtual) { + if (y > vinfo->yres_virtual) + height = 0; + else + height = vinfo->yres_virtual - y; } - resource_surface_swap_buffers(fbsurf->rsurf, - NATIVE_ATTACHMENT_FRONT_LEFT, NATIVE_ATTACHMENT_BACK_LEFT, TRUE); - /* the front/back textures are swapped */ - fbsurf->sequence_number++; - fbdpy->event_handler->invalid_surface(&fbdpy->base, - &fbsurf->base, fbsurf->sequence_number); + fbsurf->drawable.format = vinfo_to_format(vinfo); + fbsurf->drawable.x = vinfo->xoffset; + fbsurf->drawable.y = vinfo->yoffset; + fbsurf->drawable.width = vinfo->xres; + fbsurf->drawable.height = vinfo->yres; - return ret; + return (fbsurf->drawable.format != PIPE_FORMAT_NONE && + fbsurf->drawable.width && + fbsurf->drawable.height); } static boolean @@ -143,21 +187,43 @@ fbdev_surface_present(struct native_surface *nsurf, boolean preserve, uint swap_interval) { - boolean ret; + struct fbdev_surface *fbsurf = fbdev_surface(nsurf); + struct fbdev_display *fbdpy = fbsurf->fbdpy; + boolean ret = FALSE; - if (preserve || swap_interval) + if (swap_interval) + return FALSE; + if (natt != NATIVE_ATTACHMENT_BACK_LEFT) 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; + if (!fbdpy->assume_fixed_vinfo) { + struct fb_var_screeninfo vinfo; + + memset(&vinfo, 0, sizeof(vinfo)); + if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &vinfo)) + return FALSE; + + /* present the surface */ + if (fbdev_surface_update_drawable(&fbsurf->base, &vinfo)) { + ret = resource_surface_present(fbsurf->rsurf, + natt, (void *) &fbsurf->drawable); + } + + fbsurf->width = vinfo.xres; + fbsurf->height = vinfo.yres; + + if (resource_surface_set_size(fbsurf->rsurf, + fbsurf->width, fbsurf->height)) { + /* surface resized */ + fbsurf->sequence_number++; + fbdpy->event_handler->invalid_surface(&fbdpy->base, + &fbsurf->base, fbsurf->sequence_number); + } + } + else { + /* the drawable never changes */ + ret = resource_surface_present(fbsurf->rsurf, + natt, (void *) &fbsurf->drawable); } return ret; @@ -179,26 +245,48 @@ fbdev_surface_destroy(struct native_surface *nsurf) } static struct native_surface * -fbdev_display_create_scanout_surface(struct native_display *ndpy, - const struct native_config *nconf, - uint width, uint height) +fbdev_display_create_window_surface(struct native_display *ndpy, + EGLNativeWindowType win, + const struct native_config *nconf) { struct fbdev_display *fbdpy = fbdev_display(ndpy); struct fbdev_surface *fbsurf; + struct fb_var_screeninfo vinfo; + + /* there is only one native window: NULL */ + if (win) + return NULL; fbsurf = CALLOC_STRUCT(fbdev_surface); if (!fbsurf) return NULL; fbsurf->fbdpy = fbdpy; - fbsurf->width = width; - fbsurf->height = height; + + /* get current vinfo */ + if (fbdpy->assume_fixed_vinfo) { + vinfo = fbdpy->config_vinfo; + } + else { + memset(&vinfo, 0, sizeof(vinfo)); + if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &vinfo)) { + FREE(fbsurf); + return NULL; + } + } + + fbsurf->width = vinfo.xres; + fbsurf->height = vinfo.yres; + + if (!fbdev_surface_update_drawable(&fbsurf->base, &vinfo)) { + FREE(fbsurf); + return NULL; + } fbsurf->rsurf = resource_surface_create(fbdpy->base.screen, nconf->color_format, PIPE_BIND_RENDER_TARGET | - PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_SCANOUT); + PIPE_BIND_DISPLAY_TARGET); if (!fbsurf->rsurf) { FREE(fbsurf); return NULL; @@ -214,42 +302,43 @@ fbdev_display_create_scanout_surface(struct native_display *ndpy, return &fbsurf->base; } +static struct native_surface * +fbdev_display_create_scanout_surface(struct native_display *ndpy, + const struct native_config *nconf, + uint width, uint height) +{ + return fbdev_display_create_window_surface(ndpy, + (EGLNativeWindowType) NULL, nconf); +} + static boolean fbdev_display_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) { - struct fbdev_display *fbdpy = fbdev_display(ndpy); - struct fbdev_surface *fbsurf = fbdev_surface(nsurf); - - if (x || y) - return FALSE; - - if (fbdpy->current_surface) { - if (fbdpy->current_surface == fbsurf) - return TRUE; - fbdpy->current_surface->is_current = FALSE; - } - - if (fbsurf) - fbsurf->is_current = TRUE; - fbdpy->current_surface = fbsurf; - return TRUE; } static const struct native_mode ** fbdev_display_get_modes(struct native_display *ndpy, - const struct native_connector *nconn, - int *num_modes) + const struct native_connector *nconn, + int *num_modes) { - struct fbdev_display *fbdpy = fbdev_display(ndpy); + static struct native_mode mode; const struct native_mode **modes; + if (!mode.desc) { + struct fbdev_display *fbdpy = fbdev_display(ndpy); + mode.desc = "Current Mode"; + mode.width = fbdpy->config_vinfo.xres; + mode.height = fbdpy->config_vinfo.yres; + mode.refresh_rate = 60 * 1000; /* dummy */ + } + modes = MALLOC(sizeof(*modes)); if (modes) { - modes[0] = &fbdpy->mode; + modes[0] = &mode; if (num_modes) *num_modes = 1; } @@ -261,12 +350,12 @@ static const struct native_connector ** fbdev_display_get_connectors(struct native_display *ndpy, int *num_connectors, int *num_crtc) { - struct fbdev_display *fbdpy = fbdev_display(ndpy); + static struct native_connector connector; const struct native_connector **connectors; connectors = MALLOC(sizeof(*connectors)); if (connectors) { - connectors[0] = &fbdpy->connector; + connectors[0] = &connector; if (num_connectors) *num_connectors = 1; } @@ -274,7 +363,8 @@ fbdev_display_get_connectors(struct native_display *ndpy, int *num_connectors, return connectors; } -static struct native_display_modeset fbdev_display_modeset = { +/* remove modeset support one day! */ +static const struct native_display_modeset fbdev_display_modeset = { .get_connectors = fbdev_display_get_connectors, .get_modes = fbdev_display_get_modes, .create_scanout_surface = fbdev_display_create_scanout_surface, @@ -304,8 +394,10 @@ fbdev_display_get_param(struct native_display *ndpy, int val; switch (param) { - case NATIVE_PARAM_USE_NATIVE_BUFFER: case NATIVE_PARAM_PRESERVE_BUFFER: + val = 1; + break; + case NATIVE_PARAM_USE_NATIVE_BUFFER: case NATIVE_PARAM_MAX_SWAP_INTERVAL: default: val = 0; @@ -326,114 +418,55 @@ fbdev_display_destroy(struct native_display *ndpy) } static boolean -fbdev_display_init_modes(struct native_display *ndpy) +fbdev_display_init_screen(struct native_display *ndpy) { struct fbdev_display *fbdpy = fbdev_display(ndpy); - struct native_mode *nmode = &fbdpy->mode; - - nmode->desc = "Current Mode"; - nmode->width = fbdpy->vinfo.xres; - nmode->height = fbdpy->vinfo.yres; - nmode->refresh_rate = 60 * 1000; /* dummy */ - - return TRUE; -} - -static boolean -fbdev_display_init_connectors(struct native_display *ndpy) -{ - return TRUE; -} + struct sw_winsys *ws; -static enum pipe_format -vinfo_to_format(const struct fb_var_screeninfo *vinfo) -{ - enum pipe_format format = PIPE_FORMAT_NONE; + ws = fbdev_create_sw_winsys(fbdpy->fd); + if (!ws) + return FALSE; - switch (vinfo->bits_per_pixel) { - case 32: - if (vinfo->red.length == 8 && - vinfo->green.length == 8 && - vinfo->blue.length == 8) { - format = (vinfo->transp.length == 8) ? - PIPE_FORMAT_B8G8R8A8_UNORM : PIPE_FORMAT_B8G8R8X8_UNORM; - } - break; - case 16: - if (vinfo->red.length == 5 && - vinfo->green.length == 6 && - vinfo->blue.length == 5 && - vinfo->transp.length == 0) - format = PIPE_FORMAT_B5G6R5_UNORM; - break; - default: - break; + fbdpy->base.screen = fbdpy->event_handler->new_sw_screen(&fbdpy->base, ws); + if (!fbdpy->base.screen) { + if (ws->destroy) + ws->destroy(ws); + return FALSE; } - return format; -} - -static boolean -fbdev_display_init_configs(struct native_display *ndpy) -{ - struct fbdev_display *fbdpy = fbdev_display(ndpy); - struct native_config *nconf = &fbdpy->config; - - nconf->color_format = vinfo_to_format(&fbdpy->vinfo); - if (nconf->color_format == PIPE_FORMAT_NONE) + if (!fbdpy->base.screen->is_format_supported(fbdpy->base.screen, + fbdpy->config.color_format, PIPE_TEXTURE_2D, 0, + PIPE_BIND_RENDER_TARGET)) { + fbdpy->base.screen->destroy(fbdpy->base.screen); + fbdpy->base.screen = NULL; return FALSE; - - nconf->buffer_mask = - (1 << NATIVE_ATTACHMENT_FRONT_LEFT) | - (1 << NATIVE_ATTACHMENT_BACK_LEFT); - - nconf->scanout_bit = TRUE; + } return TRUE; } static boolean -fbdev_display_init(struct native_display *ndpy) +fbdev_display_init_config(struct native_display *ndpy) { struct fbdev_display *fbdpy = fbdev_display(ndpy); - struct sw_winsys *ws; - - if (ioctl(fbdpy->fd, FBIOGET_FSCREENINFO, &fbdpy->finfo)) - return FALSE; + struct native_config *nconf = &fbdpy->config; - if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &fbdpy->vinfo)) + if (ioctl(fbdpy->fd, FBIOGET_VSCREENINFO, &fbdpy->config_vinfo)) return FALSE; - if (fbdpy->finfo.visual != FB_VISUAL_TRUECOLOR || - fbdpy->finfo.type != FB_TYPE_PACKED_PIXELS) + nconf->color_format = vinfo_to_format(&fbdpy->config_vinfo); + if (nconf->color_format == PIPE_FORMAT_NONE) return FALSE; - if (!fbdev_display_init_configs(&fbdpy->base) || - !fbdev_display_init_connectors(&fbdpy->base) || - !fbdev_display_init_modes(&fbdpy->base)) - return FALSE; + nconf->buffer_mask = (1 << NATIVE_ATTACHMENT_BACK_LEFT); - ws = fbdev_create_sw_winsys(fbdpy->fd, fbdpy->config.color_format); - if (ws) { - fbdpy->base.screen = - fbdpy->event_handler->new_sw_screen(&fbdpy->base, ws); - } + nconf->window_bit = TRUE; - if (fbdpy->base.screen) { - if (!fbdpy->base.screen->is_format_supported(fbdpy->base.screen, - fbdpy->config.color_format, PIPE_TEXTURE_2D, 0, - PIPE_BIND_RENDER_TARGET)) { - fbdpy->base.screen->destroy(fbdpy->base.screen); - fbdpy->base.screen = NULL; - } - } - - return (fbdpy->base.screen != NULL); + return TRUE; } static struct native_display * -fbdev_display_create(int fd, struct native_event_handler *event_handler, - void *user_data) +fbdev_display_create(int fd, const struct native_event_handler *event_handler) { struct fbdev_display *fbdpy; @@ -443,32 +476,41 @@ fbdev_display_create(int fd, struct native_event_handler *event_handler, fbdpy->fd = fd; fbdpy->event_handler = event_handler; - fbdpy->base.user_data = user_data; - if (!fbdev_display_init(&fbdpy->base)) { - FREE(fbdpy); - return NULL; - } + if (ioctl(fbdpy->fd, FBIOGET_FSCREENINFO, &fbdpy->finfo)) + goto fail; + + if (fbdpy->finfo.visual != FB_VISUAL_TRUECOLOR || + fbdpy->finfo.type != FB_TYPE_PACKED_PIXELS) + goto fail; + + if (!fbdev_display_init_config(&fbdpy->base)) + goto fail; + fbdpy->assume_fixed_vinfo = TRUE; + + fbdpy->base.init_screen = fbdev_display_init_screen; fbdpy->base.destroy = fbdev_display_destroy; fbdpy->base.get_param = fbdev_display_get_param; fbdpy->base.get_configs = fbdev_display_get_configs; + fbdpy->base.create_window_surface = fbdev_display_create_window_surface; + + /* we'd like to remove modeset support one day */ + fbdpy->config.scanout_bit = TRUE; fbdpy->base.modeset = &fbdev_display_modeset; return &fbdpy->base; -} -static struct native_event_handler *fbdev_event_handler; - -static void -native_set_event_handler(struct native_event_handler *event_handler) -{ - fbdev_event_handler = event_handler; +fail: + FREE(fbdpy); + return NULL; } +static const struct native_event_handler *fbdev_event_handler; + static struct native_display * -native_create_display(void *dpy, boolean use_sw, void *user_data) +native_create_display(void *dpy, boolean use_sw) { struct native_display *ndpy; int fd; @@ -483,7 +525,7 @@ native_create_display(void *dpy, boolean use_sw, void *user_data) if (fd < 0) return NULL; - ndpy = fbdev_display_create(fd, fbdev_event_handler, user_data); + ndpy = fbdev_display_create(fd, fbdev_event_handler); if (!ndpy) close(fd); @@ -492,12 +534,12 @@ native_create_display(void *dpy, boolean use_sw, void *user_data) static const struct native_platform fbdev_platform = { "FBDEV", /* name */ - native_set_event_handler, native_create_display }; const struct native_platform * -native_get_fbdev_platform(void) +native_get_fbdev_platform(const struct native_event_handler *event_handler) { + fbdev_event_handler = event_handler; return &fbdev_platform; } diff --git a/src/gallium/state_trackers/egl/gdi/native_gdi.c b/src/gallium/state_trackers/egl/gdi/native_gdi.c index 5d0045f92ee..6bf0d4e4668 100644 --- a/src/gallium/state_trackers/egl/gdi/native_gdi.c +++ b/src/gallium/state_trackers/egl/gdi/native_gdi.c @@ -41,7 +41,7 @@ struct gdi_display { struct native_display base; HDC hDC; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; struct native_config *configs; int num_configs; @@ -368,35 +368,39 @@ gdi_display_destroy(struct native_display *ndpy) FREE(gdpy); } -static struct native_display * -gdi_create_display(HDC hDC, struct native_event_handler *event_handler, - void *user_data) +static boolean +gdi_display_init_screen(struct native_display *ndpy) { - struct gdi_display *gdpy; + struct gdi_display *gdpy = gdi_display(ndpy); struct sw_winsys *winsys; - gdpy = CALLOC_STRUCT(gdi_display); - if (!gdpy) - return NULL; - - gdpy->hDC = hDC; - gdpy->event_handler = event_handler; - gdpy->base.user_data = user_data; - winsys = gdi_create_sw_winsys(); - if (!winsys) { - FREE(gdpy); - return NULL; - } + if (!winsys) + return FALSE; gdpy->base.screen = gdpy->event_handler->new_sw_screen(&gdpy->base, winsys); if (!gdpy->base.screen) { if (winsys->destroy) winsys->destroy(winsys); - FREE(gdpy); - return NULL; + return FALSE; } + return TRUE; +} + +static struct native_display * +gdi_create_display(HDC hDC, const struct native_event_handler *event_handler) +{ + struct gdi_display *gdpy; + + gdpy = CALLOC_STRUCT(gdi_display); + if (!gdpy) + return NULL; + + gdpy->hDC = hDC; + gdpy->event_handler = event_handler; + + gdpy->base.init_screen = gdi_display_init_screen; gdpy->base.destroy = gdi_display_destroy; gdpy->base.get_param = gdi_display_get_param; @@ -406,28 +410,22 @@ gdi_create_display(HDC hDC, struct native_event_handler *event_handler, return &gdpy->base; } -static struct native_event_handler *gdi_event_handler; - -static void -native_set_event_handler(struct native_event_handler *event_handler) -{ - gdi_event_handler = event_handler; -} +static const struct native_event_handler *gdi_event_handler; static struct native_display * -native_create_display(void *dpy, boolean use_sw, void *user_data) +native_create_display(void *dpy, boolean use_sw) { - return gdi_create_display((HDC) dpy, gdi_event_handler, user_data); + return gdi_create_display((HDC) dpy, gdi_event_handler); } static const struct native_platform gdi_platform = { "GDI", /* name */ - native_set_event_handler, native_create_display }; const struct native_platform * -native_get_gdi_platform(void) +native_get_gdi_platform(const struct native_event_handler *event_handler) { + gdi_event_handler = event_handler; return &gdi_platform; } diff --git a/src/gallium/state_trackers/egl/wayland/native_drm.c b/src/gallium/state_trackers/egl/wayland/native_drm.c index 15383e89301..e34b24b58b1 100644 --- a/src/gallium/state_trackers/egl/wayland/native_drm.c +++ b/src/gallium/state_trackers/egl/wayland/native_drm.c @@ -51,7 +51,7 @@ struct wayland_drm_display { struct wayland_display base; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; struct wl_drm *wl_drm; struct wl_drm *wl_server_drm; /* for EGL_WL_bind_wayland_display */ @@ -98,6 +98,8 @@ wayland_drm_display_destroy(struct native_display *ndpy) FREE(drmdpy->device_name); if (drmdpy->base.config) FREE(drmdpy->base.config); + if (drmdpy->base.own_dpy) + wl_display_destroy(drmdpy->base.dpy); ndpy_uninit(ndpy); @@ -210,27 +212,10 @@ wayland_drm_display_init_screen(struct native_display *ndpy) return TRUE; } -static struct pipe_resource * -wayland_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 -wayland_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 wayland_drm_display_buffer = { - wayland_drm_display_import_buffer, - wayland_drm_display_export_buffer + /* use the helpers */ + drm_display_import_native_buffer, + drm_display_export_native_buffer }; static int @@ -300,8 +285,7 @@ static struct native_display_wayland_bufmgr wayland_drm_display_wayland_bufmgr = struct wayland_display * wayland_create_drm_display(struct wl_display *dpy, - struct native_event_handler *event_handler, - void *user_data) + const struct native_event_handler *event_handler) { struct wayland_drm_display *drmdpy; @@ -310,7 +294,6 @@ wayland_create_drm_display(struct wl_display *dpy, return NULL; drmdpy->event_handler = event_handler; - drmdpy->base.base.user_data = user_data; drmdpy->base.dpy = dpy; if (!drmdpy->base.dpy) { @@ -318,10 +301,7 @@ wayland_create_drm_display(struct wl_display *dpy, return NULL; } - if (!wayland_drm_display_init_screen(&drmdpy->base.base)) { - wayland_drm_display_destroy(&drmdpy->base.base); - return NULL; - } + drmdpy->base.base.init_screen = wayland_drm_display_init_screen; drmdpy->base.base.destroy = wayland_drm_display_destroy; drmdpy->base.base.buffer = &wayland_drm_display_buffer; drmdpy->base.base.wayland_bufmgr = &wayland_drm_display_wayland_bufmgr; diff --git a/src/gallium/state_trackers/egl/wayland/native_shm.c b/src/gallium/state_trackers/egl/wayland/native_shm.c index 609fc0cd04a..1c0799528fe 100644 --- a/src/gallium/state_trackers/egl/wayland/native_shm.c +++ b/src/gallium/state_trackers/egl/wayland/native_shm.c @@ -47,7 +47,7 @@ struct wayland_shm_display { struct wayland_display base; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; struct wl_shm *wl_shm; }; @@ -65,6 +65,8 @@ wayland_shm_display_destroy(struct native_display *ndpy) if (shmdpy->base.config) FREE(shmdpy->base.config); + if (shmdpy->base.own_dpy) + wl_display_destroy(shmdpy->base.dpy); ndpy_uninit(ndpy); @@ -142,8 +144,7 @@ wayland_shm_display_init_screen(struct native_display *ndpy) struct wayland_display * wayland_create_shm_display(struct wl_display *dpy, - struct native_event_handler *event_handler, - void *user_data) + const struct native_event_handler *event_handler) { struct wayland_shm_display *shmdpy; @@ -152,7 +153,6 @@ wayland_create_shm_display(struct wl_display *dpy, return NULL; shmdpy->event_handler = event_handler; - shmdpy->base.base.user_data = user_data; shmdpy->base.dpy = dpy; if (!shmdpy->base.dpy) { @@ -160,11 +160,7 @@ wayland_create_shm_display(struct wl_display *dpy, return NULL; } - if (!wayland_shm_display_init_screen(&shmdpy->base.base)) { - wayland_shm_display_destroy(&shmdpy->base.base); - return NULL; - } - + shmdpy->base.base.init_screen = wayland_shm_display_init_screen; shmdpy->base.base.destroy = wayland_shm_display_destroy; shmdpy->base.create_buffer = wayland_create_shm_buffer; diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.c b/src/gallium/state_trackers/egl/wayland/native_wayland.c index 0292d5631d6..544d4be215a 100644 --- a/src/gallium/state_trackers/egl/wayland/native_wayland.c +++ b/src/gallium/state_trackers/egl/wayland/native_wayland.c @@ -35,7 +35,7 @@ #include "native_wayland.h" -static struct native_event_handler *wayland_event_handler; +static const struct native_event_handler *wayland_event_handler; static void sync_callback(void *data) @@ -114,11 +114,12 @@ wayland_display_get_param(struct native_display *ndpy, } static boolean -wayland_display_is_pixmap_supported(struct native_display *ndpy, - EGLNativePixmapType pix, - const struct native_config *nconf) +wayland_display_get_pixmap_format(struct native_display *ndpy, + EGLNativePixmapType pix, + enum pipe_format *format) { /* all wl_egl_pixmaps are supported */ + *format = PIPE_FORMAT_NONE; return TRUE; } @@ -195,13 +196,11 @@ wayland_window_surface_handle_resize(struct wayland_surface *surface) wl_buffer_destroy(surface->buffer[i]); surface->buffer[i] = NULL; } + + surface->dx = surface->win->dx; + surface->dy = surface->win->dy; } pipe_resource_reference(&front_resource, NULL); - - surface->dx = surface->win->dx; - surface->dy = surface->win->dy; - surface->win->dx = 0; - surface->win->dy = 0; } static boolean @@ -449,28 +448,28 @@ wayland_create_window_surface(struct native_display *ndpy, return &surface->base; } -static void -native_set_event_handler(struct native_event_handler *event_handler) -{ - wayland_event_handler = event_handler; -} - static struct native_display * -native_create_display(void *dpy, boolean use_sw, void *user_data) +native_create_display(void *dpy, boolean use_sw) { struct wayland_display *display = NULL; + boolean own_dpy = FALSE; use_sw = use_sw || debug_get_bool_option("EGL_SOFTWARE", FALSE); + if (dpy == NULL) { + dpy = wl_display_connect(NULL); + if (dpy == NULL) + return NULL; + own_dpy = TRUE; + } + if (use_sw) { _eglLog(_EGL_INFO, "use software fallback"); display = wayland_create_shm_display((struct wl_display *) dpy, - wayland_event_handler, - user_data); + wayland_event_handler); } else { display = wayland_create_drm_display((struct wl_display *) dpy, - wayland_event_handler, - user_data); + wayland_event_handler); } if (!display) @@ -478,22 +477,25 @@ native_create_display(void *dpy, boolean use_sw, void *user_data) display->base.get_param = wayland_display_get_param; display->base.get_configs = wayland_display_get_configs; - display->base.is_pixmap_supported = wayland_display_is_pixmap_supported; + display->base.get_pixmap_format = wayland_display_get_pixmap_format; + display->base.copy_to_pixmap = native_display_copy_to_pixmap; display->base.create_window_surface = wayland_create_window_surface; display->base.create_pixmap_surface = wayland_create_pixmap_surface; + display->own_dpy = own_dpy; + return &display->base; } static const struct native_platform wayland_platform = { "wayland", /* name */ - native_set_event_handler, native_create_display }; const struct native_platform * -native_get_wayland_platform(void) +native_get_wayland_platform(const struct native_event_handler *event_handler) { + wayland_event_handler = event_handler; return &wayland_platform; } diff --git a/src/gallium/state_trackers/egl/wayland/native_wayland.h b/src/gallium/state_trackers/egl/wayland/native_wayland.h index e69a8f00f82..5390f2f08c9 100644 --- a/src/gallium/state_trackers/egl/wayland/native_wayland.h +++ b/src/gallium/state_trackers/egl/wayland/native_wayland.h @@ -41,6 +41,7 @@ struct wayland_display { struct wayland_config *config; struct wl_display *dpy; + boolean own_dpy; struct wl_buffer *(*create_buffer)(struct wayland_display *display, struct wayland_surface *surface, @@ -102,11 +103,10 @@ wayland_config(const struct native_config *nconf) struct wayland_display * wayland_create_shm_display(struct wl_display *display, - struct native_event_handler *event_handler, - void *user_data); + const struct native_event_handler *event_handler); + struct wayland_display * wayland_create_drm_display(struct wl_display *display, - struct native_event_handler *event_handler, - void *user_data); + const struct native_event_handler *event_handler); #endif /* _NATIVE_WAYLAND_H_ */ diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c index a56d43428fc..4b8be7bc759 100644 --- a/src/gallium/state_trackers/egl/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -38,6 +38,7 @@ #include "native_x11.h" #include "x11_screen.h" +#include "common/native_helper.h" #ifdef HAVE_WAYLAND_BACKEND #include "common/native_wayland_drm_bufmgr_helper.h" #endif @@ -49,7 +50,7 @@ struct dri2_display { Display *dpy; boolean own_dpy; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; struct x11_screen *xscr; int xscr_number; @@ -682,18 +683,30 @@ dri2_display_get_configs(struct native_display *ndpy, int *num_configs) } static boolean -dri2_display_is_pixmap_supported(struct native_display *ndpy, - EGLNativePixmapType pix, - const struct native_config *nconf) +dri2_display_get_pixmap_format(struct native_display *ndpy, + EGLNativePixmapType pix, + enum pipe_format *format) { struct dri2_display *dri2dpy = dri2_display(ndpy); - uint depth, nconf_depth; + boolean ret = EGL_TRUE; + uint depth; depth = x11_drawable_get_depth(dri2dpy->xscr, (Drawable) pix); - nconf_depth = util_format_get_blocksizebits(nconf->color_format); + switch (depth) { + case 32: + case 24: + *format = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + case 16: + *format = PIPE_FORMAT_B5G6R5_UNORM; + break; + default: + *format = PIPE_FORMAT_NONE; + ret = EGL_FALSE; + break; + } - /* simple depth match for now */ - return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth)); + return ret; } static int @@ -870,8 +883,7 @@ static struct native_display_wayland_bufmgr dri2_display_wayland_bufmgr = { struct native_display * x11_create_dri2_display(Display *dpy, - struct native_event_handler *event_handler, - void *user_data) + const struct native_event_handler *event_handler) { struct dri2_display *dri2dpy; @@ -880,7 +892,6 @@ x11_create_dri2_display(Display *dpy, return NULL; dri2dpy->event_handler = event_handler; - dri2dpy->base.user_data = user_data; dri2dpy->dpy = dpy; if (!dri2dpy->dpy) { @@ -899,11 +910,6 @@ x11_create_dri2_display(Display *dpy, return NULL; } - if (!dri2_display_init_screen(&dri2dpy->base)) { - dri2_display_destroy(&dri2dpy->base); - return NULL; - } - dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash, dri2_display_hash_table_compare); if (!dri2dpy->surfaces) { @@ -911,10 +917,12 @@ x11_create_dri2_display(Display *dpy, return NULL; } + dri2dpy->base.init_screen = dri2_display_init_screen; 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.get_pixmap_format = dri2_display_get_pixmap_format; + dri2dpy->base.copy_to_pixmap = native_display_copy_to_pixmap; dri2dpy->base.create_window_surface = dri2_display_create_window_surface; dri2dpy->base.create_pixmap_surface = dri2_display_create_pixmap_surface; #ifdef HAVE_WAYLAND_BACKEND @@ -928,8 +936,7 @@ x11_create_dri2_display(Display *dpy, struct native_display * x11_create_dri2_display(Display *dpy, - struct native_event_handler *event_handler, - void *user_data) + const struct native_event_handler *event_handler) { return NULL; } diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c index a0bcad4c734..ef038b52152 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.c +++ b/src/gallium/state_trackers/egl/x11/native_x11.c @@ -30,16 +30,10 @@ #include "native_x11.h" -static struct native_event_handler *x11_event_handler; - -static void -native_set_event_handler(struct native_event_handler *event_handler) -{ - x11_event_handler = event_handler; -} +static const struct native_event_handler *x11_event_handler; static struct native_display * -native_create_display(void *dpy, boolean use_sw, void *user_data) +native_create_display(void *dpy, boolean use_sw) { struct native_display *ndpy = NULL; boolean force_sw; @@ -48,12 +42,10 @@ native_create_display(void *dpy, boolean use_sw, void *user_data) if (force_sw || use_sw) { _eglLog(_EGL_INFO, "use software fallback"); - ndpy = x11_create_ximage_display((Display *) dpy, - x11_event_handler, user_data); + ndpy = x11_create_ximage_display((Display *) dpy, x11_event_handler); } else { - ndpy = x11_create_dri2_display((Display *) dpy, - x11_event_handler, user_data); + ndpy = x11_create_dri2_display((Display *) dpy, x11_event_handler); } return ndpy; @@ -61,12 +53,12 @@ native_create_display(void *dpy, boolean use_sw, void *user_data) static const struct native_platform x11_platform = { "X11", /* name */ - native_set_event_handler, native_create_display }; const struct native_platform * -native_get_x11_platform(void) +native_get_x11_platform(const struct native_event_handler *event_handler) { + x11_event_handler = event_handler; return &x11_platform; } diff --git a/src/gallium/state_trackers/egl/x11/native_x11.h b/src/gallium/state_trackers/egl/x11/native_x11.h index 8945117276e..d3c9270a667 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.h +++ b/src/gallium/state_trackers/egl/x11/native_x11.h @@ -31,12 +31,10 @@ struct native_display * x11_create_ximage_display(Display *dpy, - struct native_event_handler *event_handler, - void *user_data); + const struct native_event_handler *event_handler); struct native_display * x11_create_dri2_display(Display *dpy, - struct native_event_handler *event_handler, - void *user_data); + const struct native_event_handler *event_handler); #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 8e32c6ff0c4..e7794f0d3d7 100644 --- a/src/gallium/state_trackers/egl/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl/x11/native_ximage.c @@ -43,7 +43,7 @@ struct ximage_display { Display *dpy; boolean own_dpy; - struct native_event_handler *event_handler; + const struct native_event_handler *event_handler; struct x11_screen *xscr; int xscr_number; @@ -437,14 +437,54 @@ ximage_display_get_configs(struct native_display *ndpy, int *num_configs) } static boolean -ximage_display_is_pixmap_supported(struct native_display *ndpy, - EGLNativePixmapType pix, - const struct native_config *nconf) +ximage_display_get_pixmap_format(struct native_display *ndpy, + EGLNativePixmapType pix, + enum pipe_format *format) { struct ximage_display *xdpy = ximage_display(ndpy); - enum pipe_format fmt = get_pixmap_format(&xdpy->base, pix); - return (fmt == nconf->color_format); + *format = get_pixmap_format(&xdpy->base, pix); + + return (*format != PIPE_FORMAT_NONE); +} + +static boolean +ximage_display_copy_to_pixmap(struct native_display *ndpy, + EGLNativePixmapType pix, + struct pipe_resource *src) +{ + /* fast path to avoid unnecessary allocation and resource_copy_region */ + if (src->bind & PIPE_BIND_DISPLAY_TARGET) { + struct ximage_display *xdpy = ximage_display(ndpy); + enum pipe_format fmt = get_pixmap_format(&xdpy->base, pix); + const struct ximage_config *xconf; + struct xlib_drawable xdraw; + int i; + + if (fmt == PIPE_FORMAT_NONE || src->format != fmt) + return FALSE; + + for (i = 0; i < xdpy->num_configs; i++) { + if (xdpy->configs[i].base.color_format == fmt) { + xconf = &xdpy->configs[i]; + break; + } + } + if (!xconf) + return FALSE; + + memset(&xdraw, 0, sizeof(xdraw)); + xdraw.visual = xconf->visual->visual; + xdraw.depth = xconf->visual->depth; + xdraw.drawable = (Drawable) pix; + + xdpy->base.screen->flush_frontbuffer(xdpy->base.screen, + src, 0, 0, &xdraw); + + return TRUE; + } + + return native_display_copy_to_pixmap(ndpy, pix, src); } static int @@ -484,13 +524,32 @@ ximage_display_destroy(struct native_display *ndpy) FREE(xdpy); } +static boolean +ximage_display_init_screen(struct native_display *ndpy) +{ + struct ximage_display *xdpy = ximage_display(ndpy); + struct sw_winsys *winsys; + + winsys = xlib_create_sw_winsys(xdpy->dpy); + if (!winsys) + return FALSE; + + xdpy->base.screen = + xdpy->event_handler->new_sw_screen(&xdpy->base, winsys); + if (!xdpy->base.screen) { + if (winsys->destroy) + winsys->destroy(winsys); + return FALSE; + } + + return TRUE; +} + struct native_display * x11_create_ximage_display(Display *dpy, - struct native_event_handler *event_handler, - void *user_data) + const struct native_event_handler *event_handler) { struct ximage_display *xdpy; - struct sw_winsys *winsys = NULL; xdpy = CALLOC_STRUCT(ximage_display); if (!xdpy) @@ -507,39 +566,25 @@ x11_create_ximage_display(Display *dpy, } xdpy->event_handler = event_handler; - xdpy->base.user_data = user_data; xdpy->xscr_number = DefaultScreen(xdpy->dpy); xdpy->xscr = x11_screen_create(xdpy->dpy, xdpy->xscr_number); - if (!xdpy->xscr) - goto fail; - - winsys = xlib_create_sw_winsys(xdpy->dpy); - if (!winsys) - goto fail; - - xdpy->base.screen = - xdpy->event_handler->new_sw_screen(&xdpy->base, winsys); - if (!xdpy->base.screen) - goto fail; + if (!xdpy->xscr) { + if (xdpy->own_dpy) + XCloseDisplay(xdpy->dpy); + FREE(xdpy); + return NULL; + } + xdpy->base.init_screen = ximage_display_init_screen; 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.get_pixmap_format = ximage_display_get_pixmap_format; + xdpy->base.copy_to_pixmap = ximage_display_copy_to_pixmap; xdpy->base.create_window_surface = ximage_display_create_window_surface; xdpy->base.create_pixmap_surface = ximage_display_create_pixmap_surface; return &xdpy->base; - -fail: - if (winsys && winsys->destroy) - winsys->destroy(winsys); - if (xdpy->xscr) - x11_screen_destroy(xdpy->xscr); - if (xdpy->dpy && xdpy->own_dpy) - XCloseDisplay(xdpy->dpy); - FREE(xdpy); - return NULL; } |