diff options
Diffstat (limited to 'src/gallium/state_trackers')
40 files changed, 1491 insertions, 673 deletions
diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c index 5033c3c85b..908cef454e 100644 --- a/src/gallium/state_trackers/dri/dri_context.c +++ b/src/gallium/state_trackers/dri/dri_context.c @@ -166,10 +166,8 @@ dri_make_current(__DRIcontext * cPriv, if (__dri1_api_hooks) { dri1_update_drawables(ctx, draw, read); } else { - if (driDrawPriv) - dri_get_buffers(driDrawPriv); - if (driDrawPriv != driReadPriv && driReadPriv) - dri_get_buffers(driReadPriv); + dri_update_buffer(ctx->pipe->screen, + ctx->pipe->priv); } } else { st_make_current(NULL, NULL, NULL); diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c index 97277c0507..458473853c 100644 --- a/src/gallium/state_trackers/dri/dri_drawable.c +++ b/src/gallium/state_trackers/dri/dri_drawable.c @@ -58,6 +58,7 @@ dri_surface_from_handle(struct drm_api *api, struct pipe_surface *surface = NULL; struct pipe_texture *texture = NULL; struct pipe_texture templat; + struct winsys_handle whandle; memset(&templat, 0, sizeof(templat)); templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; @@ -68,8 +69,11 @@ dri_surface_from_handle(struct drm_api *api, templat.width0 = width; templat.height0 = height; - texture = api->texture_from_shared_handle(api, screen, &templat, - "dri2 buffer", pitch, handle); + memset(&whandle, 0, sizeof(whandle)); + whandle.handle = handle; + whandle.stride = pitch; + + texture = screen->texture_from_handle(screen, &templat, &whandle); if (!texture) { debug_printf("%s: Failed to blanket the buffer with a texture\n", __func__); @@ -134,12 +138,13 @@ dri_get_buffers(__DRIdrawable * dPriv) if ((dri_screen->dri2.loader && (dri_screen->dri2.loader->base.version > 2) - && (dri_screen->dri2.loader->getBuffersWithFormat != NULL))) + && (dri_screen->dri2.loader->getBuffersWithFormat != NULL))) { buffers = (*dri_screen->dri2.loader->getBuffersWithFormat) (dri_drawable, &dri_drawable->w, &dri_drawable->h, drawable->attachments, drawable->num_attachments, &count, dri_drawable->loaderPrivate); - else + } else { + assert(dri_screen->dri2.loader); buffers = (*dri_screen->dri2.loader->getBuffers) (dri_drawable, &dri_drawable->w, &dri_drawable->h, @@ -148,6 +153,7 @@ dri_get_buffers(__DRIdrawable * dPriv) num_attachments, &count, dri_drawable-> loaderPrivate); + } if (buffers == NULL) { return; @@ -284,7 +290,18 @@ dri_update_buffer(struct pipe_screen *screen, void *context_private) { struct dri_context *ctx = (struct dri_context *)context_private; + if (ctx->d_stamp == *ctx->dPriv->pStamp && + ctx->r_stamp == *ctx->rPriv->pStamp) + return; + + ctx->d_stamp = *ctx->dPriv->pStamp; + ctx->r_stamp = *ctx->rPriv->pStamp; + + /* Ask the X server for new renderbuffers. */ dri_get_buffers(ctx->dPriv); + if (ctx->dPriv != ctx->rPriv) + dri_get_buffers(ctx->rPriv); + } void @@ -336,11 +353,11 @@ dri_create_buffer(__DRIscreen * sPriv, if (visual->redBits == 8) { if (visual->alphaBits == 8) - drawable->color_format = PIPE_FORMAT_A8R8G8B8_UNORM; + drawable->color_format = PIPE_FORMAT_B8G8R8A8_UNORM; else - drawable->color_format = PIPE_FORMAT_X8R8G8B8_UNORM; + drawable->color_format = PIPE_FORMAT_B8G8R8X8_UNORM; } else { - drawable->color_format = PIPE_FORMAT_R5G6B5_UNORM; + drawable->color_format = PIPE_FORMAT_B5G6R5_UNORM; } switch(visual->depthBits) { @@ -354,12 +371,12 @@ dri_create_buffer(__DRIscreen * sPriv, case 24: if (visual->stencilBits == 0) { drawable->depth_stencil_format = (screen->d_depth_bits_last) ? - PIPE_FORMAT_X8Z24_UNORM: - PIPE_FORMAT_Z24X8_UNORM; + PIPE_FORMAT_Z24X8_UNORM: + PIPE_FORMAT_X8Z24_UNORM; } else { drawable->depth_stencil_format = (screen->sd_depth_bits_last) ? - PIPE_FORMAT_S8Z24_UNORM: - PIPE_FORMAT_Z24S8_UNORM; + PIPE_FORMAT_Z24S8_UNORM: + PIPE_FORMAT_S8Z24_UNORM; } break; case 32: diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c index b36ea43db5..60bc560049 100644 --- a/src/gallium/state_trackers/dri/dri_screen.c +++ b/src/gallium/state_trackers/dri/dri_screen.c @@ -61,6 +61,17 @@ static const __DRItexBufferExtension dri2TexBufferExtension = { dri2_set_tex_buffer2, }; +static void +dri2_flush_drawable(__DRIdrawable *draw) +{ +} + +static const __DRI2flushExtension dri2FlushExtension = { + { __DRI2_FLUSH, __DRI2_FLUSH_VERSION }, + dri2_flush_drawable, + dri2InvalidateDrawable, +}; + static const __DRIextension *dri_screen_extensions[] = { &driReadDrawableExtension, &driCopySubBufferExtension.base, @@ -68,6 +79,7 @@ static const __DRItexBufferExtension dri2TexBufferExtension = { &driFrameTrackingExtension.base, &driMediaStreamCounterExtension.base, &dri2TexBufferExtension.base, + &dri2FlushExtension.base, NULL }; @@ -97,22 +109,22 @@ dri_fill_in_modes(struct dri_screen *screen, stencil_bits_array[0] = 0; depth_buffer_factor = 1; - pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM, + pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); - pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM, + pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); - pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8Z24_UNORM, + pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24S8_UNORM, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); - pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24S8_UNORM, + pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8Z24_UNORM, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); - pf_a8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_A8R8G8B8_UNORM, + pf_a8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8A8_UNORM, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0); - pf_x8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8R8G8B8_UNORM, + pf_x8r8g8b8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B8G8R8X8_UNORM, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0); @@ -127,7 +139,7 @@ dri_fill_in_modes(struct dri_screen *screen, pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); - pf_r5g6b5 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_R5G6B5_UNORM, + pf_r5g6b5 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_B5G6R5_UNORM, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_RENDER_TARGET, 0); } else { diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.c b/src/gallium/state_trackers/egl/common/egl_g3d.c index 80dd126995..50774b03f3 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d.c @@ -36,6 +36,7 @@ #include "native.h" #include "egl_g3d.h" +#include "egl_g3d_image.h" #include "egl_st.h" /** @@ -528,15 +529,27 @@ static void egl_g3d_update_buffer(struct pipe_screen *screen, void *context_private) { struct egl_g3d_context *gctx = egl_g3d_context(context_private); - - /** - * It is likely that the surface has changed when this function is called. - * Set force_validate to skip an unnecessary check. - */ - gctx->force_validate = EGL_TRUE; egl_g3d_validate_context(gctx->base.Resource.Display, &gctx->base); } +static void +egl_g3d_invalid_surface(struct native_display *ndpy, + struct native_surface *nsurf, + unsigned int seq_num) +{ + /* XXX not thread safe? */ + struct egl_g3d_surface *gsurf = egl_g3d_surface(nsurf->user_data); + struct egl_g3d_context *gctx = egl_g3d_context(gsurf->base.CurrentContext); + + /* set force_validate to skip an unnecessary check */ + if (gctx) + gctx->force_validate = TRUE; +} + +static struct native_event_handler egl_g3d_native_event_handler = { + .invalid_surface = egl_g3d_invalid_surface +}; + static EGLBoolean egl_g3d_terminate(_EGLDriver *drv, _EGLDisplay *dpy) { @@ -581,31 +594,37 @@ egl_g3d_initialize(_EGLDriver *drv, _EGLDisplay *dpy, } dpy->DriverData = gdpy; - gdpy->native = native_create_display(dpy->NativeDisplay); + gdpy->native = native_create_display(dpy->NativeDisplay, + &egl_g3d_native_event_handler); if (!gdpy->native) { _eglError(EGL_NOT_INITIALIZED, "eglInitialize(no usable display)"); goto fail; } + gdpy->native->user_data = (void *) dpy; gdpy->native->screen->flush_frontbuffer = egl_g3d_flush_frontbuffer; gdpy->native->screen->update_buffer = egl_g3d_update_buffer; egl_g3d_init_st(&gdrv->base); dpy->ClientAPIsMask = gdrv->api_mask; - if (egl_g3d_add_configs(drv, dpy, 1) == 1) { - _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); - goto fail; - } - #ifdef EGL_MESA_screen_surface - /* enable MESA_screen_surface */ + /* enable MESA_screen_surface before adding (and validating) configs */ if (gdpy->native->modeset) { dpy->Extensions.MESA_screen_surface = EGL_TRUE; egl_g3d_add_screens(drv, dpy); } #endif + dpy->Extensions.KHR_image_base = EGL_TRUE; + if (gdpy->native->get_param(gdpy->native, NATIVE_PARAM_USE_NATIVE_BUFFER)) + dpy->Extensions.KHR_image_pixmap = EGL_TRUE; + + if (egl_g3d_add_configs(drv, dpy, 1) == 1) { + _eglError(EGL_NOT_INITIALIZED, "eglInitialize(unable to add configs)"); + goto fail; + } + *major = 1; *minor = 4; @@ -693,131 +712,144 @@ egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) return EGL_TRUE; } -static EGLBoolean -init_surface_geometry(_EGLSurface *surf) -{ - struct egl_g3d_surface *gsurf = egl_g3d_surface(surf); - - return gsurf->native->validate(gsurf->native, 0x0, - &gsurf->sequence_number, NULL, - &gsurf->base.Width, &gsurf->base.Height); -} +struct egl_g3d_create_surface_arg { + EGLint type; + union { + EGLNativeWindowType win; + EGLNativePixmapType pix; + } u; +}; static _EGLSurface * -egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLConfig *conf, EGLNativeWindowType win, - const EGLint *attribs) +egl_g3d_create_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, + struct egl_g3d_create_surface_arg *arg, + const EGLint *attribs) { struct egl_g3d_display *gdpy = egl_g3d_display(dpy); struct egl_g3d_config *gconf = egl_g3d_config(conf); struct egl_g3d_surface *gsurf; + struct native_surface *nsurf; + const char *err; + + switch (arg->type) { + case EGL_WINDOW_BIT: + err = "eglCreateWindowSurface"; + break; + case EGL_PIXMAP_BIT: + err = "eglCreatePixmapSurface"; + break; + case EGL_PBUFFER_BIT: + err = "eglCreatePBufferSurface"; + break; +#ifdef EGL_MESA_screen_surface + case EGL_SCREEN_BIT_MESA: + err = "eglCreateScreenSurface"; + break; +#endif + default: + err = "eglCreateUnknownSurface"; + break; + } gsurf = CALLOC_STRUCT(egl_g3d_surface); if (!gsurf) { - _eglError(EGL_BAD_ALLOC, "eglCreateWindowSurface"); + _eglError(EGL_BAD_ALLOC, err); return NULL; } - if (!_eglInitSurface(&gsurf->base, dpy, EGL_WINDOW_BIT, conf, attribs)) { + if (!_eglInitSurface(&gsurf->base, dpy, arg->type, conf, attribs)) { free(gsurf); return NULL; } - gsurf->native = - gdpy->native->create_window_surface(gdpy->native, win, gconf->native); - if (!gsurf->native) { + /* create the native surface */ + switch (arg->type) { + case EGL_WINDOW_BIT: + nsurf = gdpy->native->create_window_surface(gdpy->native, + arg->u.win, gconf->native); + break; + case EGL_PIXMAP_BIT: + nsurf = gdpy->native->create_pixmap_surface(gdpy->native, + arg->u.pix, gconf->native); + break; + case EGL_PBUFFER_BIT: + nsurf = gdpy->native->create_pbuffer_surface(gdpy->native, + gconf->native, gsurf->base.Width, gsurf->base.Height); + break; +#ifdef EGL_MESA_screen_surface + case EGL_SCREEN_BIT_MESA: + /* prefer back buffer (move to _eglInitSurface?) */ + gsurf->base.RenderBuffer = EGL_BACK_BUFFER; + nsurf = gdpy->native->modeset->create_scanout_surface(gdpy->native, + gconf->native, gsurf->base.Width, gsurf->base.Height); + break; +#endif + default: + nsurf = NULL; + break; + } + + if (!nsurf) { free(gsurf); return NULL; } - - if (!init_surface_geometry(&gsurf->base)) { - gsurf->native->destroy(gsurf->native); + /* initialize the geometry */ + if (!nsurf->validate(nsurf, 0x0, &gsurf->sequence_number, NULL, + &gsurf->base.Width, &gsurf->base.Height)) { + nsurf->destroy(nsurf); free(gsurf); return NULL; } - gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER || - !gconf->native->mode.doubleBufferMode) ? + nsurf->user_data = &gsurf->base; + gsurf->native = nsurf; + + gsurf->render_att = (gsurf->base.RenderBuffer == EGL_SINGLE_BUFFER) ? NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; + if (!gconf->native->mode.doubleBufferMode) + gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT; return &gsurf->base; } static _EGLSurface * -egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, - _EGLConfig *conf, EGLNativePixmapType pix, +egl_g3d_create_window_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, EGLNativeWindowType win, const EGLint *attribs) { - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_config *gconf = egl_g3d_config(conf); - struct egl_g3d_surface *gsurf; + struct egl_g3d_create_surface_arg arg; - gsurf = CALLOC_STRUCT(egl_g3d_surface); - if (!gsurf) { - _eglError(EGL_BAD_ALLOC, "eglCreatePixmapSurface"); - return NULL; - } + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_WINDOW_BIT; + arg.u.win = win; - if (!_eglInitSurface(&gsurf->base, dpy, EGL_PIXMAP_BIT, conf, attribs)) { - free(gsurf); - return NULL; - } - - gsurf->native = - gdpy->native->create_pixmap_surface(gdpy->native, pix, gconf->native); - if (!gsurf->native) { - free(gsurf); - return NULL; - } + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); +} - if (!init_surface_geometry(&gsurf->base)) { - gsurf->native->destroy(gsurf->native); - free(gsurf); - return NULL; - } +static _EGLSurface * +egl_g3d_create_pixmap_surface(_EGLDriver *drv, _EGLDisplay *dpy, + _EGLConfig *conf, EGLNativePixmapType pix, + const EGLint *attribs) +{ + struct egl_g3d_create_surface_arg arg; - gsurf->render_att = NATIVE_ATTACHMENT_FRONT_LEFT; + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_PIXMAP_BIT; + arg.u.pix = pix; - return &gsurf->base; + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); } static _EGLSurface * egl_g3d_create_pbuffer_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attribs) { - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_config *gconf = egl_g3d_config(conf); - struct egl_g3d_surface *gsurf; - - gsurf = CALLOC_STRUCT(egl_g3d_surface); - if (!gsurf) { - _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); - return NULL; - } - - if (!_eglInitSurface(&gsurf->base, dpy, EGL_PBUFFER_BIT, conf, attribs)) { - free(gsurf); - return NULL; - } - - gsurf->native = - gdpy->native->create_pbuffer_surface(gdpy->native, gconf->native, - gsurf->base.Width, gsurf->base.Height); - if (!gsurf->native) { - free(gsurf); - return NULL; - } - - if (!init_surface_geometry(&gsurf->base)) { - gsurf->native->destroy(gsurf->native); - free(gsurf); - return NULL; - } + struct egl_g3d_create_surface_arg arg; - gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ? - NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_PBUFFER_BIT; - return &gsurf->base; + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); } /** @@ -925,32 +957,14 @@ egl_g3d_swap_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf) if (gctx) gctx->stapi->st_notify_swapbuffers(gctx->draw.st_fb); - /* - * We drew on the back buffer, unless there was no back buffer. - * In that case, we drew on the front buffer. Either case, we call - * swap_buffers. - */ - if (!gsurf->native->swap_buffers(gsurf->native)) - return EGL_FALSE; - - if (gctx) { - struct egl_g3d_config *gconf = egl_g3d_config(gsurf->base.Config); - - /* force validation if the swap method is not copy */ - if (gconf->native->mode.swapMethod != GLX_SWAP_COPY_OML) { - gctx->force_validate = EGL_TRUE; - egl_g3d_validate_context(dpy, &gctx->base); - } - } - - return EGL_TRUE; + return gsurf->native->swap_buffers(gsurf->native); } /** * Find a config that supports the pixmap. */ -static _EGLConfig * -find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix) +_EGLConfig * +egl_g3d_find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix) { struct egl_g3d_display *gdpy = egl_g3d_display(dpy); struct egl_g3d_config *gconf; @@ -1002,7 +1016,7 @@ egl_g3d_copy_buffers(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, if (!gsurf->render_surface) return EGL_TRUE; - gconf = egl_g3d_config(find_pixmap_config(dpy, target)); + gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, target)); if (!gconf) return _eglError(EGL_BAD_NATIVE_PIXMAP, "eglCopyBuffers"); @@ -1109,7 +1123,7 @@ egl_g3d_bind_tex_image(_EGLDriver *drv, _EGLDisplay *dpy, target_format = PIPE_FORMAT_R8G8B8_UNORM; break; case EGL_TEXTURE_RGBA: - target_format = PIPE_FORMAT_A8R8G8B8_UNORM; + target_format = PIPE_FORMAT_B8G8R8A8_UNORM; break; default: return _eglError(EGL_BAD_MATCH, "eglBindTexImage"); @@ -1177,34 +1191,12 @@ static _EGLSurface * egl_g3d_create_screen_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, const EGLint *attribs) { - struct egl_g3d_display *gdpy = egl_g3d_display(dpy); - struct egl_g3d_config *gconf = egl_g3d_config(conf); - struct egl_g3d_surface *gsurf; + struct egl_g3d_create_surface_arg arg; - gsurf = CALLOC_STRUCT(egl_g3d_surface); - if (!gsurf) { - _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); - return NULL; - } - - if (!_eglInitSurface(&gsurf->base, dpy, - EGL_SCREEN_BIT_MESA, conf, attribs)) { - free(gsurf); - return NULL; - } - - gsurf->native = - gdpy->native->modeset->create_scanout_surface(gdpy->native, - gconf->native, gsurf->base.Width, gsurf->base.Height); - if (!gsurf->native) { - free(gsurf); - return NULL; - } + memset(&arg, 0, sizeof(arg)); + arg.type = EGL_SCREEN_BIT_MESA; - gsurf->render_att = (!gconf->native->mode.doubleBufferMode) ? - NATIVE_ATTACHMENT_FRONT_LEFT : NATIVE_ATTACHMENT_BACK_LEFT; - - return &gsurf->base; + return egl_g3d_create_surface(drv, dpy, conf, &arg, attribs); } static EGLBoolean @@ -1335,6 +1327,9 @@ _eglMain(const char *args) gdrv->base.API.BindTexImage = egl_g3d_bind_tex_image; gdrv->base.API.ReleaseTexImage = egl_g3d_release_tex_image; + gdrv->base.API.CreateImageKHR = egl_g3d_create_image; + gdrv->base.API.DestroyImageKHR = egl_g3d_destroy_image; + #ifdef EGL_MESA_screen_surface gdrv->base.API.CreateScreenSurfaceMESA = egl_g3d_create_screen_surface; gdrv->base.API.ShowScreenSurfaceMESA = egl_g3d_show_screen_surface; diff --git a/src/gallium/state_trackers/egl/common/egl_g3d.h b/src/gallium/state_trackers/egl/common/egl_g3d.h index 5d2d9c481a..e3e55e46d3 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d.h +++ b/src/gallium/state_trackers/egl/common/egl_g3d.h @@ -34,6 +34,7 @@ #include "eglcontext.h" #include "eglsurface.h" #include "eglconfig.h" +#include "eglimage.h" #include "eglscreen.h" #include "eglmode.h" @@ -81,6 +82,14 @@ struct egl_g3d_config { const struct native_config *native; }; +struct egl_g3d_image { + _EGLImage base; + struct pipe_texture *texture; + unsigned face; + unsigned level; + unsigned zslice; +}; + struct egl_g3d_screen { _EGLScreen base; const struct native_connector *native; @@ -90,5 +99,10 @@ struct egl_g3d_screen { /* standard typecasts */ _EGL_DRIVER_STANDARD_TYPECASTS(egl_g3d) _EGL_DRIVER_TYPECAST(egl_g3d_screen, _EGLScreen, obj) +_EGL_DRIVER_TYPECAST(egl_g3d_image, _EGLImage, obj) + + +_EGLConfig * +egl_g3d_find_pixmap_config(_EGLDisplay *dpy, EGLNativePixmapType pix); #endif /* _EGL_G3D_H_ */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.c b/src/gallium/state_trackers/egl/common/egl_g3d_image.c new file mode 100644 index 0000000000..d701f9c9a8 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.c @@ -0,0 +1,136 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#include <assert.h> +#include "pipe/p_screen.h" +#include "util/u_memory.h" +#include "util/u_rect.h" +#include "util/u_inlines.h" +#include "eglcurrent.h" +#include "egllog.h" + +#include "native.h" +#include "egl_g3d.h" +#include "egl_g3d_image.h" + +/** + * Reference and return the front left buffer of the native pixmap. + */ +static struct pipe_texture * +egl_g3d_reference_native_pixmap(_EGLDisplay *dpy, EGLNativePixmapType pix) +{ + struct egl_g3d_display *gdpy = egl_g3d_display(dpy); + struct egl_g3d_config *gconf; + struct native_surface *nsurf; + struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + enum native_attachment natt; + + gconf = egl_g3d_config(egl_g3d_find_pixmap_config(dpy, pix)); + if (!gconf) + return NULL; + + nsurf = gdpy->native->create_pixmap_surface(gdpy->native, + pix, gconf->native); + if (!nsurf) + return NULL; + + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + if (!nsurf->validate(nsurf, 1 << natt, NULL, textures, NULL, NULL)) + textures[natt] = NULL; + + nsurf->destroy(nsurf); + + return textures[natt]; +} + +_EGLImage * +egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, + EGLenum target, EGLClientBuffer buffer, + const EGLint *attribs) +{ + struct pipe_texture *ptex; + struct egl_g3d_image *gimg; + unsigned face = 0, level = 0, zslice = 0; + + gimg = CALLOC_STRUCT(egl_g3d_image); + if (!gimg) { + _eglError(EGL_BAD_ALLOC, "eglCreatePbufferSurface"); + return NULL; + } + + if (!_eglInitImage(&gimg->base, dpy, attribs)) { + free(gimg); + return NULL; + } + + switch (target) { + case EGL_NATIVE_PIXMAP_KHR: + ptex = egl_g3d_reference_native_pixmap(dpy, + (EGLNativePixmapType) buffer); + break; + default: + ptex = NULL; + break; + } + + if (!ptex) { + free(gimg); + return NULL; + } + + if (level > ptex->last_level) { + _eglError(EGL_BAD_MATCH, "eglCreateEGLImageKHR"); + pipe_texture_reference(&gimg->texture, NULL); + free(gimg); + return NULL; + } + if (zslice > ptex->depth0) { + _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); + pipe_texture_reference(&gimg->texture, NULL); + free(gimg); + return NULL; + } + + /* transfer the ownership to the image */ + gimg->texture = ptex; + gimg->face = face; + gimg->level = level; + gimg->zslice = zslice; + + return &gimg->base; +} + +EGLBoolean +egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *img) +{ + struct egl_g3d_image *gimg = egl_g3d_image(img); + + pipe_texture_reference(&gimg->texture, NULL); + free(gimg); + + return EGL_TRUE; +} diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_image.h b/src/gallium/state_trackers/egl/common/egl_g3d_image.h new file mode 100644 index 0000000000..c199c46645 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/egl_g3d_image.h @@ -0,0 +1,41 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Chia-I Wu <olv@lunarg.com> + */ + +#ifndef _EGL_G3D_IMAGE_H_ +#define _EGL_G3D_IMAGE_H_ + +#include "egl_g3d.h" + +_EGLImage * +egl_g3d_create_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, + EGLenum target, EGLClientBuffer buffer, + const EGLint *attribs); + +EGLBoolean +egl_g3d_destroy_image(_EGLDriver *drv, _EGLDisplay *dpy, _EGLImage *image); + +#endif /* _EGL_G3D_IMAGE_H_ */ diff --git a/src/gallium/state_trackers/egl/common/native.h b/src/gallium/state_trackers/egl/common/native.h index 4f9758545a..9c22ff3e43 100644 --- a/src/gallium/state_trackers/egl/common/native.h +++ b/src/gallium/state_trackers/egl/common/native.h @@ -34,6 +34,8 @@ #include "pipe/p_context.h" #include "pipe/p_state.h" +#include "native_modeset.h" + /** * Only color buffers are listed. The others are allocated privately through, * for example, st_renderbuffer_alloc_storage(). @@ -47,6 +49,14 @@ enum native_attachment { NUM_NATIVE_ATTACHMENTS }; +enum native_param_type { + /* + * Return TRUE if window/pixmap surfaces use the buffers of the native + * types. + */ + NATIVE_PARAM_USE_NATIVE_BUFFER +}; + /** * Enumerations for probe results. */ @@ -69,6 +79,11 @@ struct native_probe { }; struct native_surface { + /** + * Available for caller's use. + */ + void *user_data; + void (*destroy)(struct native_surface *nsurf); /** @@ -117,18 +132,6 @@ struct native_config { boolean scanout_bit; }; -struct native_connector { - int dummy; -}; - -struct native_mode { - const char *desc; - int width, height; - int refresh_rate; -}; - -struct native_display_modeset; - /** * A pipe winsys abstracts the OS. A pipe screen abstracts the graphcis * hardware. A native display consists of a pipe winsys, a pipe screen, and @@ -143,9 +146,22 @@ struct native_display { */ struct pipe_screen *screen; + /** + * Available for caller's use. + */ + void *user_data; + void (*destroy)(struct native_display *ndpy); /** + * Query the parameters of the native display. + * + * The return value is defined by the parameter. + */ + int (*get_param)(struct native_display *ndpy, + enum native_param_type param); + + /** * Get the supported configs. The configs are owned by the display, but * the returned array should be free()ed. * @@ -196,46 +212,17 @@ struct native_display { }; /** - * Mode setting interface of the native display. It exposes the mode setting - * capabilities of the underlying graphics hardware. + * The handler for events that a native display may generate. The events are + * generated asynchronously and the handler may be called by any thread at any + * time. */ -struct native_display_modeset { - /** - * Get the available physical connectors and the number of CRTCs. - */ - const struct native_connector **(*get_connectors)(struct native_display *ndpy, - int *num_connectors, - int *num_crtcs); - +struct native_event_handler { /** - * Get the current supported modes of a connector. The returned modes may - * change every time this function is called and those from previous calls - * might become invalid. - */ - const struct native_mode **(*get_modes)(struct native_display *ndpy, - const struct native_connector *nconn, - int *num_modes); - - /** - * Create a scan-out surface. Required unless no config has - * GLX_SCREEN_BIT_MESA set. - */ - struct native_surface *(*create_scanout_surface)(struct native_display *ndpy, - const struct native_config *nconf, - uint width, uint height); - - /** - * Program the CRTC to output the surface to the given connectors with the - * given mode. When surface is not given, the CRTC is disabled. - * - * This interface does not export a way to query capabilities of the CRTCs. - * The native display usually needs to dynamically map the index to a CRTC - * that supports the given connectors. + * This function is called when a surface needs to be validated. */ - boolean (*program)(struct native_display *ndpy, int crtc_idx, - struct native_surface *nsurf, uint x, uint y, - const struct native_connector **nconns, int num_nconns, - const struct native_mode *nmode); + void (*invalid_surface)(struct native_display *ndpy, + struct native_surface *nsurf, + unsigned int seq_num); }; /** @@ -267,6 +254,7 @@ const char * native_get_name(void); struct native_display * -native_create_display(EGLNativeDisplayType dpy); +native_create_display(EGLNativeDisplayType dpy, + struct native_event_handler *handler); #endif /* _NATIVE_H_ */ diff --git a/src/gallium/state_trackers/egl/common/native_modeset.h b/src/gallium/state_trackers/egl/common/native_modeset.h new file mode 100644 index 0000000000..71dc3ec860 --- /dev/null +++ b/src/gallium/state_trackers/egl/common/native_modeset.h @@ -0,0 +1,87 @@ +/* + * Mesa 3-D graphics library + * Version: 7.8 + * + * Copyright (C) 2009-2010 Chia-I Wu <olv@0xlab.org> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef _NATIVE_MODESET_H_ +#define _NATIVE_MODESET_H_ + +#include "pipe/p_compiler.h" + +struct native_display; +struct native_surface; +struct native_config; + +struct native_connector { + int dummy; +}; + +struct native_mode { + const char *desc; + int width, height; + int refresh_rate; +}; + +/** + * Mode setting interface of the native display. It exposes the mode setting + * capabilities of the underlying graphics hardware. + */ +struct native_display_modeset { + /** + * Get the available physical connectors and the number of CRTCs. + */ + const struct native_connector **(*get_connectors)(struct native_display *ndpy, + int *num_connectors, + int *num_crtcs); + + /** + * Get the current supported modes of a connector. The returned modes may + * change every time this function is called and those from previous calls + * might become invalid. + */ + const struct native_mode **(*get_modes)(struct native_display *ndpy, + const struct native_connector *nconn, + int *num_modes); + + /** + * Create a scan-out surface. Required unless no config has + * GLX_SCREEN_BIT_MESA set. + */ + struct native_surface *(*create_scanout_surface)(struct native_display *ndpy, + const struct native_config *nconf, + uint width, uint height); + + /** + * Program the CRTC to output the surface to the given connectors with the + * given mode. When surface is not given, the CRTC is disabled. + * + * This interface does not export a way to query capabilities of the CRTCs. + * The native display usually needs to dynamically map the index to a CRTC + * that supports the given connectors. + */ + boolean (*program)(struct native_display *ndpy, int crtc_idx, + struct native_surface *nsurf, uint x, uint y, + const struct native_connector **nconns, int num_nconns, + const struct native_mode *nmode); +}; + +#endif /* _NATIVE_MODESET_H_ */ diff --git a/src/gallium/state_trackers/egl/kms/native_kms.c b/src/gallium/state_trackers/egl/kms/native_kms.c index 91cefc538d..7322240856 100644 --- a/src/gallium/state_trackers/egl/kms/native_kms.c +++ b/src/gallium/state_trackers/egl/kms/native_kms.c @@ -55,7 +55,7 @@ kms_surface_validate(struct native_surface *nsurf, uint attachment_mask, templ.format = ksurf->color_format; templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; if (ksurf->type == KMS_SURFACE_TYPE_SCANOUT) - templ.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; + templ.tex_usage |= PIPE_TEXTURE_USAGE_SCANOUT; } /* create textures */ @@ -100,7 +100,7 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) for (i = 0; i < num_framebuffers; i++) { struct kms_framebuffer *fb; enum native_attachment natt; - unsigned int handle, stride; + struct winsys_handle whandle; uint block_bits; if (i == 0) { @@ -128,13 +128,17 @@ kms_surface_init_framebuffers(struct native_surface *nsurf, boolean need_back) /* TODO detect the real value */ fb->is_passive = TRUE; - if (!kdpy->api->local_handle_from_texture(kdpy->api, - kdpy->base.screen, fb->texture, &stride, &handle)) + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_KMS; + + if (!kdpy->base.screen->texture_get_handle(kdpy->base.screen, + fb->texture, &whandle)) return FALSE; block_bits = util_format_get_blocksizebits(ksurf->color_format); err = drmModeAddFB(kdpy->fd, ksurf->width, ksurf->height, - block_bits, block_bits, stride, handle, &fb->buffer_id); + block_bits, block_bits, whandle.stride, whandle.handle, + &fb->buffer_id); if (err) { fb->buffer_id = 0; return FALSE; @@ -201,6 +205,8 @@ kms_surface_swap_buffers(struct native_surface *nsurf) /* the front/back textures are swapped */ ksurf->sequence_number++; + kdpy->event_handler->invalid_surface(&kdpy->base, + &ksurf->base, ksurf->sequence_number); return TRUE; } @@ -499,7 +505,10 @@ kms_display_get_modes(struct native_display *ndpy, kmode->base.desc = kmode->mode.name; kmode->base.width = kmode->mode.hdisplay; kmode->base.height = kmode->mode.vdisplay; - kmode->base.refresh_rate = kmode->mode.vrefresh / 1000; + kmode->base.refresh_rate = kmode->mode.vrefresh; + /* not all kernels have vrefresh = refresh_rate * 1000 */ + if (kmode->base.refresh_rate > 1000) + kmode->base.refresh_rate = (kmode->base.refresh_rate + 500) / 1000; } nmodes_return = malloc(count * sizeof(*nmodes_return)); @@ -606,9 +615,9 @@ kms_display_get_configs(struct native_display *ndpy, int *num_configs) /* always double-buffered */ nconf->mode.doubleBufferMode = TRUE; - format = PIPE_FORMAT_A8R8G8B8_UNORM; + format = PIPE_FORMAT_B8G8R8A8_UNORM; if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) { - format = PIPE_FORMAT_B8G8R8A8_UNORM; + format = PIPE_FORMAT_A8R8G8B8_UNORM; if (!kms_display_is_format_supported(&kdpy->base, format, TRUE)) format = PIPE_FORMAT_NONE; } @@ -622,9 +631,9 @@ kms_display_get_configs(struct native_display *ndpy, int *num_configs) nconf->mode.alphaBits = 8; nconf->mode.rgbBits = 32; - format = PIPE_FORMAT_S8Z24_UNORM; + format = PIPE_FORMAT_Z24S8_UNORM; if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) { - format = PIPE_FORMAT_Z24S8_UNORM; + format = PIPE_FORMAT_S8Z24_UNORM; if (!kms_display_is_format_supported(&kdpy->base, format, FALSE)) format = PIPE_FORMAT_NONE; } @@ -660,6 +669,21 @@ kms_display_get_configs(struct native_display *ndpy, int *num_configs) return configs; } +static int +kms_display_get_param(struct native_display *ndpy, + enum native_param_type param) +{ + int val; + + switch (param) { + default: + val = 0; + break; + } + + return val; +} + static void kms_display_destroy(struct native_display *ndpy) { @@ -759,7 +783,9 @@ static struct native_display_modeset kms_display_modeset = { }; static struct native_display * -kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api) +kms_create_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler, + struct drm_api *api) { struct kms_display *kdpy; @@ -767,6 +793,8 @@ kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api) if (!kdpy) return NULL; + kdpy->event_handler = event_handler; + kdpy->api = api; if (!kdpy->api) { _eglLog(_EGL_WARNING, "failed to create DRM API"); @@ -802,6 +830,7 @@ kms_create_display(EGLNativeDisplayType dpy, struct drm_api *api) } kdpy->base.destroy = kms_display_destroy; + kdpy->base.get_param = kms_display_get_param; kdpy->base.get_configs = kms_display_get_configs; kdpy->base.create_pbuffer_surface = kms_display_create_pbuffer_surface; @@ -842,7 +871,8 @@ native_get_name(void) } struct native_display * -native_create_display(EGLNativeDisplayType dpy) +native_create_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler) { struct native_display *ndpy = NULL; @@ -850,7 +880,7 @@ native_create_display(EGLNativeDisplayType dpy) drm_api = drm_api_create(); if (drm_api) - ndpy = kms_create_display(dpy, drm_api); + ndpy = kms_create_display(dpy, event_handler, drm_api); return ndpy; } diff --git a/src/gallium/state_trackers/egl/kms/native_kms.h b/src/gallium/state_trackers/egl/kms/native_kms.h index 095186e3cf..f9cbcb158b 100644 --- a/src/gallium/state_trackers/egl/kms/native_kms.h +++ b/src/gallium/state_trackers/egl/kms/native_kms.h @@ -53,6 +53,8 @@ struct kms_crtc { struct kms_display { struct native_display base; + struct native_event_handler *event_handler; + int fd; struct drm_api *api; drmModeResPtr resources; diff --git a/src/gallium/state_trackers/egl/x11/native_dri2.c b/src/gallium/state_trackers/egl/x11/native_dri2.c index 5f2fd41260..9839979231 100644 --- a/src/gallium/state_trackers/egl/x11/native_dri2.c +++ b/src/gallium/state_trackers/egl/x11/native_dri2.c @@ -26,6 +26,7 @@ #include "util/u_math.h" #include "util/u_format.h" #include "util/u_inlines.h" +#include "util/u_hash_table.h" #include "pipe/p_compiler.h" #include "pipe/p_screen.h" #include "pipe/p_context.h" @@ -47,12 +48,18 @@ struct dri2_display { Display *dpy; boolean own_dpy; + struct native_event_handler *event_handler; + struct drm_api *api; struct x11_screen *xscr; int xscr_number; + const char *dri_driver; + int dri_major, dri_minor; struct dri2_config *configs; int num_configs; + + struct util_hash_table *surfaces; }; struct dri2_surface { @@ -62,10 +69,16 @@ struct dri2_surface { enum pipe_format color_format; struct dri2_display *dri2dpy; - struct pipe_texture *pbuffer_textures[NUM_NATIVE_ATTACHMENTS]; - boolean have_back, have_fake; + unsigned int server_stamp; + unsigned int client_stamp; int width, height; - unsigned int sequence_number; + struct pipe_texture *textures[NUM_NATIVE_ATTACHMENTS]; + uint valid_mask; + + boolean have_back, have_fake; + + struct x11_drawable_buffer *last_xbufs; + int last_num_xbufs; }; struct dri2_config { @@ -90,110 +103,103 @@ dri2_config(const struct native_config *nconf) return (struct dri2_config *) nconf; } -static boolean -dri2_surface_flush_frontbuffer(struct native_surface *nsurf) +/** + * Process the buffers returned by the server. + */ +static void +dri2_surface_process_drawable_buffers(struct native_surface *nsurf, + struct x11_drawable_buffer *xbufs, + int num_xbufs) { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; + struct pipe_texture templ; + struct winsys_handle whandle; + uint valid_mask; + int i; - /* pbuffer is private */ - if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) - return TRUE; + /* free the old textures */ + for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) + pipe_texture_reference(&dri2surf->textures[i], NULL); + dri2surf->valid_mask = 0x0; - /* copy to real front buffer */ - if (dri2surf->have_fake) - x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, - 0, 0, dri2surf->width, dri2surf->height, - DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); + dri2surf->have_back = FALSE; + dri2surf->have_fake = FALSE; - return TRUE; -} + if (!xbufs) + return; -static boolean -dri2_surface_swap_buffers(struct native_surface *nsurf) -{ - struct dri2_surface *dri2surf = dri2_surface(nsurf); - struct dri2_display *dri2dpy = dri2surf->dri2dpy; + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = dri2surf->width; + templ.height0 = dri2surf->height; + templ.depth0 = 1; + templ.format = dri2surf->color_format; + templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - /* pbuffer is private */ - if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) - return TRUE; + valid_mask = 0x0; + for (i = 0; i < num_xbufs; i++) { + struct x11_drawable_buffer *xbuf = &xbufs[i]; + const char *desc; + enum native_attachment natt; - /* copy to front buffer */ - if (dri2surf->have_back) - x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, - 0, 0, dri2surf->width, dri2surf->height, - DRI2BufferBackLeft, DRI2BufferFrontLeft); + switch (xbuf->attachment) { + case DRI2BufferFrontLeft: + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + desc = "DRI2 Front Buffer"; + break; + case DRI2BufferFakeFrontLeft: + natt = NATIVE_ATTACHMENT_FRONT_LEFT; + desc = "DRI2 Fake Front Buffer"; + dri2surf->have_fake = TRUE; + break; + case DRI2BufferBackLeft: + natt = NATIVE_ATTACHMENT_BACK_LEFT; + desc = "DRI2 Back Buffer"; + dri2surf->have_back = TRUE; + break; + default: + desc = NULL; + break; + } - /* and update fake front buffer */ - if (dri2surf->have_fake) - x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, - 0, 0, dri2surf->width, dri2surf->height, - DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); + if (!desc || dri2surf->textures[natt]) { + if (!desc) + _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment); + else + _eglLog(_EGL_WARNING, "both real and fake front buffers are listed"); + continue; + } - return TRUE; + memset(&whandle, 0, sizeof(whandle)); + whandle.stride = xbuf->pitch; + whandle.handle = xbuf->name; + dri2surf->textures[natt] = dri2dpy->base.screen->texture_from_handle( + dri2dpy->base.screen, &templ, &whandle); + if (dri2surf->textures[natt]) + valid_mask |= 1 << natt; + } + + dri2surf->valid_mask = valid_mask; } -static boolean -dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, - unsigned int *seq_num, struct pipe_texture **textures, - int *width, int *height) +/** + * Get the buffers from the server. + */ +static void +dri2_surface_get_buffers(struct native_surface *nsurf, uint buffer_mask) { struct dri2_surface *dri2surf = dri2_surface(nsurf); struct dri2_display *dri2dpy = dri2surf->dri2dpy; unsigned int dri2atts[NUM_NATIVE_ATTACHMENTS]; - struct pipe_texture templ; + int num_ins, num_outs, att; struct x11_drawable_buffer *xbufs; - int num_ins, num_outs, att, i; - - if (attachment_mask) { - memset(&templ, 0, sizeof(templ)); - templ.target = PIPE_TEXTURE_2D; - templ.last_level = 0; - templ.width0 = dri2surf->width; - templ.height0 = dri2surf->height; - templ.depth0 = 1; - templ.format = dri2surf->color_format; - templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - - if (textures) - memset(textures, 0, sizeof(*textures) * NUM_NATIVE_ATTACHMENTS); - } - - /* create textures for pbuffer */ - if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) { - struct pipe_screen *screen = dri2dpy->base.screen; - - for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { - struct pipe_texture *ptex = dri2surf->pbuffer_textures[att]; - - /* delay the allocation */ - if (!native_attachment_mask_test(attachment_mask, att)) - continue; - - if (!ptex) { - ptex = screen->texture_create(screen, &templ); - dri2surf->pbuffer_textures[att] = ptex; - } - - if (textures) - pipe_texture_reference(&textures[att], ptex); - } - - if (seq_num) - *seq_num = dri2surf->sequence_number; - if (width) - *width = dri2surf->width; - if (height) - *height = dri2surf->height; - - return TRUE; - } /* prepare the attachments */ num_ins = 0; for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { - if (native_attachment_mask_test(attachment_mask, att)) { + if (native_attachment_mask_test(buffer_mask, att)) { unsigned int dri2att; switch (att) { @@ -220,79 +226,178 @@ dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, } } - dri2surf->have_back = FALSE; - dri2surf->have_fake = FALSE; - - /* remember old geometry */ - templ.width0 = dri2surf->width; - templ.height0 = dri2surf->height; - xbufs = x11_drawable_get_buffers(dri2dpy->xscr, dri2surf->drawable, &dri2surf->width, &dri2surf->height, dri2atts, FALSE, num_ins, &num_outs); - if (!xbufs) - return FALSE; - if (templ.width0 != dri2surf->width || templ.height0 != dri2surf->height) { - /* are there cases where the buffers change and the geometry doesn't? */ - dri2surf->sequence_number++; + /* we should be able to do better... */ + if (xbufs && dri2surf->last_num_xbufs == num_outs && + memcmp(dri2surf->last_xbufs, xbufs, sizeof(*xbufs) * num_outs) == 0) { + free(xbufs); + dri2surf->client_stamp = dri2surf->server_stamp; + return; + } + + dri2_surface_process_drawable_buffers(&dri2surf->base, xbufs, num_outs); + dri2surf->server_stamp++; + dri2surf->client_stamp = dri2surf->server_stamp; + + if (dri2surf->last_xbufs) + free(dri2surf->last_xbufs); + dri2surf->last_xbufs = xbufs; + dri2surf->last_num_xbufs = num_outs; +} + +/** + * Update the buffers of the surface. This is a slow function due to the + * round-trip to the server. + */ +static boolean +dri2_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) +{ + struct dri2_surface *dri2surf = dri2_surface(nsurf); + struct dri2_display *dri2dpy = dri2surf->dri2dpy; + + /* create textures for pbuffer */ + if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) { + struct pipe_screen *screen = dri2dpy->base.screen; + struct pipe_texture templ; + uint new_valid = 0x0; + int att; + + buffer_mask &= ~dri2surf->valid_mask; + if (!buffer_mask) + return TRUE; + + memset(&templ, 0, sizeof(templ)); + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; templ.width0 = dri2surf->width; templ.height0 = dri2surf->height; - } - - for (i = 0; i < num_outs; i++) { - struct x11_drawable_buffer *xbuf = &xbufs[i]; - const char *desc; - enum native_attachment natt; + templ.depth0 = 1; + templ.format = dri2surf->color_format; + templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; - switch (xbuf->attachment) { - case DRI2BufferFrontLeft: - natt = NATIVE_ATTACHMENT_FRONT_LEFT; - desc = "DRI2 Front Buffer"; - break; - case DRI2BufferFakeFrontLeft: - natt = NATIVE_ATTACHMENT_FRONT_LEFT; - desc = "DRI2 Fake Front Buffer"; - dri2surf->have_fake = TRUE; - break; - case DRI2BufferBackLeft: - natt = NATIVE_ATTACHMENT_BACK_LEFT; - desc = "DRI2 Back Buffer"; - dri2surf->have_back = TRUE; - break; - default: - desc = NULL; - break; - } + for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { + if (native_attachment_mask_test(buffer_mask, att)) { + assert(!dri2surf->textures[att]); - if (!desc || !native_attachment_mask_test(attachment_mask, natt) || - (textures && textures[natt])) { - if (!desc) - _eglLog(_EGL_WARNING, "unknown buffer %d", xbuf->attachment); - else if (!native_attachment_mask_test(attachment_mask, natt)) - _eglLog(_EGL_WARNING, "unexpected buffer %d", xbuf->attachment); - else - _eglLog(_EGL_WARNING, "both real and fake front buffers are listed"); - continue; - } + dri2surf->textures[att] = screen->texture_create(screen, &templ); + if (!dri2surf->textures[att]) + break; - if (textures) { - struct pipe_texture *ptex = - dri2dpy->api->texture_from_shared_handle(dri2dpy->api, - dri2dpy->base.screen, &templ, - desc, xbuf->pitch, xbuf->name); - if (ptex) { - /* the caller owns the textures */ - textures[natt] = ptex; + new_valid |= 1 << att; + if (new_valid == buffer_mask) + break; } } + dri2surf->valid_mask |= new_valid; + /* no need to update the stamps */ + } + else { + dri2_surface_get_buffers(&dri2surf->base, buffer_mask); + } + + return ((dri2surf->valid_mask & buffer_mask) == buffer_mask); +} + +/** + * Return TRUE if the surface receives DRI2_InvalidateBuffers events. + */ +static INLINE boolean +dri2_surface_receive_events(struct native_surface *nsurf) +{ + struct dri2_surface *dri2surf = dri2_surface(nsurf); + return (dri2surf->dri2dpy->dri_minor >= 3); +} + +static boolean +dri2_surface_flush_frontbuffer(struct native_surface *nsurf) +{ + struct dri2_surface *dri2surf = dri2_surface(nsurf); + struct dri2_display *dri2dpy = dri2surf->dri2dpy; + + /* pbuffer is private */ + if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) + return TRUE; + + /* copy to real front buffer */ + if (dri2surf->have_fake) + x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, + 0, 0, dri2surf->width, dri2surf->height, + DRI2BufferFakeFrontLeft, DRI2BufferFrontLeft); + + /* force buffers to be updated in next validation call */ + if (!dri2_surface_receive_events(&dri2surf->base)) { + dri2surf->server_stamp++; + dri2dpy->event_handler->invalid_surface(&dri2dpy->base, + &dri2surf->base, dri2surf->server_stamp); } - free(xbufs); + return TRUE; +} + +static boolean +dri2_surface_swap_buffers(struct native_surface *nsurf) +{ + struct dri2_surface *dri2surf = dri2_surface(nsurf); + struct dri2_display *dri2dpy = dri2surf->dri2dpy; + + /* pbuffer is private */ + if (dri2surf->type == DRI2_SURFACE_TYPE_PBUFFER) + return TRUE; + + /* copy to front buffer */ + if (dri2surf->have_back) + x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, + 0, 0, dri2surf->width, dri2surf->height, + DRI2BufferBackLeft, DRI2BufferFrontLeft); + + /* and update fake front buffer */ + if (dri2surf->have_fake) + x11_drawable_copy_buffers(dri2dpy->xscr, dri2surf->drawable, + 0, 0, dri2surf->width, dri2surf->height, + DRI2BufferFrontLeft, DRI2BufferFakeFrontLeft); + + /* force buffers to be updated in next validation call */ + if (!dri2_surface_receive_events(&dri2surf->base)) { + dri2surf->server_stamp++; + dri2dpy->event_handler->invalid_surface(&dri2dpy->base, + &dri2surf->base, dri2surf->server_stamp); + } + + return TRUE; +} + +static boolean +dri2_surface_validate(struct native_surface *nsurf, uint attachment_mask, + unsigned int *seq_num, struct pipe_texture **textures, + int *width, int *height) +{ + struct dri2_surface *dri2surf = dri2_surface(nsurf); + + if (dri2surf->server_stamp != dri2surf->client_stamp || + (dri2surf->valid_mask & attachment_mask) != attachment_mask) { + if (!dri2_surface_update_buffers(&dri2surf->base, attachment_mask)) + return FALSE; + } if (seq_num) - *seq_num = dri2surf->sequence_number; + *seq_num = dri2surf->client_stamp; + + if (textures) { + int att; + for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { + if (native_attachment_mask_test(attachment_mask, att)) { + struct pipe_texture *ptex = dri2surf->textures[att]; + + textures[att] = NULL; + pipe_texture_reference(&textures[att], ptex); + } + } + } + if (width) *width = dri2surf->width; if (height) @@ -320,14 +425,21 @@ dri2_surface_destroy(struct native_surface *nsurf) struct dri2_surface *dri2surf = dri2_surface(nsurf); int i; + if (dri2surf->last_xbufs) + free(dri2surf->last_xbufs); + for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { - struct pipe_texture *ptex = dri2surf->pbuffer_textures[i]; + struct pipe_texture *ptex = dri2surf->textures[i]; pipe_texture_reference(&ptex, NULL); } - if (dri2surf->drawable) + if (dri2surf->drawable) { x11_drawable_enable_dri2(dri2surf->dri2dpy->xscr, dri2surf->drawable, FALSE); + + util_hash_table_remove(dri2surf->dri2dpy->surfaces, + (void *) dri2surf->drawable); + } free(dri2surf); } @@ -345,9 +457,6 @@ dri2_display_create_surface(struct native_display *ndpy, if (!dri2surf) return NULL; - if (drawable) - x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE); - dri2surf->dri2dpy = dri2dpy; dri2surf->type = type; dri2surf->drawable = drawable; @@ -359,6 +468,15 @@ dri2_display_create_surface(struct native_display *ndpy, dri2surf->base.validate = dri2_surface_validate; dri2surf->base.wait = dri2_surface_wait; + if (drawable) { + x11_drawable_enable_dri2(dri2dpy->xscr, drawable, TRUE); + /* initialize the geometry */ + dri2_surface_update_buffers(&dri2surf->base, 0x0); + + util_hash_table_set(dri2surf->dri2dpy->surfaces, + (void *) dri2surf->drawable, (void *) &dri2surf->base); + } + return dri2surf; } @@ -409,17 +527,17 @@ choose_color_format(const __GLcontextModes *mode, enum pipe_format formats[32]) switch (mode->rgbBits) { case 32: - formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM; formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM; + formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM; break; case 24: - formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM; formats[count++] = PIPE_FORMAT_B8G8R8X8_UNORM; - formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM; + formats[count++] = PIPE_FORMAT_X8R8G8B8_UNORM; formats[count++] = PIPE_FORMAT_B8G8R8A8_UNORM; + formats[count++] = PIPE_FORMAT_A8R8G8B8_UNORM; break; case 16: - formats[count++] = PIPE_FORMAT_R5G6B5_UNORM; + formats[count++] = PIPE_FORMAT_B5G6R5_UNORM; break; default: break; @@ -440,12 +558,12 @@ choose_depth_stencil_format(const __GLcontextModes *mode, break; case 24: if (mode->stencilBits) { - formats[count++] = PIPE_FORMAT_S8Z24_UNORM; formats[count++] = PIPE_FORMAT_Z24S8_UNORM; + formats[count++] = PIPE_FORMAT_S8Z24_UNORM; } else { - formats[count++] = PIPE_FORMAT_X8Z24_UNORM; formats[count++] = PIPE_FORMAT_Z24X8_UNORM; + formats[count++] = PIPE_FORMAT_X8Z24_UNORM; } break; case 16: @@ -592,6 +710,25 @@ dri2_display_is_pixmap_supported(struct native_display *ndpy, return (depth == nconf_depth || (depth == 24 && depth + 8 == nconf_depth)); } +static int +dri2_display_get_param(struct native_display *ndpy, + enum native_param_type param) +{ + int val; + + switch (param) { + case NATIVE_PARAM_USE_NATIVE_BUFFER: + /* DRI2GetBuffers use the native buffers */ + val = TRUE; + break; + default: + val = 0; + break; + } + + return val; +} + static void dri2_display_destroy(struct native_display *ndpy) { @@ -603,6 +740,9 @@ dri2_display_destroy(struct native_display *ndpy) if (dri2dpy->base.screen) dri2dpy->base.screen->destroy(dri2dpy->base.screen); + if (dri2dpy->surfaces) + util_hash_table_destroy(dri2dpy->surfaces); + if (dri2dpy->xscr) x11_screen_destroy(dri2dpy->xscr); if (dri2dpy->own_dpy) @@ -612,6 +752,27 @@ dri2_display_destroy(struct native_display *ndpy) free(dri2dpy); } +static void +dri2_display_invalidate_buffers(struct x11_screen *xscr, Drawable drawable, + void *user_data) +{ + struct native_display *ndpy = (struct native_display* ) user_data; + struct dri2_display *dri2dpy = dri2_display(ndpy); + struct native_surface *nsurf; + struct dri2_surface *dri2surf; + + nsurf = (struct native_surface *) + util_hash_table_get(dri2dpy->surfaces, (void *) drawable); + if (!nsurf) + return; + + dri2surf = dri2_surface(nsurf); + + dri2surf->server_stamp++; + dri2dpy->event_handler->invalid_surface(&dri2dpy->base, + &dri2surf->base, dri2surf->server_stamp); +} + /** * Initialize DRI2 and pipe screen. */ @@ -629,7 +790,17 @@ dri2_display_init_screen(struct native_display *ndpy) return FALSE; } - fd = x11_screen_enable_dri2(dri2dpy->xscr, driver); + dri2dpy->dri_driver = x11_screen_probe_dri2(dri2dpy->xscr, + &dri2dpy->dri_major, &dri2dpy->dri_minor); + if (!dri2dpy->dri_driver || !driver || + strcmp(dri2dpy->dri_driver, driver) != 0) { + _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s", + dri2dpy->dri_driver, dri2dpy->api->name); + return FALSE; + } + + fd = x11_screen_enable_dri2(dri2dpy->xscr, + dri2_display_invalidate_buffers, &dri2dpy->base); if (fd < 0) return FALSE; @@ -644,8 +815,23 @@ dri2_display_init_screen(struct native_display *ndpy) return TRUE; } +static unsigned +dri2_display_hash_table_hash(void *key) +{ + XID drawable = pointer_to_uintptr(key); + return (unsigned) drawable; +} + +static int +dri2_display_hash_table_compare(void *key1, void *key2) +{ + return (key1 - key2); +} + struct native_display * -x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api) +x11_create_dri2_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler, + struct drm_api *api) { struct dri2_display *dri2dpy; @@ -653,12 +839,8 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api) if (!dri2dpy) return NULL; + dri2dpy->event_handler = event_handler; dri2dpy->api = api; - if (!dri2dpy->api) { - _eglLog(_EGL_WARNING, "failed to create DRM API"); - free(dri2dpy); - return NULL; - } dri2dpy->dpy = dpy; if (!dri2dpy->dpy) { @@ -682,7 +864,15 @@ x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api) return NULL; } + dri2dpy->surfaces = util_hash_table_create(dri2_display_hash_table_hash, + dri2_display_hash_table_compare); + if (!dri2dpy->surfaces) { + dri2_display_destroy(&dri2dpy->base); + return NULL; + } + dri2dpy->base.destroy = dri2_display_destroy; + dri2dpy->base.get_param = dri2_display_get_param; dri2dpy->base.get_configs = dri2_display_get_configs; dri2dpy->base.is_pixmap_supported = dri2_display_is_pixmap_supported; dri2dpy->base.create_window_surface = dri2_display_create_window_surface; diff --git a/src/gallium/state_trackers/egl/x11/native_x11.c b/src/gallium/state_trackers/egl/x11/native_x11.c index 8eb542bd82..7b4fe63fa0 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.c +++ b/src/gallium/state_trackers/egl/x11/native_x11.c @@ -70,7 +70,7 @@ native_create_probe(EGLNativeDisplayType dpy) xscr = x11_screen_create(xdpy, scr); if (xscr) { if (x11_screen_support(xscr, X11_SCREEN_EXTENSION_DRI2)) { - driver_name = x11_screen_probe_dri2(xscr); + driver_name = x11_screen_probe_dri2(xscr, NULL, NULL); if (driver_name) nprobe->data = strdup(driver_name); } @@ -126,7 +126,8 @@ native_get_name(void) } struct native_display * -native_create_display(EGLNativeDisplayType dpy) +native_create_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler) { struct native_display *ndpy = NULL; boolean force_sw; @@ -136,14 +137,21 @@ native_create_display(EGLNativeDisplayType dpy) force_sw = debug_get_bool_option("EGL_SOFTWARE", FALSE); if (api && !force_sw) { - ndpy = x11_create_dri2_display(dpy, api); + ndpy = x11_create_dri2_display(dpy, event_handler, api); } if (!ndpy) { EGLint level = (force_sw) ? _EGL_INFO : _EGL_WARNING; - - _eglLog(level, "use software fallback"); - ndpy = x11_create_ximage_display(dpy, TRUE); + boolean use_shm; + + /* + * XXX st/mesa calls pipe_screen::update_buffer in st_validate_state. + * When SHM is used, there is a good chance that the shared memory + * segment is detached before the softpipe tile cache is flushed. + */ + use_shm = FALSE; + _eglLog(level, "use software%s fallback", (use_shm) ? " (SHM)" : ""); + ndpy = x11_create_ximage_display(dpy, event_handler, use_shm); } return ndpy; diff --git a/src/gallium/state_trackers/egl/x11/native_x11.h b/src/gallium/state_trackers/egl/x11/native_x11.h index 622ddac5df..8c6a7d9349 100644 --- a/src/gallium/state_trackers/egl/x11/native_x11.h +++ b/src/gallium/state_trackers/egl/x11/native_x11.h @@ -29,9 +29,13 @@ #include "common/native.h" struct native_display * -x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm); +x11_create_ximage_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler, + boolean use_xshm); struct native_display * -x11_create_dri2_display(EGLNativeDisplayType dpy, struct drm_api *api); +x11_create_dri2_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler, + struct drm_api *api); #endif /* _NATIVE_X11_H_ */ diff --git a/src/gallium/state_trackers/egl/x11/native_ximage.c b/src/gallium/state_trackers/egl/x11/native_ximage.c index 92a62f230e..a94b1ca6c6 100644 --- a/src/gallium/state_trackers/egl/x11/native_ximage.c +++ b/src/gallium/state_trackers/egl/x11/native_ximage.c @@ -56,6 +56,8 @@ struct ximage_display { struct x11_screen *xscr; int xscr_number; + struct native_event_handler *event_handler; + boolean use_xshm; struct pipe_winsys *winsys; @@ -79,11 +81,13 @@ struct ximage_surface { XVisualInfo visual; struct ximage_display *xdpy; - int width, height; GC gc; + unsigned int server_stamp; + unsigned int client_stamp; + int width, height; struct ximage_buffer buffers[NUM_NATIVE_ATTACHMENTS]; - unsigned int sequence_number; + uint valid_mask; }; struct ximage_config { @@ -152,6 +156,11 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf, templ.depth0 = 1; templ.tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET; +#if 0 + /* Interesting and suprising use of texture_blanket + + * user_buffer_create... To be superceded by the sw_winsys branch, + * but currently disabled. + */ if (xbuf->shm_info) { struct pipe_buffer *pbuf; unsigned stride, size; @@ -184,7 +193,9 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf, } } } - else { + else +#endif + { xbuf->texture = screen->texture_create(screen, &templ); } @@ -195,6 +206,100 @@ ximage_surface_alloc_buffer(struct native_surface *nsurf, return (xbuf->texture != NULL); } +/** + * Update the geometry of the surface. Return TRUE if the geometry has changed + * since last call. + */ +static boolean +ximage_surface_update_geometry(struct native_surface *nsurf) +{ + struct ximage_surface *xsurf = ximage_surface(nsurf); + Status ok; + Window root; + int x, y; + unsigned int w, h, border, depth; + boolean updated = FALSE; + + /* pbuffer has fixed geometry */ + if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER) + return FALSE; + + ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable, + &root, &x, &y, &w, &h, &border, &depth); + if (ok && (xsurf->width != w || xsurf->height != h)) { + xsurf->width = w; + xsurf->height = h; + + xsurf->server_stamp++; + updated = TRUE; + } + + return updated; +} + +static void +ximage_surface_notify_invalid(struct native_surface *nsurf) +{ + struct ximage_surface *xsurf = ximage_surface(nsurf); + struct ximage_display *xdpy = xsurf->xdpy; + + xdpy->event_handler->invalid_surface(&xdpy->base, + &xsurf->base, xsurf->server_stamp); +} + +/** + * Update the buffers of the surface. It is a slow function due to the + * round-trip to the server. + */ +static boolean +ximage_surface_update_buffers(struct native_surface *nsurf, uint buffer_mask) +{ + struct ximage_surface *xsurf = ximage_surface(nsurf); + boolean updated; + uint new_valid; + int att; + + updated = ximage_surface_update_geometry(&xsurf->base); + if (updated) { + /* all buffers become invalid */ + xsurf->valid_mask = 0x0; + } + else { + buffer_mask &= ~xsurf->valid_mask; + /* all requested buffers are valid */ + if (!buffer_mask) { + xsurf->client_stamp = xsurf->server_stamp; + return TRUE; + } + } + + new_valid = 0x0; + for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { + if (native_attachment_mask_test(buffer_mask, att)) { + struct ximage_buffer *xbuf = &xsurf->buffers[att]; + + /* reallocate the texture */ + if (!ximage_surface_alloc_buffer(&xsurf->base, att)) + break; + + /* update ximage */ + if (xbuf->ximage) { + xbuf->ximage->width = xsurf->width; + xbuf->ximage->height = xsurf->height; + } + + new_valid |= (1 << att); + if (buffer_mask == new_valid) + break; + } + } + + xsurf->valid_mask |= new_valid; + xsurf->client_stamp = xsurf->server_stamp; + + return (new_valid == buffer_mask); +} + static boolean ximage_surface_draw_buffer(struct native_surface *nsurf, enum native_attachment which) @@ -246,7 +351,16 @@ ximage_surface_draw_buffer(struct native_surface *nsurf, static boolean ximage_surface_flush_frontbuffer(struct native_surface *nsurf) { - return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); + struct ximage_surface *xsurf = ximage_surface(nsurf); + boolean ret; + + ret = ximage_surface_draw_buffer(&xsurf->base, + NATIVE_ATTACHMENT_FRONT_LEFT); + /* force buffers to be updated in next validation call */ + xsurf->server_stamp++; + ximage_surface_notify_invalid(&xsurf->base); + + return ret; } static boolean @@ -254,44 +368,26 @@ ximage_surface_swap_buffers(struct native_surface *nsurf) { struct ximage_surface *xsurf = ximage_surface(nsurf); struct ximage_buffer *xfront, *xback, xtmp; + boolean ret; + + /* display the back buffer first */ + ret = ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT); + /* force buffers to be updated in next validation call */ + xsurf->server_stamp++; + ximage_surface_notify_invalid(&xsurf->base); xfront = &xsurf->buffers[NATIVE_ATTACHMENT_FRONT_LEFT]; xback = &xsurf->buffers[NATIVE_ATTACHMENT_BACK_LEFT]; - /* draw the back buffer directly if there is no front buffer */ + /* skip swapping so that the front buffer is allocated only when needed */ if (!xfront->texture) - return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_BACK_LEFT); + return ret; - /* swap the buffers */ xtmp = *xfront; *xfront = *xback; *xback = xtmp; - /* the front/back textures are swapped */ - xsurf->sequence_number++; - - return ximage_surface_draw_buffer(nsurf, NATIVE_ATTACHMENT_FRONT_LEFT); -} - -static void -ximage_surface_update_geometry(struct native_surface *nsurf) -{ - struct ximage_surface *xsurf = ximage_surface(nsurf); - Status ok; - Window root; - int x, y; - unsigned int w, h, border, depth; - - /* pbuffer has fixed geometry */ - if (xsurf->type == XIMAGE_SURFACE_TYPE_PBUFFER) - return; - - ok = XGetGeometry(xsurf->xdpy->dpy, xsurf->drawable, - &root, &x, &y, &w, &h, &border, &depth); - if (ok) { - xsurf->width = w; - xsurf->height = h; - } + return ret; } static boolean @@ -300,44 +396,28 @@ ximage_surface_validate(struct native_surface *nsurf, uint attachment_mask, int *width, int *height) { struct ximage_surface *xsurf = ximage_surface(nsurf); - boolean new_buffers = FALSE; - int att; - ximage_surface_update_geometry(&xsurf->base); + if (xsurf->client_stamp != xsurf->server_stamp || + (xsurf->valid_mask & attachment_mask) != attachment_mask) { + if (!ximage_surface_update_buffers(&xsurf->base, attachment_mask)) + return FALSE; + } - for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { - struct ximage_buffer *xbuf = &xsurf->buffers[att]; - - /* delay the allocation */ - if (!native_attachment_mask_test(attachment_mask, att)) - continue; - - /* reallocate the texture */ - if (!xbuf->texture || - xsurf->width != xbuf->texture->width0 || - xsurf->height != xbuf->texture->height0) { - new_buffers = TRUE; - if (ximage_surface_alloc_buffer(&xsurf->base, att)) { - /* update ximage */ - if (xbuf->ximage) { - xbuf->ximage->width = xsurf->width; - xbuf->ximage->height = xsurf->height; - } - } - } + if (seq_num) + *seq_num = xsurf->client_stamp; - if (textures) { - textures[att] = NULL; - pipe_texture_reference(&textures[att], xbuf->texture); + if (textures) { + int att; + for (att = 0; att < NUM_NATIVE_ATTACHMENTS; att++) { + if (native_attachment_mask_test(attachment_mask, att)) { + struct ximage_buffer *xbuf = &xsurf->buffers[att]; + + textures[att] = NULL; + pipe_texture_reference(&textures[att], xbuf->texture); + } } } - /* increase the sequence number so that caller knows */ - if (new_buffers) - xsurf->sequence_number++; - - if (seq_num) - *seq_num = xsurf->sequence_number; if (width) *width = xsurf->width; if (height) @@ -405,6 +485,9 @@ ximage_display_create_surface(struct native_display *ndpy, return NULL; } + /* initialize the geometry */ + ximage_surface_update_buffers(&xsurf->base, 0x0); + for (i = 0; i < NUM_NATIVE_ATTACHMENTS; i++) { struct ximage_buffer *xbuf = &xsurf->buffers[i]; @@ -499,13 +582,13 @@ choose_format(const XVisualInfo *vinfo) /* TODO elaborate the formats */ switch (vinfo->depth) { case 32: - fmt = PIPE_FORMAT_A8R8G8B8_UNORM; + fmt = PIPE_FORMAT_B8G8R8A8_UNORM; break; case 24: - fmt = PIPE_FORMAT_X8R8G8B8_UNORM; + fmt = PIPE_FORMAT_B8G8R8X8_UNORM; break; case 16: - fmt = PIPE_FORMAT_R5G6B5_UNORM; + fmt = PIPE_FORMAT_B5G6R5_UNORM; break; default: fmt = PIPE_FORMAT_NONE; @@ -558,8 +641,8 @@ ximage_display_get_configs(struct native_display *ndpy, int *num_configs) xconf->base.stencil_format = PIPE_FORMAT_NONE; /* create the second config with depth/stencil buffer */ if (j == 1) { - xconf->base.depth_format = PIPE_FORMAT_S8Z24_UNORM; - xconf->base.stencil_format = PIPE_FORMAT_S8Z24_UNORM; + xconf->base.depth_format = PIPE_FORMAT_Z24S8_UNORM; + xconf->base.stencil_format = PIPE_FORMAT_Z24S8_UNORM; mode->depthBits = 24; mode->stencilBits = 8; mode->haveDepthBuffer = TRUE; @@ -607,13 +690,13 @@ ximage_display_is_pixmap_supported(struct native_display *ndpy, depth = x11_drawable_get_depth(xdpy->xscr, (Drawable) pix); switch (depth) { case 32: - fmt = PIPE_FORMAT_A8R8G8B8_UNORM; + fmt = PIPE_FORMAT_B8G8R8A8_UNORM; break; case 24: - fmt = PIPE_FORMAT_X8R8G8B8_UNORM; + fmt = PIPE_FORMAT_B8G8R8X8_UNORM; break; case 16: - fmt = PIPE_FORMAT_R5G6B5_UNORM; + fmt = PIPE_FORMAT_B5G6R5_UNORM; break; default: fmt = PIPE_FORMAT_NONE; @@ -623,6 +706,25 @@ ximage_display_is_pixmap_supported(struct native_display *ndpy, return (fmt == nconf->color_format); } +static int +ximage_display_get_param(struct native_display *ndpy, + enum native_param_type param) +{ + int val; + + switch (param) { + case NATIVE_PARAM_USE_NATIVE_BUFFER: + /* private buffers are allocated */ + val = FALSE; + break; + default: + val = 0; + break; + } + + return val; +} + static void ximage_display_destroy(struct native_display *ndpy) { @@ -641,7 +743,9 @@ ximage_display_destroy(struct native_display *ndpy) } struct native_display * -x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm) +x11_create_ximage_display(EGLNativeDisplayType dpy, + struct native_event_handler *event_handler, + boolean use_xshm) { struct ximage_display *xdpy; @@ -666,6 +770,8 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm) return NULL; } + xdpy->event_handler = event_handler; + xdpy->use_xshm = (use_xshm && x11_screen_support(xdpy->xscr, X11_SCREEN_EXTENSION_XSHM)); @@ -673,6 +779,7 @@ x11_create_ximage_display(EGLNativeDisplayType dpy, boolean use_xshm) xdpy->base.screen = softpipe_create_screen(xdpy->winsys); 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; diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.c b/src/gallium/state_trackers/egl/x11/x11_screen.c index d72bfc99d3..f409611484 100644 --- a/src/gallium/state_trackers/egl/x11/x11_screen.c +++ b/src/gallium/state_trackers/egl/x11/x11_screen.c @@ -39,6 +39,9 @@ #include "glxinit.h" struct x11_screen { + /* dummy base class */ + struct __GLXDRIdisplayRec base; + Display *dpy; int number; @@ -53,6 +56,9 @@ struct x11_screen { char *dri_device; int dri_fd; + x11_drawable_invalidate_buffers dri_invalidate_buffers; + void *dri_user_data; + XVisualInfo *visuals; int num_visuals; @@ -98,6 +104,8 @@ x11_screen_destroy(struct x11_screen *xscr) Xfree(xscr->dri_device); /* xscr->glx_dpy will be destroyed with the X display */ + if (xscr->glx_dpy) + xscr->glx_dpy->dri2Display = NULL; if (xscr->visuals) XFree(xscr->visuals); @@ -247,24 +255,25 @@ x11_screen_get_glx_visuals(struct x11_screen *xscr) : NULL; } -static boolean -x11_screen_is_driver_equal(struct x11_screen *xscr, const char *driver) -{ - return (strcmp(xscr->dri_driver, driver) == 0); -} - /** * Probe the screen for the DRI2 driver name. */ const char * -x11_screen_probe_dri2(struct x11_screen *xscr) +x11_screen_probe_dri2(struct x11_screen *xscr, int *major, int *minor) { + if (!x11_screen_init_dri2(xscr)) + return NULL; + /* get the driver name and the device name */ if (!xscr->dri_driver) { if (!DRI2Connect(xscr->dpy, RootWindow(xscr->dpy, xscr->number), &xscr->dri_driver, &xscr->dri_device)) xscr->dri_driver = xscr->dri_device = NULL; } + if (major) + *major = xscr->dri_major; + if (minor) + *minor = xscr->dri_minor; return xscr->dri_driver; } @@ -274,21 +283,17 @@ x11_screen_probe_dri2(struct x11_screen *xscr) * descriptor will be closed automatically when the screen is destoryed. */ int -x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver) +x11_screen_enable_dri2(struct x11_screen *xscr, + x11_drawable_invalidate_buffers invalidate_buffers, + void *user_data) { if (xscr->dri_fd < 0) { int fd; drm_magic_t magic; /* get the driver name and the device name first */ - if (!x11_screen_probe_dri2(xscr)) - return -1; - - if (!x11_screen_is_driver_equal(xscr, driver)) { - _eglLog(_EGL_WARNING, "Driver mismatch: %s != %s", - xscr->dri_driver, driver); + if (!x11_screen_probe_dri2(xscr, NULL, NULL)) return -1; - } fd = open(xscr->dri_device, O_RDWR); if (fd < 0) { @@ -310,6 +315,22 @@ x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver) return -1; } + if (!x11_screen_init_glx(xscr)) { + _eglLog(_EGL_WARNING, "failed to initialize GLX"); + close(fd); + return -1; + } + if (xscr->glx_dpy->dri2Display) { + _eglLog(_EGL_WARNING, + "display is already managed by another x11 screen"); + close(fd); + return -1; + } + + xscr->glx_dpy->dri2Display = (__GLXDRIdisplay *) xscr; + xscr->dri_invalidate_buffers = invalidate_buffers; + xscr->dri_user_data = user_data; + xscr->dri_fd = fd; } @@ -451,3 +472,20 @@ x11_context_modes_count(const __GLcontextModes *modes) count++; return count; } + +/** + * This is called from src/glx/dri2.c. + */ +void +dri2InvalidateBuffers(Display *dpy, XID drawable) +{ + __GLXdisplayPrivate *priv = __glXInitialize(dpy); + struct x11_screen *xscr = NULL; + + if (priv && priv->dri2Display) + xscr = (struct x11_screen *) priv->dri2Display; + if (!xscr || !xscr->dri_invalidate_buffers) + return; + + xscr->dri_invalidate_buffers(xscr, drawable, xscr->dri_user_data); +} diff --git a/src/gallium/state_trackers/egl/x11/x11_screen.h b/src/gallium/state_trackers/egl/x11/x11_screen.h index 5432858ac3..37e8d5a40e 100644 --- a/src/gallium/state_trackers/egl/x11/x11_screen.h +++ b/src/gallium/state_trackers/egl/x11/x11_screen.h @@ -48,6 +48,10 @@ struct x11_drawable_buffer { struct x11_screen; +typedef void (*x11_drawable_invalidate_buffers)(struct x11_screen *xscr, + Drawable drawable, + void *user_data); + struct x11_screen * x11_screen_create(Display *dpy, int screen); @@ -71,10 +75,12 @@ const __GLcontextModes * x11_screen_get_glx_visuals(struct x11_screen *xscr); const char * -x11_screen_probe_dri2(struct x11_screen *xscr); +x11_screen_probe_dri2(struct x11_screen *xscr, int *major, int *minor); int -x11_screen_enable_dri2(struct x11_screen *xscr, const char *driver); +x11_screen_enable_dri2(struct x11_screen *xscr, + x11_drawable_invalidate_buffers invalidate_buffers, + void *user_data); __GLcontextModes * x11_context_modes_create(unsigned count); diff --git a/src/gallium/state_trackers/glx/xlib/glx_api.c b/src/gallium/state_trackers/glx/xlib/glx_api.c index 3caf56e924..08bf624b5c 100644 --- a/src/gallium/state_trackers/glx/xlib/glx_api.c +++ b/src/gallium/state_trackers/glx/xlib/glx_api.c @@ -280,7 +280,7 @@ default_depth_bits(void) int zBits; const char *zEnv = _mesa_getenv("MESA_GLX_DEPTH_BITS"); if (zEnv) - zBits = _mesa_atoi(zEnv); + zBits = atoi(zEnv); else zBits = DEFAULT_SOFTWARE_DEPTH_BITS; return zBits; @@ -292,7 +292,7 @@ default_alpha_bits(void) int aBits; const char *aEnv = _mesa_getenv("MESA_GLX_ALPHA_BITS"); if (aEnv) - aBits = _mesa_atoi(aEnv); + aBits = atoi(aEnv); else aBits = 0; return aBits; @@ -442,17 +442,17 @@ get_env_visual(Display *dpy, int scr, const char *varname) return NULL; } - _mesa_strncpy( value, _mesa_getenv(varname), 100 ); + strncpy( value, _mesa_getenv(varname), 100 ); value[99] = 0; sscanf( value, "%s %d", type, &depth ); - if (_mesa_strcmp(type,"TrueColor")==0) xclass = TrueColor; - else if (_mesa_strcmp(type,"DirectColor")==0) xclass = DirectColor; - else if (_mesa_strcmp(type,"PseudoColor")==0) xclass = PseudoColor; - else if (_mesa_strcmp(type,"StaticColor")==0) xclass = StaticColor; - else if (_mesa_strcmp(type,"GrayScale")==0) xclass = GrayScale; - else if (_mesa_strcmp(type,"StaticGray")==0) xclass = StaticGray; + if (strcmp(type,"TrueColor")==0) xclass = TrueColor; + else if (strcmp(type,"DirectColor")==0) xclass = DirectColor; + else if (strcmp(type,"PseudoColor")==0) xclass = PseudoColor; + else if (strcmp(type,"StaticColor")==0) xclass = StaticColor; + else if (strcmp(type,"GrayScale")==0) xclass = GrayScale; + else if (strcmp(type,"StaticGray")==0) xclass = StaticGray; if (xclass>-1 && depth>0) { vis = get_visual( dpy, scr, depth, xclass ); @@ -689,6 +689,8 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig ) int desiredVisualID = -1; int numAux = 0; + xmesa_init(); + parselist = list; while (*parselist) { @@ -941,9 +943,6 @@ choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig ) /* give the visual some useful GLX attributes */ double_flag = GL_TRUE; rgb_flag = GL_TRUE; - depth_size = default_depth_bits(); - stencil_size = STENCIL_BITS; - /* XXX accum??? */ } } else if (level==0) { @@ -1018,9 +1017,9 @@ glXChooseVisual( Display *dpy, int screen, int *list ) xmvis = choose_visual(dpy, screen, list, GL_FALSE); if (xmvis) { /* create a new vishandle - the cached one may be stale */ - xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo)); + xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo)); if (xmvis->vishandle) { - _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); + memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); } return xmvis->vishandle; } @@ -1055,7 +1054,7 @@ glXCreateContext( Display *dpy, XVisualInfo *visinfo, xmvis = create_glx_visual( dpy, visinfo ); if (!xmvis) { /* unusable visual */ - _mesa_free(glxCtx); + free(glxCtx); return NULL; } } @@ -1063,7 +1062,7 @@ glXCreateContext( Display *dpy, XVisualInfo *visinfo, glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx ? shareCtx->xmesaContext : NULL); if (!glxCtx->xmesaContext) { - _mesa_free(glxCtx); + free(glxCtx); return NULL; } @@ -1336,7 +1335,7 @@ glXDestroyContext( Display *dpy, GLXContext ctx ) MakeCurrent_PrevReadBuffer = 0; XMesaDestroyContext( glxCtx->xmesaContext ); XMesaGarbageCollect(); - _mesa_free(glxCtx); + free(glxCtx); } @@ -1679,8 +1678,8 @@ PUBLIC const char * glXQueryServerString( Display *dpy, int screen, int name ) { static char version[1000]; - _mesa_sprintf(version, "%d.%d %s", - SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, MESA_GLX_VERSION); + sprintf(version, "%d.%d %s", + SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, MESA_GLX_VERSION); (void) dpy; (void) screen; @@ -1704,8 +1703,8 @@ PUBLIC const char * glXGetClientString( Display *dpy, int name ) { static char version[1000]; - _mesa_sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, - CLIENT_MINOR_VERSION, MESA_GLX_VERSION); + sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, + CLIENT_MINOR_VERSION, MESA_GLX_VERSION); (void) dpy; @@ -1755,7 +1754,7 @@ glXGetFBConfigs( Display *dpy, int screen, int *nelements ) visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements); if (*nelements > 0) { XMesaVisual *results; - results = (XMesaVisual *) _mesa_malloc(*nelements * sizeof(XMesaVisual)); + results = (XMesaVisual *) malloc(*nelements * sizeof(XMesaVisual)); if (!results) { *nelements = 0; return NULL; @@ -1782,7 +1781,7 @@ glXChooseFBConfig( Display *dpy, int screen, xmvis = choose_visual(dpy, screen, attribList, GL_TRUE); if (xmvis) { - GLXFBConfig *config = (GLXFBConfig *) _mesa_malloc(sizeof(XMesaVisual)); + GLXFBConfig *config = (GLXFBConfig *) malloc(sizeof(XMesaVisual)); if (!config) { *nitems = 0; return NULL; @@ -1807,9 +1806,9 @@ glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) return xmvis->vishandle; #else /* create a new vishandle - the cached one may be stale */ - xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo)); + xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo)); if (xmvis->vishandle) { - _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); + memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); } return xmvis->vishandle; #endif @@ -2112,7 +2111,7 @@ glXCreateNewContext( Display *dpy, GLXFBConfig config, glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx ? shareCtx->xmesaContext : NULL); if (!glxCtx->xmesaContext) { - _mesa_free(glxCtx); + free(glxCtx); return NULL; } @@ -2332,7 +2331,7 @@ glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_ glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx ? shareCtx->xmesaContext : NULL); if (!glxCtx->xmesaContext) { - _mesa_free(glxCtx); + free(glxCtx); return NULL; } diff --git a/src/gallium/state_trackers/glx/xlib/glx_usefont.c b/src/gallium/state_trackers/glx/xlib/glx_usefont.c index e502198b20..8903b0e6cb 100644 --- a/src/gallium/state_trackers/glx/xlib/glx_usefont.c +++ b/src/gallium/state_trackers/glx/xlib/glx_usefont.c @@ -343,7 +343,7 @@ glXUseXFont(Font font, int first, int count, int listbase) glNewList(list, GL_COMPILE); if (valid && (bm_width > 0) && (bm_height > 0)) { - MEMSET(bm, '\0', bm_width * bm_height); + memset(bm, '\0', bm_width * bm_height); fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm); glBitmap(width, height, x0, y0, dx, dy, bm); diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c index fb314f3b52..217bdeff75 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.c +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -175,7 +175,7 @@ bits_per_pixel( XMesaVisual xmv ) /* grab the bits/pixel value */ bitsPerPixel = img->bits_per_pixel; /* free the XImage */ - _mesa_free( img->data ); + free( img->data ); img->data = NULL; XDestroyImage( img ); return bitsPerPixel; @@ -274,10 +274,10 @@ choose_pixel_format(XMesaVisual v) && v->BitsPerPixel == 32) { if (native_byte_order) { /* no byteswapping needed */ - return 0 /* PIXEL_FORMAT_U_A8_B8_G8_R8 */; + return PIPE_FORMAT_R8G8B8A8_UNORM; } else { - return PIPE_FORMAT_R8G8B8A8_UNORM; + return PIPE_FORMAT_A8B8G8R8_UNORM; } } else if ( GET_REDMASK(v) == 0xff0000 @@ -286,10 +286,10 @@ choose_pixel_format(XMesaVisual v) && v->BitsPerPixel == 32) { if (native_byte_order) { /* no byteswapping needed */ - return PIPE_FORMAT_A8R8G8B8_UNORM; + return PIPE_FORMAT_B8G8R8A8_UNORM; } else { - return PIPE_FORMAT_B8G8R8A8_UNORM; + return PIPE_FORMAT_A8R8G8B8_UNORM; } } else if ( GET_REDMASK(v) == 0x0000ff00 @@ -298,10 +298,10 @@ choose_pixel_format(XMesaVisual v) && v->BitsPerPixel == 32) { if (native_byte_order) { /* no byteswapping needed */ - return PIPE_FORMAT_B8G8R8A8_UNORM; + return PIPE_FORMAT_A8R8G8B8_UNORM; } else { - return PIPE_FORMAT_A8R8G8B8_UNORM; + return PIPE_FORMAT_B8G8R8A8_UNORM; } } else if ( GET_REDMASK(v) == 0xf800 @@ -310,7 +310,7 @@ choose_pixel_format(XMesaVisual v) && native_byte_order && v->BitsPerPixel == 16) { /* 5-6-5 RGB */ - return PIPE_FORMAT_R5G6B5_UNORM; + return PIPE_FORMAT_B5G6R5_UNORM; } assert(0); @@ -319,6 +319,51 @@ choose_pixel_format(XMesaVisual v) +/** + * Query the default gallium screen for a Z/Stencil format that + * at least matches the given depthBits and stencilBits. + */ +static void +xmesa_choose_z_stencil_format(int depthBits, int stencilBits, + enum pipe_format *depthFormat, + enum pipe_format *stencilFormat) +{ + const enum pipe_texture_target target = PIPE_TEXTURE_2D; + const unsigned tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL; + const unsigned geom_flags = (PIPE_TEXTURE_GEOM_NON_SQUARE | + PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO); + static enum pipe_format formats[] = { + PIPE_FORMAT_S8Z24_UNORM, + PIPE_FORMAT_Z24S8_UNORM, + PIPE_FORMAT_Z16_UNORM, + PIPE_FORMAT_Z32_UNORM + }; + int i; + + assert(screen); + + *depthFormat = *stencilFormat = PIPE_FORMAT_NONE; + + /* search for supported format */ + for (i = 0; i < Elements(formats); i++) { + if (screen->is_format_supported(screen, formats[i], + target, tex_usage, geom_flags)) { + *depthFormat = formats[i]; + break; + } + } + + if (stencilBits) { + *stencilFormat = *depthFormat; + } + + /* XXX we should check that he chosen format has at least as many bits + * as what was requested. + */ +} + + + /**********************************************************************/ /***** Linked list of XMesaBuffers *****/ /**********************************************************************/ @@ -361,34 +406,9 @@ create_xmesa_buffer(Drawable d, BufferType type, /* determine PIPE_FORMATs for buffers */ colorFormat = choose_pixel_format(vis); - if (vis->mesa_visual.depthBits == 0) - depthFormat = PIPE_FORMAT_NONE; -#ifdef GALLIUM_CELL /* XXX temporary for Cell! */ - else - depthFormat = PIPE_FORMAT_S8Z24_UNORM; -#else - else if (vis->mesa_visual.depthBits <= 16) - depthFormat = PIPE_FORMAT_Z16_UNORM; - else if (vis->mesa_visual.depthBits <= 24) - depthFormat = PIPE_FORMAT_S8Z24_UNORM; - else - depthFormat = PIPE_FORMAT_Z32_UNORM; -#endif - - if (vis->mesa_visual.stencilBits == 8) { - if (depthFormat == PIPE_FORMAT_S8Z24_UNORM) - stencilFormat = depthFormat; - else - stencilFormat = PIPE_FORMAT_S8_UNORM; - } - else { - /* no stencil */ - stencilFormat = PIPE_FORMAT_NONE; - if (depthFormat == PIPE_FORMAT_S8Z24_UNORM) { - /* use 24-bit Z, undefined stencil channel */ - depthFormat = PIPE_FORMAT_X8Z24_UNORM; - } - } + xmesa_choose_z_stencil_format(vis->mesa_visual.depthBits, + vis->mesa_visual.stencilBits, + &depthFormat, &stencilFormat); get_drawable_size(vis->display, d, &width, &height); @@ -550,10 +570,10 @@ initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b, * reports bugs. */ if (_mesa_getenv("MESA_INFO")) { - _mesa_printf("X/Mesa visual = %p\n", (void *) v); - _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level); - _mesa_printf("X/Mesa depth = %d\n", v->visinfo->depth); - _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); + printf("X/Mesa visual = %p\n", (void *) v); + printf("X/Mesa level = %d\n", v->mesa_visual.level); + printf("X/Mesa depth = %d\n", v->visinfo->depth); + printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); } if (b && window) { @@ -653,6 +673,8 @@ XMesaVisual XMesaCreateVisual( Display *display, XMesaVisual v; GLint red_bits, green_bits, blue_bits, alpha_bits; + xmesa_init(); + /* For debugging only */ if (_mesa_getenv("MESA_XSYNC")) { /* This makes debugging X easier. @@ -669,16 +691,16 @@ XMesaVisual XMesaCreateVisual( Display *display, v->display = display; - /* Save a copy of the XVisualInfo struct because the user may X_mesa_free() + /* Save a copy of the XVisualInfo struct because the user may Xfree() * the struct but we may need some of the information contained in it * at a later time. */ v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo)); if (!v->visinfo) { - _mesa_free(v); + free(v); return NULL; } - MEMCPY(v->visinfo, visinfo, sizeof(*visinfo)); + memcpy(v->visinfo, visinfo, sizeof(*visinfo)); v->ximage_flag = ximage_flag; @@ -724,10 +746,9 @@ XMesaVisual XMesaCreateVisual( Display *display, } _mesa_initialize_visual( &v->mesa_visual, - rgb_flag, db_flag, stereo_flag, + db_flag, stereo_flag, red_bits, green_bits, blue_bits, alpha_bits, - v->mesa_visual.indexBits, depth_size, stencil_size, accum_red_size, accum_green_size, @@ -743,11 +764,26 @@ XMesaVisual XMesaCreateVisual( Display *display, PUBLIC void XMesaDestroyVisual( XMesaVisual v ) { - _mesa_free(v->visinfo); - _mesa_free(v); + free(v->visinfo); + free(v); } +/** + * Do one-time initializations. + */ +void +xmesa_init(void) +{ + static GLboolean firstTime = GL_TRUE; + if (firstTime) { + pipe_mutex_init(_xmesa_lock); + _screen = driver.create_pipe_screen(); + screen = trace_screen_create( _screen ); + firstTime = GL_FALSE; + } +} + /** * Create a new XMesaContext. @@ -759,18 +795,12 @@ void XMesaDestroyVisual( XMesaVisual v ) PUBLIC XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) { - static GLboolean firstTime = GL_TRUE; struct pipe_context *pipe = NULL; XMesaContext c; GLcontext *mesaCtx; uint pf; - if (firstTime) { - pipe_mutex_init(_xmesa_lock); - _screen = driver.create_pipe_screen(); - screen = trace_screen_create( _screen ); - firstTime = GL_FALSE; - } + xmesa_init(); /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */ c = (XMesaContext) CALLOC_STRUCT(xmesa_context); @@ -811,7 +841,7 @@ fail: else if (pipe) pipe->destroy(pipe); - _mesa_free(c); + free(c); return NULL; } @@ -828,7 +858,7 @@ void XMesaDestroyContext( XMesaContext c ) screen->destroy(screen); */ - _mesa_free(c); + free(c); } @@ -1148,6 +1178,7 @@ void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) if (!surf_front || !surf_back) return; + assert(pipe); pipe->surface_copy(pipe, surf_front, x, y, /* dest */ surf_back, x, y, /* src */ diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.h b/src/gallium/state_trackers/glx/xlib/xm_api.h index 63a329cbe0..004cb260dc 100644 --- a/src/gallium/state_trackers/glx/xlib/xm_api.h +++ b/src/gallium/state_trackers/glx/xlib/xm_api.h @@ -367,6 +367,9 @@ xmesa_buffer(GLframebuffer *fb) extern void +xmesa_init(void); + +extern void xmesa_delete_framebuffer(struct gl_framebuffer *fb); extern XMesaBuffer diff --git a/src/gallium/state_trackers/python/README b/src/gallium/state_trackers/python/README index 4a06073024..e24a262aba 100644 --- a/src/gallium/state_trackers/python/README +++ b/src/gallium/state_trackers/python/README @@ -18,7 +18,7 @@ On a Windows machine ensure the swig command is in your PATH. Invoke scons on the top dir as - scons debug=yes statetrackers=python drivers=softpipe,trace winsys=none + scons debug=yes statetrackers=python drivers=softpipe winsys=none To use it set PYTHONPATH appropriately, e.g, in Linux do: diff --git a/src/gallium/state_trackers/python/p_state.i b/src/gallium/state_trackers/python/p_state.i index 5afe4d4908..eda77b56f8 100644 --- a/src/gallium/state_trackers/python/p_state.i +++ b/src/gallium/state_trackers/python/p_state.i @@ -69,7 +69,7 @@ pipe_blend_state(const char *STRING, unsigned LENGTH) { struct pipe_blend_state *state; - state = CALLOC_STRUCT(pipe_framebuffer_state); + state = CALLOC_STRUCT(pipe_blend_state); if (state) { LENGTH = MIN2(sizeof *state, LENGTH); memcpy(state, STRING, LENGTH); diff --git a/src/gallium/state_trackers/python/st_device.c b/src/gallium/state_trackers/python/st_device.c index a3798a5521..45e7841750 100644 --- a/src/gallium/state_trackers/python/st_device.c +++ b/src/gallium/state_trackers/python/st_device.c @@ -244,7 +244,7 @@ st_context_create(struct st_device *st_dev) memset( &templat, 0, sizeof( templat ) ); templat.target = PIPE_TEXTURE_2D; - templat.format = PIPE_FORMAT_A8R8G8B8_UNORM; + templat.format = PIPE_FORMAT_B8G8R8A8_UNORM; templat.width0 = 1; templat.height0 = 1; templat.depth0 = 1; diff --git a/src/gallium/state_trackers/python/st_sample.c b/src/gallium/state_trackers/python/st_sample.c index 32a6551a87..e180815346 100644 --- a/src/gallium/state_trackers/python/st_sample.c +++ b/src/gallium/state_trackers/python/st_sample.c @@ -485,7 +485,7 @@ st_sample_generic_pixel_block(enum pipe_format format, w, h, rgba, rgba_stride); - if(format == PIPE_FORMAT_YCBCR || format == PIPE_FORMAT_YCBCR_REV) { + if(format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) { for(y = 0; y < h; ++y) { for(x = 0; x < w; ++x) { for(ch = 0; ch < 4; ++ch) { diff --git a/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-abs.png b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-abs.png Binary files differnew file mode 100644 index 0000000000..c947a7b881 --- /dev/null +++ b/src/gallium/state_trackers/python/tests/regress/fragment-shader/frag-abs.png diff --git a/src/gallium/state_trackers/vega/Makefile b/src/gallium/state_trackers/vega/Makefile index 037d8dc911..7f04b2aa83 100644 --- a/src/gallium/state_trackers/vega/Makefile +++ b/src/gallium/state_trackers/vega/Makefile @@ -53,7 +53,7 @@ INCLUDE_DIRS = \ .c.o: - $(CC) -c $(INCLUDE_DIRS) $(DEFINES) $(CFLAGS) $< -o $@ + $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@ default: depend $(TOP)/$(LIB_DIR)/$(VG_LIB_NAME) diff --git a/src/gallium/state_trackers/vega/api_filters.c b/src/gallium/state_trackers/vega/api_filters.c index 20c72c1ff5..02248ad433 100644 --- a/src/gallium/state_trackers/vega/api_filters.c +++ b/src/gallium/state_trackers/vega/api_filters.c @@ -67,7 +67,7 @@ static INLINE struct pipe_texture *create_texture_1d(struct vg_context *ctx, memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_1D; - templ.format = PIPE_FORMAT_A8R8G8B8_UNORM; + templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; templ.last_level = 0; templ.width0 = color_data_len; templ.height0 = 1; diff --git a/src/gallium/state_trackers/vega/image.c b/src/gallium/state_trackers/vega/image.c index 2e10965be4..41c979bfec 100644 --- a/src/gallium/state_trackers/vega/image.c +++ b/src/gallium/state_trackers/vega/image.c @@ -48,16 +48,16 @@ static enum pipe_format vg_format_to_pipe(VGImageFormat format) { switch(format) { case VG_sRGB_565: - return PIPE_FORMAT_R5G6B5_UNORM; + return PIPE_FORMAT_B5G6R5_UNORM; case VG_sRGBA_5551: - return PIPE_FORMAT_A1R5G5B5_UNORM; + return PIPE_FORMAT_B5G5R5A1_UNORM; case VG_sRGBA_4444: - return PIPE_FORMAT_A4R4G4B4_UNORM; + return PIPE_FORMAT_B4G4R4A4_UNORM; case VG_sL_8: case VG_lL_8: return PIPE_FORMAT_L8_UNORM; case VG_BW_1: - return PIPE_FORMAT_A8R8G8B8_UNORM; + return PIPE_FORMAT_B8G8R8A8_UNORM; case VG_A_8: return PIPE_FORMAT_A8_UNORM; #ifdef OPENVG_VERSION_1_1 @@ -66,7 +66,7 @@ static enum pipe_format vg_format_to_pipe(VGImageFormat format) return PIPE_FORMAT_A8_UNORM; #endif default: - return PIPE_FORMAT_A8R8G8B8_UNORM; + return PIPE_FORMAT_B8G8R8A8_UNORM; } } diff --git a/src/gallium/state_trackers/vega/mask.c b/src/gallium/state_trackers/vega/mask.c index 467b95b751..839dc19a3b 100644 --- a/src/gallium/state_trackers/vega/mask.c +++ b/src/gallium/state_trackers/vega/mask.c @@ -488,7 +488,7 @@ struct vg_mask_layer * mask_layer_create(VGint width, VGint height) memset(&pt, 0, sizeof(pt)); pt.target = PIPE_TEXTURE_2D; - pt.format = PIPE_FORMAT_A8R8G8B8_UNORM; + pt.format = PIPE_FORMAT_B8G8R8A8_UNORM; pt.last_level = 0; pt.width0 = width; pt.height0 = height; diff --git a/src/gallium/state_trackers/vega/paint.c b/src/gallium/state_trackers/vega/paint.c index 3405d635f0..cdb87d3bf6 100644 --- a/src/gallium/state_trackers/vega/paint.c +++ b/src/gallium/state_trackers/vega/paint.c @@ -151,7 +151,7 @@ static INLINE struct pipe_texture *create_gradient_texture(struct vg_paint *p) memset(&templ, 0, sizeof(templ)); templ.target = PIPE_TEXTURE_1D; - templ.format = PIPE_FORMAT_A8R8G8B8_UNORM; + templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; templ.last_level = 0; templ.width0 = 1024; templ.height0 = 1; @@ -639,9 +639,6 @@ VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **sa } break; default: - samplers[0] = &paint->pattern.sampler; /* dummy */ - textures[0] = 0; - return 0; break; } return 0; diff --git a/src/gallium/state_trackers/vega/vg_tracker.c b/src/gallium/state_trackers/vega/vg_tracker.c index a94dfb160c..57d3baad7f 100644 --- a/src/gallium/state_trackers/vega/vg_tracker.c +++ b/src/gallium/state_trackers/vega/vg_tracker.c @@ -51,7 +51,7 @@ create_texture(struct pipe_context *pipe, enum pipe_format format, templ.format = format; } else { - templ.format = PIPE_FORMAT_A8R8G8B8_UNORM; + templ.format = PIPE_FORMAT_B8G8R8A8_UNORM; } templ.target = PIPE_TEXTURE_2D; @@ -186,7 +186,7 @@ struct st_framebuffer * st_create_framebuffer(const void *visual, if (stencilFormat == depthFormat) stfb->dsrb = st_new_renderbuffer_fb(stencilFormat); else - stfb->dsrb = st_new_renderbuffer_fb(PIPE_FORMAT_S8Z24_UNORM); + stfb->dsrb = st_new_renderbuffer_fb(PIPE_FORMAT_Z24S8_UNORM); /*### currently we always allocate it but it's possible it's not necessary if EGL_ALPHA_MASK_SIZE was 0 @@ -209,12 +209,12 @@ static void setup_new_alpha_mask(struct vg_context *ctx, struct pipe_texture *old_texture = stfb->alpha_mask; /* - we use PIPE_FORMAT_A8R8G8B8_UNORM because we want to render to + we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to this texture and use it as a sampler, so while this wastes some space it makes both of those a lot simpler */ stfb->alpha_mask = - create_texture(pipe, PIPE_FORMAT_A8R8G8B8_UNORM, width, height); + create_texture(pipe, PIPE_FORMAT_B8G8R8A8_UNORM, width, height); if (!stfb->alpha_mask) { if (old_texture) @@ -327,7 +327,7 @@ void st_resize_framebuffer(struct st_framebuffer *stfb, setup_new_alpha_mask(ctx, stfb, width, height); pipe_texture_reference( &stfb->blend_texture, NULL ); - stfb->blend_texture = create_texture(ctx->pipe, PIPE_FORMAT_A8R8G8B8_UNORM, + stfb->blend_texture = create_texture(ctx->pipe, PIPE_FORMAT_B8G8R8A8_UNORM, width, height); } diff --git a/src/gallium/state_trackers/wgl/stw_device.c b/src/gallium/state_trackers/wgl/stw_device.c index e5fa6ac8eb..472a2a5379 100644 --- a/src/gallium/state_trackers/wgl/stw_device.c +++ b/src/gallium/state_trackers/wgl/stw_device.c @@ -47,7 +47,6 @@ #ifdef WIN32_THREADS extern _glthread_Mutex OneTimeLock; -extern void FreeAllTSD(void); #endif @@ -183,7 +182,8 @@ stw_cleanup(void) #ifdef WIN32_THREADS _glthread_DESTROY_MUTEX(OneTimeLock); - FreeAllTSD(); + + _glapi_destroy_multithread(); #endif #ifdef DEBUG diff --git a/src/gallium/state_trackers/wgl/stw_pixelformat.c b/src/gallium/state_trackers/wgl/stw_pixelformat.c index b750b03695..bc28f31ed1 100644 --- a/src/gallium/state_trackers/wgl/stw_pixelformat.c +++ b/src/gallium/state_trackers/wgl/stw_pixelformat.c @@ -74,17 +74,17 @@ struct stw_pf_depth_info static const struct stw_pf_color_info stw_pf_color[] = { /* no-alpha */ - { PIPE_FORMAT_X8R8G8B8_UNORM, { 8, 8, 8, 0}, {16, 8, 0, 0} }, - { PIPE_FORMAT_B8G8R8X8_UNORM, { 8, 8, 8, 0}, { 8, 16, 24, 0} }, - { PIPE_FORMAT_R5G6B5_UNORM, { 5, 6, 5, 0}, {11, 5, 0, 0} }, + { PIPE_FORMAT_B8G8R8X8_UNORM, { 8, 8, 8, 0}, {16, 8, 0, 0} }, + { PIPE_FORMAT_X8R8G8B8_UNORM, { 8, 8, 8, 0}, { 8, 16, 24, 0} }, + { PIPE_FORMAT_B5G6R5_UNORM, { 5, 6, 5, 0}, {11, 5, 0, 0} }, /* alpha */ - { PIPE_FORMAT_A8R8G8B8_UNORM, { 8, 8, 8, 8}, {16, 8, 0, 24} }, - { PIPE_FORMAT_B8G8R8A8_UNORM, { 8, 8, 8, 8}, { 8, 16, 24, 0} }, + { PIPE_FORMAT_B8G8R8A8_UNORM, { 8, 8, 8, 8}, {16, 8, 0, 24} }, + { PIPE_FORMAT_A8R8G8B8_UNORM, { 8, 8, 8, 8}, { 8, 16, 24, 0} }, #if 0 - { PIPE_FORMAT_A2B10G10R10_UNORM, {10, 10, 10, 2}, { 0, 10, 20, 30} }, + { PIPE_FORMAT_R10G10B10A2_UNORM, {10, 10, 10, 2}, { 0, 10, 20, 30} }, #endif - { PIPE_FORMAT_A1R5G5B5_UNORM, { 5, 5, 5, 1}, {10, 5, 0, 15} }, - { PIPE_FORMAT_A4R4G4B4_UNORM, { 4, 4, 4, 4}, {16, 4, 0, 12} } + { PIPE_FORMAT_B5G5R5A1_UNORM, { 5, 5, 5, 1}, {10, 5, 0, 15} }, + { PIPE_FORMAT_B4G4R4A4_UNORM, { 4, 4, 4, 4}, {16, 4, 0, 12} } }; @@ -92,12 +92,12 @@ static const struct stw_pf_depth_info stw_pf_depth_stencil[] = { /* pure depth */ { PIPE_FORMAT_Z32_UNORM, {32, 0} }, - { PIPE_FORMAT_Z24X8_UNORM, {24, 0} }, { PIPE_FORMAT_X8Z24_UNORM, {24, 0} }, + { PIPE_FORMAT_Z24X8_UNORM, {24, 0} }, { PIPE_FORMAT_Z16_UNORM, {16, 0} }, /* combined depth-stencil */ - { PIPE_FORMAT_S8Z24_UNORM, {24, 8} }, - { PIPE_FORMAT_Z24S8_UNORM, {24, 8} } + { PIPE_FORMAT_Z24S8_UNORM, {24, 8} }, + { PIPE_FORMAT_S8Z24_UNORM, {24, 8} } }; @@ -271,14 +271,12 @@ stw_pixelformat_visual(GLvisual *visual, memset(visual, 0, sizeof *visual); _mesa_initialize_visual( visual, - (pfi->pfd.iPixelType == PFD_TYPE_RGBA) ? GL_TRUE : GL_FALSE, (pfi->pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE, (pfi->pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE, pfi->pfd.cRedBits, pfi->pfd.cGreenBits, pfi->pfd.cBlueBits, pfi->pfd.cAlphaBits, - (pfi->pfd.iPixelType == PFD_TYPE_COLORINDEX) ? pfi->pfd.cColorBits : 0, pfi->pfd.cDepthBits, pfi->pfd.cStencilBits, pfi->pfd.cAccumRedBits, diff --git a/src/gallium/state_trackers/xorg/xorg_crtc.c b/src/gallium/state_trackers/xorg/xorg_crtc.c index 221ce772af..44f7da0f96 100644 --- a/src/gallium/state_trackers/xorg/xorg_crtc.c +++ b/src/gallium/state_trackers/xorg/xorg_crtc.c @@ -197,25 +197,26 @@ crtc_load_cursor_argb_ga3d(xf86CrtcPtr crtc, CARD32 * image) if (!crtcp->cursor_tex) { struct pipe_texture templat; - unsigned pitch; + struct winsys_handle whandle; memset(&templat, 0, sizeof(templat)); templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; - templat.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; + templat.tex_usage |= PIPE_TEXTURE_USAGE_SCANOUT; templat.target = PIPE_TEXTURE_2D; templat.last_level = 0; templat.depth0 = 1; - templat.format = PIPE_FORMAT_A8R8G8B8_UNORM; + templat.format = PIPE_FORMAT_B8G8R8A8_UNORM; templat.width0 = 64; templat.height0 = 64; + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_KMS; + crtcp->cursor_tex = ms->screen->texture_create(ms->screen, &templat); - ms->api->local_handle_from_texture(ms->api, - ms->screen, - crtcp->cursor_tex, - &pitch, - &crtcp->cursor_handle); + ms->screen->texture_get_handle(ms->screen, crtcp->cursor_tex, &whandle); + + crtcp->cursor_handle = whandle.handle; } transfer = ms->screen->get_tex_transfer(ms->screen, crtcp->cursor_tex, diff --git a/src/gallium/state_trackers/xorg/xorg_dri2.c b/src/gallium/state_trackers/xorg/xorg_dri2.c index 5b67392435..f23e4c6cc7 100644 --- a/src/gallium/state_trackers/xorg/xorg_dri2.c +++ b/src/gallium/state_trackers/xorg/xorg_dri2.c @@ -67,7 +67,7 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form struct exa_pixmap_priv *exa_priv; BufferPrivatePtr private = buffer->driverPrivate; PixmapPtr pPixmap; - unsigned stride, handle; + struct winsys_handle whandle; if (pDraw->type == DRAWABLE_PIXMAP) pPixmap = (PixmapPtr) pDraw; @@ -75,6 +75,7 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form pPixmap = (*pScreen->GetWindowPixmap)((WindowPtr) pDraw); exa_priv = exaGetPixmapDriverPrivate(pPixmap); + switch (buffer->attachment) { default: if (buffer->attachment != DRI2BufferFakeFrontLeft || @@ -116,19 +117,19 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form break; default: template.format = ms->ds_depth_bits_last ? - PIPE_FORMAT_X8Z24_UNORM : PIPE_FORMAT_Z24X8_UNORM; + PIPE_FORMAT_Z24X8_UNORM : PIPE_FORMAT_X8Z24_UNORM; break; } } else { template.format = ms->ds_depth_bits_last ? - PIPE_FORMAT_S8Z24_UNORM : PIPE_FORMAT_Z24S8_UNORM; + PIPE_FORMAT_Z24S8_UNORM : PIPE_FORMAT_S8Z24_UNORM; } template.width0 = pDraw->width; template.height0 = pDraw->height; template.depth0 = 1; template.last_level = 0; template.tex_usage = PIPE_TEXTURE_USAGE_DEPTH_STENCIL | - PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + PIPE_TEXTURE_USAGE_SHARED; tex = ms->screen->texture_create(ms->screen, &template); pipe_texture_reference(&exa_priv->depth_stencil_tex, tex); } @@ -153,10 +154,13 @@ dri2_do_create_buffer(DrawablePtr pDraw, DRI2BufferPtr buffer, unsigned int form if (!tex) FatalError("NO TEXTURE IN DRI2\n"); - ms->api->shared_handle_from_texture(ms->api, ms->screen, tex, &stride, &handle); + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_SHARED; + + ms->screen->texture_get_handle(ms->screen, tex, &whandle); - buffer->name = handle; - buffer->pitch = stride; + buffer->name = whandle.handle; + buffer->pitch = whandle.stride; buffer->cpp = 4; buffer->driverPrivate = private; buffer->flags = 0; /* not tiled */ @@ -431,11 +435,11 @@ xorg_dri2_init(ScreenPtr pScreen) dri2info.Wait = NULL; ms->d_depth_bits_last = - ms->screen->is_format_supported(ms->screen, PIPE_FORMAT_X8Z24_UNORM, + ms->screen->is_format_supported(ms->screen, PIPE_FORMAT_Z24X8_UNORM, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); ms->ds_depth_bits_last = - ms->screen->is_format_supported(ms->screen, PIPE_FORMAT_S8Z24_UNORM, + ms->screen->is_format_supported(ms->screen, PIPE_FORMAT_Z24S8_UNORM, PIPE_TEXTURE_2D, PIPE_TEXTURE_USAGE_DEPTH_STENCIL, 0); diff --git a/src/gallium/state_trackers/xorg/xorg_driver.c b/src/gallium/state_trackers/xorg/xorg_driver.c index f53a879a14..004a28f00e 100644 --- a/src/gallium/state_trackers/xorg/xorg_driver.c +++ b/src/gallium/state_trackers/xorg/xorg_driver.c @@ -155,7 +155,7 @@ drv_get_rec(ScrnInfoPtr pScrn) if (pScrn->driverPrivate) return TRUE; - pScrn->driverPrivate = xnfcalloc(sizeof(modesettingRec), 1); + pScrn->driverPrivate = xnfcalloc(1, sizeof(modesettingRec)); return TRUE; } @@ -183,31 +183,66 @@ drv_probe_ddc(ScrnInfoPtr pScrn, int index) static Bool drv_crtc_resize(ScrnInfoPtr pScrn, int width, int height) { + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); modesettingPtr ms = modesettingPTR(pScrn); - PixmapPtr rootPixmap; ScreenPtr pScreen = pScrn->pScreen; + int old_width, old_height; + PixmapPtr rootPixmap; + int i; if (width == pScrn->virtualX && height == pScrn->virtualY) return TRUE; + old_width = pScrn->virtualX; + old_height = pScrn->virtualY; pScrn->virtualX = width; pScrn->virtualY = height; - /* - * Remove the old framebuffer & texture. - */ - drmModeRmFB(ms->fd, ms->fb_id); - if (!ms->destroy_front_buffer(pScrn)) - FatalError("failed to destroy front buffer\n"); + /* ms->create_front_buffer will remove the old front buffer */ rootPixmap = pScreen->GetScreenPixmap(pScreen); if (!pScreen->ModifyPixmapHeader(rootPixmap, width, height, -1, -1, -1, NULL)) - return FALSE; + goto error_modify; pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8); - /* now create new frontbuffer */ - return ms->create_front_buffer(pScrn) && ms->bind_front_buffer(pScrn); + if (!ms->create_front_buffer(pScrn) || !ms->bind_front_buffer(pScrn)) + goto error_create; + + /* + * create && bind will turn off all crtc(s) in the kernel so we need to + * re-enable all the crtcs again. For real HW we might want to do this + * before destroying the old framebuffer. + */ + for (i = 0; i < xf86_config->num_crtc; i++) { + xf86CrtcPtr crtc = xf86_config->crtc[i]; + + if (!crtc->enabled) + continue; + + crtc->funcs->set_mode_major(crtc, &crtc->mode, crtc->rotation, crtc->x, crtc->y); + } + + return TRUE; + + /* + * This is the error recovery path. + */ +error_create: + if (!pScreen->ModifyPixmapHeader(rootPixmap, old_width, old_height, -1, -1, -1, NULL)) + FatalError("failed to resize rootPixmap error path\n"); + + pScrn->displayWidth = rootPixmap->devKind / (rootPixmap->drawable.bitsPerPixel / 8); + +error_modify: + pScrn->virtualX = old_width; + pScrn->virtualY = old_height; + + if (ms->create_front_buffer(pScrn) && ms->bind_front_buffer(pScrn)) + return FALSE; + + FatalError("failed to setup old framebuffer\n"); + return FALSE; } static const xf86CrtcConfigFuncsRec crtc_config_funcs = { @@ -333,6 +368,7 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) EntityInfoPtr pEnt; EntPtr msEnt = NULL; int max_width, max_height; + CustomizerPtr cust; if (pScrn->numEntities != 1) return FALSE; @@ -344,6 +380,9 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) return TRUE; } + cust = (CustomizerPtr) pScrn->driverPrivate; + pScrn->driverPrivate = NULL; + /* Allocate driverPrivate */ if (!drv_get_rec(pScrn)) return FALSE; @@ -351,6 +390,7 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) ms = modesettingPTR(pScrn); ms->SaveGeneration = -1; ms->pEnt = pEnt; + ms->cust = cust; pScrn->displayWidth = 640; /* default it */ @@ -423,8 +463,8 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags) xf86CrtcConfigInit(pScrn, &crtc_config_funcs); xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - max_width = 8192; - max_height = 8192; + max_width = 2048; /* A very low default */ + max_height = 2048; /* see screen_init */ xf86CrtcSetSizeRange(pScrn, 320, 200, max_width, max_height); if (xf86ReturnOptValBool(ms->Options, OPTION_SW_CURSOR, FALSE)) { @@ -607,7 +647,9 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; modesettingPtr ms = modesettingPTR(pScrn); + unsigned max_width, max_height; VisualPtr visual; + CustomizerPtr cust = ms->cust; if (!drv_init_drm(pScrn)) { FatalError("Could not init DRM"); @@ -624,6 +666,26 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) return FALSE; } + /* get max width and height */ + { + drmModeResPtr res; + res = drmModeGetResources(ms->fd); + max_width = res->max_width; + max_height = res->max_height; + drmModeFreeResources(res); + } + + if (ms->screen) { + float maxf; + int max; + maxf = ms->screen->get_paramf(ms->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS); + max = (1 << (int)(maxf - 1.0f)); + max_width = max < max_width ? max : max_width; + max_height = max < max_height ? max : max_height; + } + + xf86CrtcSetSizeRange(pScrn, 1, 1, max_width, max_height); + pScrn->pScreen = pScreen; /* HW dependent - FIXME */ @@ -673,7 +735,7 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) xf86SetBlackWhitePixels(pScreen); ms->accelerate_2d = xf86ReturnOptValBool(ms->Options, OPTION_2D_ACCEL, FALSE); - ms->debug_fallback = xf86ReturnOptValBool(ms->Options, OPTION_DEBUG_FALLBACK, TRUE); + ms->debug_fallback = xf86ReturnOptValBool(ms->Options, OPTION_DEBUG_FALLBACK, ms->accelerate_2d); if (ms->screen) { ms->exa = xorg_exa_init(pScrn, ms->accelerate_2d); @@ -684,6 +746,11 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #endif } + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "##################################\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "# Usefull debugging info follows #\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "##################################\n"); + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Using %s backend\n", + ms->screen ? "Gallium3D" : "libkms"); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "2D Acceleration is %s\n", ms->screen && ms->accelerate_2d ? "enabled" : "disabled"); xf86DrvMsg(pScrn->scrnIndex, X_INFO, "Fallback debugging is %s\n", @@ -694,6 +761,7 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) #else xf86DrvMsg(pScrn->scrnIndex, X_INFO, "3D Acceleration is disabled\n"); #endif + xf86DrvMsg(pScrn->scrnIndex, X_INFO, "##################################\n"); miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); @@ -725,8 +793,8 @@ drv_screen_init(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) if (serverGeneration == 1) xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options); - if (ms->winsys_screen_init) - ms->winsys_screen_init(pScrn); + if (cust && cust->winsys_screen_init) + cust->winsys_screen_init(cust, ms->fd); return drv_enter_vt(scrnIndex, 1); } @@ -759,10 +827,11 @@ drv_leave_vt(int scrnIndex, int flags) ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; modesettingPtr ms = modesettingPTR(pScrn); xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); + CustomizerPtr cust = ms->cust; int o; - if (ms->winsys_leave_vt) - ms->winsys_leave_vt(pScrn); + if (cust && cust->winsys_leave_vt) + cust->winsys_leave_vt(cust); for (o = 0; o < config->num_crtc; o++) { xf86CrtcPtr crtc = config->crtc[o]; @@ -778,6 +847,7 @@ drv_leave_vt(int scrnIndex, int flags) } drmModeRmFB(ms->fd, ms->fb_id); + ms->fb_id = -1; drv_restore_hw_state(pScrn); @@ -796,6 +866,7 @@ drv_enter_vt(int scrnIndex, int flags) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; modesettingPtr ms = modesettingPTR(pScrn); + CustomizerPtr cust = ms->cust; if (drmSetMaster(ms->fd)) { if (errno == EINVAL) { @@ -826,8 +897,8 @@ drv_enter_vt(int scrnIndex, int flags) if (!xf86SetDesiredModes(pScrn)) return FALSE; - if (ms->winsys_enter_vt) - ms->winsys_enter_vt(pScrn); + if (cust && cust->winsys_enter_vt) + cust->winsys_enter_vt(cust); return TRUE; } @@ -845,13 +916,14 @@ drv_close_screen(int scrnIndex, ScreenPtr pScreen) { ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; modesettingPtr ms = modesettingPTR(pScrn); + CustomizerPtr cust = ms->cust; if (pScrn->vtSema) { drv_leave_vt(scrnIndex, 0); } - if (ms->winsys_screen_close) - ms->winsys_screen_close(pScrn); + if (cust && cust->winsys_screen_close) + cust->winsys_screen_close(cust); #ifdef DRI2 if (ms->screen) @@ -900,6 +972,15 @@ static Bool drv_destroy_front_buffer_ga3d(ScrnInfoPtr pScrn) { modesettingPtr ms = modesettingPTR(pScrn); + + if (!ms->root_texture) + return TRUE; + + if (ms->fb_id != -1) { + drmModeRmFB(ms->fd, ms->fb_id); + ms->fb_id = -1; + } + pipe_texture_reference(&ms->root_texture, NULL); return TRUE; } @@ -908,8 +989,9 @@ static Bool drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) { modesettingPtr ms = modesettingPTR(pScrn); - unsigned handle, stride; struct pipe_texture *tex; + struct winsys_handle whandle; + unsigned fb_id; int ret; ms->noEvict = TRUE; @@ -920,10 +1002,10 @@ drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) if (!tex) return FALSE; - if (!ms->api->local_handle_from_texture(ms->api, ms->screen, - tex, - &stride, - &handle)) + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_KMS; + + if (!ms->screen->texture_get_handle(ms->screen, tex, &whandle)) goto err_destroy; ret = drmModeAddFB(ms->fd, @@ -931,21 +1013,25 @@ drv_create_front_buffer_ga3d(ScrnInfoPtr pScrn) pScrn->virtualY, pScrn->depth, pScrn->bitsPerPixel, - stride, - handle, - &ms->fb_id); + whandle.stride, + whandle.handle, + &fb_id); if (ret) { - debug_printf("%s: failed to create framebuffer (%i, %s)", + debug_printf("%s: failed to create framebuffer (%i, %s)\n", __func__, ret, strerror(-ret)); goto err_destroy; } + if (!drv_destroy_front_buffer_ga3d(pScrn)) + FatalError("%s: failed to take down old framebuffer\n", __func__); + pScrn->frameX0 = 0; pScrn->frameY0 = 0; drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); pipe_texture_reference(&ms->root_texture, tex); pipe_texture_reference(&tex, NULL); + ms->fb_id = fb_id; return TRUE; @@ -993,6 +1079,11 @@ drv_destroy_front_buffer_kms(ScrnInfoPtr pScrn) if (!ms->root_bo) return TRUE; + if (ms->fb_id != -1) { + drmModeRmFB(ms->fd, ms->fb_id); + ms->fb_id = -1; + } + kms_bo_unmap(ms->root_bo); kms_bo_destroy(&ms->root_bo); return TRUE; @@ -1005,6 +1096,7 @@ drv_create_front_buffer_kms(ScrnInfoPtr pScrn) unsigned handle, stride; struct kms_bo *bo; unsigned attr[8]; + unsigned fb_id; int ret; attr[0] = KMS_BO_TYPE; @@ -1035,17 +1127,21 @@ drv_create_front_buffer_kms(ScrnInfoPtr pScrn) pScrn->bitsPerPixel, stride, handle, - &ms->fb_id); + &fb_id); if (ret) { debug_printf("%s: failed to create framebuffer (%i, %s)", __func__, ret, strerror(-ret)); goto err_destroy; } + if (!drv_destroy_front_buffer_kms(pScrn)) + FatalError("%s: could not takedown old bo", __func__); + pScrn->frameX0 = 0; pScrn->frameY0 = 0; drv_adjust_frame(pScrn->scrnIndex, pScrn->frameX0, pScrn->frameY0, 0); ms->root_bo = bo; + ms->fb_id = fb_id; return TRUE; @@ -1113,4 +1209,14 @@ static Bool drv_init_front_buffer_functions(ScrnInfoPtr pScrn) return TRUE; } +CustomizerPtr xorg_customizer(ScrnInfoPtr pScrn) +{ + return modesettingPTR(pScrn)->cust; +} + +Bool xorg_has_gallium(ScrnInfoPtr pScrn) +{ + return modesettingPTR(pScrn)->screen != NULL; +} + /* vim: set sw=4 ts=8 sts=4: */ diff --git a/src/gallium/state_trackers/xorg/xorg_exa.c b/src/gallium/state_trackers/xorg/xorg_exa.c index 665efdc0f0..a7ffe3f499 100644 --- a/src/gallium/state_trackers/xorg/xorg_exa.c +++ b/src/gallium/state_trackers/xorg/xorg_exa.c @@ -118,22 +118,22 @@ exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp, int *picture_ { switch (depth) { case 32: - *format = PIPE_FORMAT_A8R8G8B8_UNORM; + *format = PIPE_FORMAT_B8G8R8A8_UNORM; *picture_format = PICT_a8r8g8b8; assert(*bbp == 32); break; case 24: - *format = PIPE_FORMAT_X8R8G8B8_UNORM; + *format = PIPE_FORMAT_B8G8R8X8_UNORM; *picture_format = PICT_x8r8g8b8; assert(*bbp == 32); break; case 16: - *format = PIPE_FORMAT_R5G6B5_UNORM; + *format = PIPE_FORMAT_B5G6R5_UNORM; *picture_format = PICT_r5g6b5; assert(*bbp == 16); break; case 15: - *format = PIPE_FORMAT_A1R5G5B5_UNORM; + *format = PIPE_FORMAT_B5G5R5A1_UNORM; *picture_format = PICT_x1r5g5b5; assert(*bbp == 16); break; @@ -144,7 +144,7 @@ exa_get_pipe_format(int depth, enum pipe_format *format, int *bbp, int *picture_ break; case 4: case 1: - *format = PIPE_FORMAT_A8R8G8B8_UNORM; /* bad bad bad */ + *format = PIPE_FORMAT_B8G8R8A8_UNORM; /* bad bad bad */ break; default: assert(0); @@ -789,7 +789,7 @@ xorg_exa_set_displayed_usage(PixmapPtr pPixmap) return 0; } - priv->flags |= PIPE_TEXTURE_USAGE_PRIMARY; + priv->flags |= PIPE_TEXTURE_USAGE_SCANOUT; return 0; } @@ -805,7 +805,7 @@ xorg_exa_set_shared_usage(PixmapPtr pPixmap) return 0; } - priv->flags |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + priv->flags |= PIPE_TEXTURE_USAGE_SHARED; return 0; } @@ -943,7 +943,7 @@ xorg_exa_set_texture(PixmapPtr pPixmap, struct pipe_texture *tex) { struct exa_pixmap_priv *priv = exaGetPixmapDriverPrivate(pPixmap); - int mask = PIPE_TEXTURE_USAGE_PRIMARY | PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + int mask = PIPE_TEXTURE_USAGE_SHARED | PIPE_TEXTURE_USAGE_SCANOUT; if (!priv) return FALSE; @@ -976,8 +976,8 @@ xorg_exa_create_root_texture(ScrnInfoPtr pScrn, template.depth0 = 1; template.last_level = 0; template.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; - template.tex_usage |= PIPE_TEXTURE_USAGE_PRIMARY; - template.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + template.tex_usage |= PIPE_TEXTURE_USAGE_SCANOUT; + template.tex_usage |= PIPE_TEXTURE_USAGE_SHARED; return exa->scrn->texture_create(exa->scrn, &template); } diff --git a/src/gallium/state_trackers/xorg/xorg_tracker.h b/src/gallium/state_trackers/xorg/xorg_tracker.h index 58bb60a721..2f5cc64d9c 100644 --- a/src/gallium/state_trackers/xorg/xorg_tracker.h +++ b/src/gallium/state_trackers/xorg/xorg_tracker.h @@ -67,6 +67,14 @@ typedef struct #define XORG_NR_FENCES 3 +typedef struct _CustomizerRec +{ + Bool (*winsys_screen_init)(struct _CustomizerRec *cust, int fd); + Bool (*winsys_screen_close)(struct _CustomizerRec *cust); + Bool (*winsys_enter_vt)(struct _CustomizerRec *cust); + Bool (*winsys_leave_vt)(struct _CustomizerRec *cust); +} CustomizerRec, *CustomizerPtr; + typedef struct _modesettingRec { /* drm */ @@ -117,12 +125,7 @@ typedef struct _modesettingRec Bool accelerate_2d; Bool debug_fallback; - /* winsys hocks */ - Bool (*winsys_screen_init)(ScrnInfoPtr pScr); - Bool (*winsys_screen_close)(ScrnInfoPtr pScr); - Bool (*winsys_enter_vt)(ScrnInfoPtr pScr); - Bool (*winsys_leave_vt)(ScrnInfoPtr pScr); - void *winsys_priv; + CustomizerPtr cust; #ifdef DRM_MODE_FEATURE_DIRTYFB DamagePtr damage; @@ -131,6 +134,9 @@ typedef struct _modesettingRec #define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate)) +CustomizerPtr xorg_customizer(ScrnInfoPtr pScrn); + +Bool xorg_has_gallium(ScrnInfoPtr pScrn); /*********************************************************************** * xorg_exa.c diff --git a/src/gallium/state_trackers/xorg/xvmc/surface.c b/src/gallium/state_trackers/xorg/xvmc/surface.c index 0e39a390c6..12d94e0c5c 100644 --- a/src/gallium/state_trackers/xorg/xvmc/surface.c +++ b/src/gallium/state_trackers/xorg/xvmc/surface.c @@ -101,12 +101,12 @@ CreateOrResizeBackBuffer(struct pipe_video_context *vpipe, unsigned int width, u memset(&template, 0, sizeof(struct pipe_texture)); template.target = PIPE_TEXTURE_2D; /* XXX: Needs to match the drawable's format? */ - template.format = PIPE_FORMAT_X8R8G8B8_UNORM; + template.format = PIPE_FORMAT_B8G8R8X8_UNORM; template.last_level = 0; template.width0 = width; template.height0 = height; template.depth0 = 1; - template.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + template.tex_usage = PIPE_TEXTURE_USAGE_SHARED; tex = vpipe->screen->texture_create(vpipe->screen, &template); if (!tex) |