From 782eae916d1f02121785448d4ab4759767a46afd Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 12 Jan 2009 11:51:57 +0000 Subject: [PATCH] dri: sketch of new device-independent glx/dri state tracker --- .../state_trackers/glx/dri1/dri_context.c | 168 ++++++++++ .../state_trackers/glx/dri1/dri_context.h | 93 ++++++ .../state_trackers/glx/dri1/dri_drawable.c | 63 ++++ .../state_trackers/glx/dri1/dri_extensions.c | 108 +++++++ .../state_trackers/glx/dri1/dri_lock.c | 90 ++++++ .../state_trackers/glx/dri1/dri_screen.c | 255 +++++++++++++++ .../state_trackers/glx/dri1/dri_screen.h | 98 ++++++ .../state_trackers/glx/dri1/dri_swapbuffers.c | 295 ++++++++++++++++++ .../state_trackers/glx/dri1/dri_swapbuffers.h | 47 +++ 9 files changed, 1217 insertions(+) create mode 100644 src/gallium/state_trackers/glx/dri1/dri_context.c create mode 100644 src/gallium/state_trackers/glx/dri1/dri_context.h create mode 100644 src/gallium/state_trackers/glx/dri1/dri_drawable.c create mode 100644 src/gallium/state_trackers/glx/dri1/dri_extensions.c create mode 100644 src/gallium/state_trackers/glx/dri1/dri_lock.c create mode 100644 src/gallium/state_trackers/glx/dri1/dri_screen.c create mode 100644 src/gallium/state_trackers/glx/dri1/dri_screen.h create mode 100644 src/gallium/state_trackers/glx/dri1/dri_swapbuffers.c create mode 100644 src/gallium/state_trackers/glx/dri1/dri_swapbuffers.h diff --git a/src/gallium/state_trackers/glx/dri1/dri_context.c b/src/gallium/state_trackers/glx/dri1/dri_context.c new file mode 100644 index 00000000000..9424e18bee3 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri1/dri_context.c @@ -0,0 +1,168 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_winsys.h" + +#include "state_tracker/st_public.h" +#include "state_tracker/st_context.h" +#include "pipe/p_context.h" + +#include "util/u_memory.h" + + +GLboolean +dri_create_context(const __GLcontextModes *visual, + __DRIcontextPrivate *cPriv, + void *sharedContextPrivate) +{ + __DRIscreenPrivate *sPriv = cPriv->driScreenPriv; + struct dri_screen *screen = dri_screen(sPriv); + struct dri_context *ctx = NULL; + struct st_context *st_share = NULL; + + if (sharedContextPrivate) { + st_share = ((struct dri_context *) sharedContextPrivate)->st; + } + + ctx = CALLOC_STRUCT(dri_context); + if (ctx == NULL) + goto fail; + + cPriv->driverPrivate = ctx; + ctx->cPriv = cPriv; + ctx->sPriv = sPriv; + + driParseConfigFiles(&ctx->optionCache, + &screen->optionCache, + sPriv->myNum, + "dri"); + + ctx->pipe = screen->pipe_screen->create_context(screen->pipe_screen, + screen->pipe_winsys, + hw_winsys ); + if (ctx->pipe == NULL) + goto fail; + + ctx->pipe->priv = ctx; /* I guess */ + + ctx->st = st_create_context(ctx->pipe, visual, st_share); + if (ctx->st == NULL) + goto fail; + + dri_init_extensions( ctx ); + + return GL_TRUE; + +fail: + if (ctx && ctx->st) + st_destroy_context( ctx->st ); + + if (ctx && ctx->pipe) + ctx->pipe->destroy( ctx->pipe ); + + FREE(ctx); + return FALSE; +} + + +void +dri_destroy_context(__DRIcontextPrivate *cPriv) +{ + struct dri_context *ctx = dri_context(cPriv); + struct dri_screen *screen = dri_screen(cPriv->driScreenPriv); + struct pipe_winsys *winsys = screen->winsys; + + /* No particular reason to wait for command completion before + * destroying a context, but it is probably worthwhile flushing it + * to avoid having to add code elsewhere to cope with flushing a + * partially destroyed context. + */ + st_flush(ctx->st); + + if (screen->dummyContext == ctx) + screen->dummyContext = NULL; + + /* Also frees ctx->pipe? + */ + st_destroy_context(ctx->st); + + FREE(ctx); +} + + +GLboolean +dri_unbind_context(__DRIcontextPrivate *cPriv) +{ + struct dri_context *ctx = dri_context(cPriv); + st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + /* XXX make_current(NULL)? */ + return GL_TRUE; +} + + +GLboolean +dri_make_current(__DRIcontextPrivate *cPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv) +{ + if (cPriv) { + struct dri_context *ctx = dri_context(cPriv); + struct dri_screen *screen = dri_screen(cPriv->driScreenPriv); + struct dri_drawable *draw = dri_drawable(driDrawPriv); + struct dri_drawable *read = dri_drawable(driReadPriv); + + /* This is for situations in which we need a rendering context but + * there may not be any currently bound. + */ + screen->dummyContext = ctx; + + st_make_current( ctx->st, + draw->stfb, + read->stfb ); + + ctx->dPriv = driDrawPriv; + + /* Update window sizes if necessary: + */ + if (draw->stamp != driDrawPriv->lastStamp) { + dri_update_window_size( draw ); + } + + if (read->stamp != driReadPriv->lastStamp) { + dri_update_window_size( read ); + } + + } + else { + st_make_current(NULL, NULL, NULL); + } + + return GL_TRUE; +} diff --git a/src/gallium/state_trackers/glx/dri1/dri_context.h b/src/gallium/state_trackers/glx/dri1/dri_context.h new file mode 100644 index 00000000000..06b86d69a89 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri1/dri_context.h @@ -0,0 +1,93 @@ +/************************************************************************** + * + * Copyright (C) 2009 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef DRI_CONTEXT_H +#define DRI_CONTEXT_H + +#include +#include "drm.h" + +#include "pipe/p_debug.h" + +#include "dri_screen.h" + +struct pipe_context; +struct pipe_fence; +struct st_context; + + +struct dri_context +{ + __DRIcontextPrivate *cPriv; + __DRIdrawablePrivate *dPriv; + + struct st_context *st; + struct pipe_context *pipe; + + boolean locked; + + /** + * Configuration cache + */ + driOptionCache optionCache; +}; + + + +struct dri_drawable +{ + __DRIdrawablePrivate *dPriv; + unsigned stamp; + + struct pipe_fence *last_swap_fence; + struct pipe_fence *first_swap_fence; + + struct st_framebuffer *stfb; +}; + + +static INLINE struct dri_context * +dri_context(__DRIcontextPrivate *driContextPriv) +{ + return (struct dri_context *) driContextPriv->driverPrivate; +} + +static INLINE struct dri_drawable * +dri_drawable(__DRIdrawablePrivate * driDrawPriv) +{ + return (struct dri_drawable *) driDrawPriv->driverPrivate; +} + +/*********************************************************************** + * dri_lock.c + */ +void dri_lock_hardware( struct dri_context *dri, struct dri_drawable *drawable ); +void dri_unlock_hardware( struct dri_context *dri ); +boolean dri_is_locked( struct dri_context *dri ); + + + +#endif diff --git a/src/gallium/state_trackers/glx/dri1/dri_drawable.c b/src/gallium/state_trackers/glx/dri1/dri_drawable.c new file mode 100644 index 00000000000..7503c40194e --- /dev/null +++ b/src/gallium/state_trackers/glx/dri1/dri_drawable.c @@ -0,0 +1,63 @@ + +/** + * This is called when we need to set up GL rendering to a new X window. + */ +static boolean +dri_create_buffer(__DRIscreenPrivate *sPriv, + __DRIdrawablePrivate *dPriv, + const __GLcontextModes *visual, + boolean isPixmap) +{ + enum pipe_format colorFormat, depthFormat, stencilFormat; + struct dri_drawable *drawable; + + if (isPixmap) + goto fail; /* not implemented */ + + drawable = CALLOC_STRUCT(dri_drawable); + if (drawable == NULL) + goto fail; + + /* XXX: todo: use the pipe_screen queries to figure out which + * render targets are supportable. + */ + if (visual->redBits == 5) + colorFormat = PIPE_FORMAT_R5G6B5_UNORM; + else + colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM; + + if (visual->depthBits == 16) + depthFormat = PIPE_FORMAT_Z16_UNORM; + else if (visual->depthBits == 24) { + if (visual->stencilBits == 8) + depthFormat = PIPE_FORMAT_S8Z24_UNORM; + else + depthFormat = PIPE_FORMAT_X8Z24_UNORM; + } + + drawable->stfb = st_create_framebuffer(visual, + colorFormat, + depthFormat, + dPriv->w, + dPriv->h, + (void*) drawable); + if (drawable->stfb == NULL) + goto fail; + + dPriv->driverPrivate = (void *) drawable; + return GL_TRUE; + +fail: + FREE(drawable); + return GL_FALSE; +} + +static void +dri_destroy_buffer(__DRIdrawablePrivate *dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + assert(drawable->stfb); + st_unreference_framebuffer(drawable->stfb); + FREE(drawable); +} + diff --git a/src/gallium/state_trackers/glx/dri1/dri_extensions.c b/src/gallium/state_trackers/glx/dri1/dri_extensions.c new file mode 100644 index 00000000000..126faf76014 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri1/dri_extensions.c @@ -0,0 +1,108 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + + + +#define need_GL_ARB_multisample +#define need_GL_ARB_point_parameters +#define need_GL_ARB_texture_compression +#define need_GL_ARB_vertex_buffer_object +#define need_GL_ARB_vertex_program +#define need_GL_ARB_window_pos +#define need_GL_EXT_blend_color +#define need_GL_EXT_blend_equation_separate +#define need_GL_EXT_blend_func_separate +#define need_GL_EXT_blend_minmax +#define need_GL_EXT_cull_vertex +#define need_GL_EXT_fog_coord +#define need_GL_EXT_framebuffer_object +#define need_GL_EXT_multi_draw_arrays +#define need_GL_EXT_secondary_color +#define need_GL_NV_vertex_program +#include "extension_helper.h" + + +/** + * Extension strings exported by the driver. + */ +const struct dri_extension card_extensions[] = { + {"GL_ARB_multisample", GL_ARB_multisample_functions}, + {"GL_ARB_multitexture", NULL}, + {"GL_ARB_point_parameters", GL_ARB_point_parameters_functions}, + {"GL_ARB_texture_border_clamp", NULL}, + {"GL_ARB_texture_compression", GL_ARB_texture_compression_functions}, + {"GL_ARB_texture_cube_map", NULL}, + {"GL_ARB_texture_env_add", NULL}, + {"GL_ARB_texture_env_combine", NULL}, + {"GL_ARB_texture_env_dot3", NULL}, + {"GL_ARB_texture_mirrored_repeat", NULL}, + {"GL_ARB_texture_rectangle", NULL}, + {"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions}, + {"GL_ARB_pixel_buffer_object", NULL}, + {"GL_ARB_vertex_program", GL_ARB_vertex_program_functions}, + {"GL_ARB_window_pos", GL_ARB_window_pos_functions}, + {"GL_EXT_blend_color", GL_EXT_blend_color_functions}, + {"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions}, + {"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions}, + {"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions}, + {"GL_EXT_blend_subtract", NULL}, + {"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions}, + {"GL_EXT_fog_coord", GL_EXT_fog_coord_functions}, + {"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions}, + {"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions}, + {"GL_EXT_packed_depth_stencil", NULL}, + {"GL_EXT_pixel_buffer_object", NULL}, + {"GL_EXT_secondary_color", GL_EXT_secondary_color_functions}, + {"GL_EXT_stencil_wrap", NULL}, + {"GL_EXT_texture_edge_clamp", NULL}, + {"GL_EXT_texture_env_combine", NULL}, + {"GL_EXT_texture_env_dot3", NULL}, + {"GL_EXT_texture_filter_anisotropic", NULL}, + {"GL_EXT_texture_lod_bias", NULL}, + {"GL_3DFX_texture_compression_FXT1", NULL}, + {"GL_APPLE_client_storage", NULL}, + {"GL_MESA_pack_invert", NULL}, + {"GL_MESA_ycbcr_texture", NULL}, + {"GL_NV_blend_square", NULL}, + {"GL_NV_vertex_program", GL_NV_vertex_program_functions}, + {"GL_NV_vertex_program1_1", NULL}, + {"GL_SGIS_generate_mipmap", NULL }, + {NULL, NULL} +}; + + + +void +dri_init_extensions( void ) +{ + /* The card_extensions list should be pruned according to the + * capabilities of the pipe_screen. This is actually something + * that can/should be done inside st_create_context(). + */ + driInitExtensions( ctx->st->ctx, card_extensions, GL_TRUE ); +} diff --git a/src/gallium/state_trackers/glx/dri1/dri_lock.c b/src/gallium/state_trackers/glx/dri1/dri_lock.c new file mode 100644 index 00000000000..9d7bd61e282 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri1/dri_lock.c @@ -0,0 +1,90 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "pipe/p_thread.h" +#include "dri_context.h" +#include "xf86drm.h" + +pipe_static_mutex( lockMutex ); + +static void +dri_contended_lock(struct dri_context *ctx) +{ + __DRIdrawablePrivate *dPriv = ctx->dPriv; + __DRIcontextPrivate *cPriv = ctx->cPriv; + __DRIscreenPrivate *sPriv = ctx->sPriv; + + drmGetLock(sPriv->fd, cPriv->hHWContext, 0); + + /* Perform round trip communication with server (including dropping + * and retaking the above lock) to update window dimensions: + */ + if (dPriv) + DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); +} + + +/* Lock the hardware and validate our state. + */ +void dri_lock_hardware( struct dri_context *ctx ) +{ + __DRIscreenPrivate *sPriv = ctx->sPriv; + __DRIcontextPrivate *cPriv = ctx->cPriv; + char __ret = 0; + + pipe_mutex_lock(lockMutex); + assert(!ctx->locked); + + DRM_CAS((drmLock *) &sPriv->pSAREA->lock, + cPriv->hHWContext, + (DRM_LOCK_HELD | cPriv->hHWContext), + __ret); + + if (__ret) + dri_contended_lock( ctx ); + + ctx->locked = TRUE; +} + + +/* Unlock the hardware using the global current context + */ +void dri_unlock_hardware( struct dri_context *ctx ) +{ + __DRIscreenPrivate *sPriv = ctx->sPriv; + __DRIcontextPrivate *cPriv = ctx->cPriv; + + assert(ctx->locked); + ctx->locked = FALSE; + + DRM_UNLOCK(sPriv->fd, + (drmLock *) &sPriv->pSAREA->lock, + cPriv->hHWContext); + + pipe_mutex_unlock(lockMutex); +} diff --git a/src/gallium/state_trackers/glx/dri1/dri_screen.c b/src/gallium/state_trackers/glx/dri1/dri_screen.c new file mode 100644 index 00000000000..f7119b949a3 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri1/dri_screen.c @@ -0,0 +1,255 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "utils.h" +#include "vblank.h" +#include "xmlpool.h" + +#include "dri_context.h" +#include "dri_screen.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "pipe/p_inlines.h" +#include "state_tracker/st_public.h" +#include "state_tracker/st_cb_fbo.h" + + +PUBLIC const char __driConfigOptions[] = + DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE + DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) + DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) + DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY +// DRI_CONF_FORCE_S3TC_ENABLE(false) + DRI_CONF_ALLOW_LARGE_TEXTURES(1) + DRI_CONF_SECTION_END DRI_CONF_END; + +const uint __driNConfigOptions = 3; + +static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; + +extern const struct dri_extension card_extensions[]; + + + +static const __DRIextension *driScreenExtensions[] = { + &driReadDrawableExtension, + &driCopySubBufferExtension.base, + &driSwapControlExtension.base, + &driFrameTrackingExtension.base, + &driMediaStreamCounterExtension.base, + NULL +}; + + + + +static const char * +dri_get_name( struct pipe_winsys *winsys ) +{ + return "dri"; +} + + + +static void +dri_destroy_screen(__DRIscreenPrivate * sPriv) +{ + struct dri_screen *screen = dri_screen(sPriv); + + screen->pipe_screen->destroy( screen->pipe_screen ); + screen->pipe_winsys->destroy( screen->pipe_winsys ); + FREE(screen); + sPriv->private = NULL; +} + + +/** + * Get information about previous buffer swaps. + */ +static int +dri_get_swap_info(__DRIdrawablePrivate * dPriv, + __DRIswapInfo * sInfo) +{ + if (dPriv == NULL || + dPriv->driverPrivate == NULL || + sInfo == NULL) + return -1; + else + return 0; +} + +static const __DRIconfig ** +dri_fill_in_modes(__DRIscreenPrivate *psp, + unsigned pixel_bits ) +{ + __DRIconfig **configs; + __GLcontextModes *m; + unsigned num_modes; + uint8_t depth_bits_array[3]; + uint8_t stencil_bits_array[3]; + uint8_t msaa_samples_array[1]; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + GLenum fb_format; + GLenum fb_type; + int i; + + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML + }; + + depth_bits_array[0] = 0; + depth_bits_array[1] = depth_bits; + depth_bits_array[2] = depth_bits; + + stencil_bits_array[0] = 0; /* no depth or stencil */ + stencil_bits_array[1] = 0; /* z24x8 */ + stencil_bits_array[2] = 8; /* z24s8 */ + + msaa_samples_array[0] = 0; + + depth_buffer_factor = 3; + back_buffer_factor = 1; + + num_modes = depth_buffer_factor * back_buffer_factor * 4; + + if (pixel_bits == 16) { + fb_format = GL_RGB; + fb_type = GL_UNSIGNED_SHORT_5_6_5; + } + else { + fb_format = GL_BGRA; + fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; + } + + configs = driCreateConfigs(fb_format, fb_type, + depth_bits_array, + stencil_bits_array, depth_buffer_factor, + back_buffer_modes, back_buffer_factor, + msaa_samples_array, 1); + if (configs == NULL) { + debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__); + return NULL; + } + + return configs; +} + + + +/* This is the driver specific part of the createNewScreen entry point. + * + * Returns the __GLcontextModes supported by this driver. + */ +static const __DRIconfig **dri_init_screen(__DRIscreenPrivate *sPriv) +{ + static const __DRIversion ddx_expected = { 1, 6, 0 }; /* hw query */ + static const __DRIversion dri_expected = { 4, 0, 0 }; + static const __DRIversion drm_expected = { 1, 5, 0 }; /* hw query */ + struct dri_screen *screen; + + if (!driCheckDriDdxDrmVersions2("dri", + &sPriv->dri_version, &dri_expected, + &sPriv->ddx_version, &ddx_expected, + &sPriv->drm_version, &drm_expected)) { + return NULL; + } + + /* Set up dispatch table to cope with all known extensions: + */ + driInitExtensions( NULL, card_extensions, GL_FALSE ); + + + screen = CALLOC_STRUCT(dri_screen); + if (!screen) + goto fail; + + screen->sPriv = sPriv; + sPriv->private = (void *) screen; + + + /* Search the registered winsys' for one that likes this sPriv. + * This is required in situations where multiple devices speak to + * the same DDX and are built into the same binary. + * + * Note that cases like Intel i915 vs i965 doesn't fall into this + * category because they are built into separate binaries. + * + * Nonetheless, it's healthy to keep that level of detail out of + * this state_tracker. + */ + for (i = 0; + i < dri1_winsys_count && + screen->st_winsys == NULL; + i++) + { + screen->dri_winsys = + dri_winsys[i]->check_dri_privates( sPriv->pDevPriv, + sPriv->pSAREA + /* versions, etc?? */)); + } + + + driParseOptionInfo(&screen->optionCache, + __driConfigOptions, + __driNConfigOptions); + + + /* Plug our info back into the __DRIscreenPrivate: + */ + sPriv->private = (void *) screen; + sPriv->extensions = driScreenExtensions; + + return dri_fill_in_modes(sPriv, + dri_priv->cpp * 8, + 24, + 8, + 1); +fail: + return NULL; +} + + + +const struct __DriverAPIRec driDriverAPI = { + .InitScreen = dri_init_screen, + .DestroyScreen = dri_destroy_screen, + .CreateContext = dri_create_context, + .DestroyContext = dri_destroy_context, + .CreateBuffer = dri_create_buffer, + .DestroyBuffer = dri_destroy_buffer, + .SwapBuffers = dri_swap_buffers, + .MakeCurrent = dri_make_current, + .UnbindContext = dri_unbind_context, + .GetSwapInfo = dri_get_swap_info, + .GetDrawableMSC = driDrawableGetMSC32, + .WaitForMSC = driWaitForMSC32, + .CopySubBuffer = dri_copy_sub_buffer, + + //.InitScreen2 = dri_init_screen2, +}; diff --git a/src/gallium/state_trackers/glx/dri1/dri_screen.h b/src/gallium/state_trackers/glx/dri1/dri_screen.h new file mode 100644 index 00000000000..8909c920e42 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri1/dri_screen.h @@ -0,0 +1,98 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef DRI_SCREEN_H +#define DRI_SCREEN_H + +#include "dri_util.h" +#include "xmlconfig.h" + +#include "pipe/p_compiler.h" + +struct dri_screen +{ + __DRIScreenPrivate *sPriv; + struct pipe_winsys *pipe_winsys; + struct pipe_screen *pipe_screen; + + struct { + /* Need a pipe_surface pointer to do client-side swapbuffers: + */ + unsigned long buffer_handle; + struct pipe_surface *surface; + struct pipe_texture *texture; + + int pitch; /* row stride, in bytes */ + int width; + int height; + int size; + int cpp; /* for front and back buffers */ + } front; + + int deviceID; + int drmMinor; + + + /** + * Configuration cache with default values for all contexts + */ + driOptionCache optionCache; + + /** + * Temporary(?) context to use for SwapBuffers or other situations in + * which we need a rendering context, but none is currently bound. + */ + struct dri_context *dummyContext; +}; + + + +/** cast wrapper */ +static INLINE struct dri_screen * +dri_screen(__DRIscreenPrivate *sPriv) +{ + return (struct dri_screen *) sPriv->private; +} + + +extern void dri_destroy_context(__DRIcontextPrivate * driContextPriv); + +extern boolean dri_unbind_context(__DRIcontextPrivate * driContextPriv); + +extern boolean +dri_make_current(__DRIcontextPrivate * driContextPriv, + __DRIdrawablePrivate * driDrawPriv, + __DRIdrawablePrivate * driReadPriv); + + +extern boolean +dri_create_context(const __GLcontextModes * visual, + __DRIcontextPrivate * driContextPriv, + void *sharedContextPrivate); + + +#endif diff --git a/src/gallium/state_trackers/glx/dri1/dri_swapbuffers.c b/src/gallium/state_trackers/glx/dri1/dri_swapbuffers.c new file mode 100644 index 00000000000..6b2b9301344 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri1/dri_swapbuffers.c @@ -0,0 +1,295 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_swapbuffers.h" + +#include "pipe/p_context.h" +#include "state_tracker/st_public.h" +#include "state_tracker/st_context.h" +#include "state_tracker/st_cb_fbo.h" + + +static void +blit_swapbuffers(__DRIdrawablePrivate *dPriv, + __DRIcontextPrivate *cPriv, + struct pipe_surface *src, + const drm_clip_rect_t *rect) +{ + struct dri_screen *screen = dri_screen(dPriv->driScreenPriv); + struct dri_drawable *fb = dri_drawable(dPriv); + struct dri_context *context = dri_context(cPriv); + + const int nbox = dPriv->numClipRects; + const drm_clip_rect_t *pbox = dPriv->pClipRects; + + struct pipe_surface *dest = fb->front_surface; + const int backWidth = fb->stfb->Base.Width; + const int backHeight = fb->stfb->Base.Height; + int i; + + for (i = 0; i < nbox; i++, pbox++) { + drm_clip_rect_t box; + drm_clip_rect_t sbox; + + if (pbox->x1 > pbox->x2 || + pbox->y1 > pbox->y2 || + (pbox->x2 - pbox->x1) > dest->width || + (pbox->y2 - pbox->y1) > dest->height) + continue; + + box = *pbox; + + if (rect) { + drm_clip_rect_t rrect; + + rrect.x1 = dPriv->x + rect->x1; + rrect.y1 = (dPriv->h - rect->y1 - rect->y2) + dPriv->y; + rrect.x2 = rect->x2 + rrect.x1; + rrect.y2 = rect->y2 + rrect.y1; + if (rrect.x1 > box.x1) + box.x1 = rrect.x1; + if (rrect.y1 > box.y1) + box.y1 = rrect.y1; + if (rrect.x2 < box.x2) + box.x2 = rrect.x2; + if (rrect.y2 < box.y2) + box.y2 = rrect.y2; + + if (box.x1 > box.x2 || box.y1 > box.y2) + continue; + } + + /* restrict blit to size of actually rendered area */ + if (box.x2 - box.x1 > backWidth) + box.x2 = backWidth + box.x1; + if (box.y2 - box.y1 > backHeight) + box.y2 = backHeight + box.y1; + + debug_printf("%s: box %d,%d-%d,%d\n", __FUNCTION__, + box.x1, box.y1, box.x2, box.y2); + + sbox.x1 = box.x1 - dPriv->x; + sbox.y1 = box.y1 - dPriv->y; + + ctx->st->pipe->surface_copy( ctx->st->pipe, + FALSE, + dest, + box.x1, box.y1, + src, + sbox.x1, sbox.y1, + box.x2 - box.x1, + box.y2 - box.y1 ); + } +} + +/** + * Display a colorbuffer surface in an X window. + * Used for SwapBuffers and flushing front buffer rendering. + * + * \param dPriv the window/drawable to display into + * \param surf the surface to display + * \param rect optional subrect of surface to display (may be NULL). + */ +void +dri_display_surface(__DRIdrawablePrivate *dPriv, + struct pipe_surface *source, + const drm_clip_rect_t *rect) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct dri_screen *screen = dri_screen(dPriv->driScreenPriv); + struct dri_context *context = screen->dummy_context; + struct pipe_winsys *winsys = screen->winsys; + + if (!context) + return; + + if (drawable->last_swap_fence) { + winsys->fence_finish( winsys, + drawable->last_swap_fence, + 0 ); + + winsys->fence_reference( winsys, + &drawable->last_swap_fence, + NULL ); + } + + drawable->last_swap_fence = drawable->first_swap_fence; + drawable->first_swap_fence = NULL; + + /* The lock_hardware is required for the cliprects. Buffer offsets + * should work regardless. + */ + dri_lock_hardware(context, drawable); + { + if (dPriv->numClipRects) { + blit_swapbuffers( context, dPriv, source, rect ); + } + } + dri_unlock_hardware(context); + + if (drawble->stamp != drawable->dPriv->lastStamp) { + dri_update_window_size( dpriv ); + } +} + + + +/** + * This will be called a drawable is known to have moved/resized. + */ +void +dri_update_window_size(__DRIdrawablePrivate *dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + st_resize_framebuffer(drawable->stfb, dPriv->w, dPriv->h); + drawable->stamp = dPriv->lastStamp; +} + + + +void +dri_swap_buffers(__DRIdrawablePrivate * dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_surface *back_surf; + + assert(drawable); + assert(drawable->stfb); + + back_surf = st_get_framebuffer_surface(drawable->stfb, + ST_SURFACE_BACK_LEFT); + if (back_surf) { + st_notify_swapbuffers(drawable->stfb); + dri_display_surface(dPriv, back_surf, NULL); + st_notify_swapbuffers_complete(drawable->stfb); + } +} + + +/** + * Called via glXCopySubBufferMESA() to copy a subrect of the back + * buffer to the front buffer/screen. + */ +void +dri_copy_sub_buffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_surface *back_surf; + + assert(drawable); + assert(drawable->stfb); + + back_surf = st_get_framebuffer_surface(drawable->stfb, + ST_SURFACE_BACK_LEFT); + if (back_surf) { + drm_clip_rect_t rect; + rect.x1 = x; + rect.y1 = y; + rect.x2 = w; + rect.y2 = h; + + st_notify_swapbuffers(drawable->stfb); + dri_display_surface(dPriv, back_surf, &rect); + } +} + + + +/* + * The state tracker keeps track of whether the fake frontbuffer has + * been touched by any rendering since the last time we copied its + * contents to the real frontbuffer. Our task is easy: + */ +static void +dri_flush_frontbuffer( struct pipe_winsys *winsys, + struct pipe_surface *surf, + void *context_private) +{ + struct dri_context *dri = (struct dri_context *) context_private; + __DRIdrawablePrivate *dPriv = dri->driDrawable; + + dri_display_surface(dPriv, surf, NULL); +} + + + +/* Need to create a surface which wraps the front surface to support + * client-side swapbuffers. + */ +static void +dri_create_front_surface(struct dri_screen *screen, + struct pipe_winsys *winsys, + unsigned handle) +{ + struct pipe_screen *pipe_screen = screen->pipe_screen; + struct pipe_texture *texture; + struct pipe_texture templat; + struct pipe_surface *surface; + struct pipe_buffer *buffer; + unsigned pitch; + + assert(screen->front.cpp == 4); + +// buffer = dri_buffer_from_handle(screen->winsys, +// "front", handle); + + if (!buffer) + return; + + screen->front.buffer = dri_bo(buffer); + + memset(&templat, 0, sizeof(templat)); + templat.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + templat.target = PIPE_TEXTURE_2D; + templat.last_level = 0; + templat.depth[0] = 1; + templat.format = PIPE_FORMAT_A8R8G8B8_UNORM; + templat.width[0] = screen->front.width; + templat.height[0] = screen->front.height; + pf_get_block(templat.format, &templat.block); + pitch = screen->front.pitch; + + texture = pipe_screen->texture_blanket(pipe_screen, + &templat, + &pitch, + buffer); + + /* Unref the buffer we don't need it anyways */ + pipe_buffer_reference(screen, &buffer, NULL); + + surface = pipe_screen->get_tex_surface(pipe_screen, + texture, + 0, + 0, + 0, + PIPE_BUFFER_USAGE_GPU_WRITE); + + screen->front.texture = texture; + screen->front.surface = surface; +} diff --git a/src/gallium/state_trackers/glx/dri1/dri_swapbuffers.h b/src/gallium/state_trackers/glx/dri1/dri_swapbuffers.h new file mode 100644 index 00000000000..1b8cd857047 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri1/dri_swapbuffers.h @@ -0,0 +1,47 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef DRI_SWAPBUFFERS_H +#define DRI_SWAPBUFFERS_H + + +struct pipe_surface; + + +extern void dri_display_surface(__DRIdrawablePrivate * dPriv, + struct pipe_surface *surf, + const drm_clip_rect_t * rect); + +extern void dri_swap_buffers(__DRIdrawablePrivate * dPriv); + +extern void dri_copy_sub_buffer(__DRIdrawablePrivate * dPriv, + int x, int y, int w, int h); + +extern void dri_update_window_size(__DRIdrawablePrivate *dPriv); + + +#endif -- 2.30.2