From 29ca7d2c9488d13e496ec65b6e1e1bf1d53042c5 Mon Sep 17 00:00:00 2001 From: Emil Velikov Date: Tue, 17 Jun 2014 14:34:52 +0100 Subject: st/dri: merge dri/drm and dri/sw backends Move the driver_name to dri2/drisw and remove all the SPLIT_TAGETS mayhem. In the next step we'll unify the dri and dri-swrast targets, completing the gallium DRI megadriver. v2: Remove leftover st/dri Makefiles from CONFIG_FILES. Spotted by Thomas Helland. Signed-off-by: Emil Velikov Tested-by: Rob Clark Tested-by: Thomas Helland Acked-by: Tom Stellard --- src/gallium/state_trackers/dri/Makefile.am | 36 +- src/gallium/state_trackers/dri/Makefile.sources | 14 + src/gallium/state_trackers/dri/SConscript | 35 +- .../state_trackers/dri/common/dri_context.c | 276 ---- .../state_trackers/dri/common/dri_context.h | 98 -- .../state_trackers/dri/common/dri_drawable.c | 571 --------- .../state_trackers/dri/common/dri_drawable.h | 128 -- src/gallium/state_trackers/dri/common/dri_screen.c | 482 ------- src/gallium/state_trackers/dri/common/dri_screen.h | 156 --- src/gallium/state_trackers/dri/dri2.c | 1347 +++++++++++++++++++ src/gallium/state_trackers/dri/dri2_buffer.h | 22 + src/gallium/state_trackers/dri/dri_context.c | 276 ++++ src/gallium/state_trackers/dri/dri_context.h | 98 ++ src/gallium/state_trackers/dri/dri_drawable.c | 571 +++++++++ src/gallium/state_trackers/dri/dri_drawable.h | 128 ++ src/gallium/state_trackers/dri/dri_screen.c | 473 +++++++ src/gallium/state_trackers/dri/dri_screen.h | 157 +++ src/gallium/state_trackers/dri/drisw.c | 422 ++++++ src/gallium/state_trackers/dri/drm/Makefile.am | 46 - .../state_trackers/dri/drm/Makefile.sources | 5 - src/gallium/state_trackers/dri/drm/SConscript | 24 - src/gallium/state_trackers/dri/drm/dri2.c | 1354 -------------------- src/gallium/state_trackers/dri/drm/dri2_buffer.h | 22 - src/gallium/state_trackers/dri/drm/dri_context.c | 1 - src/gallium/state_trackers/dri/drm/dri_drawable.c | 1 - src/gallium/state_trackers/dri/drm/dri_screen.c | 1 - src/gallium/state_trackers/dri/sw/Makefile.am | 42 - src/gallium/state_trackers/dri/sw/Makefile.sources | 5 - src/gallium/state_trackers/dri/sw/SConscript | 23 - src/gallium/state_trackers/dri/sw/dri_context.c | 1 - src/gallium/state_trackers/dri/sw/dri_drawable.c | 1 - src/gallium/state_trackers/dri/sw/dri_screen.c | 1 - src/gallium/state_trackers/dri/sw/drisw.c | 422 ------ 33 files changed, 3572 insertions(+), 3667 deletions(-) create mode 100644 src/gallium/state_trackers/dri/Makefile.sources delete mode 100644 src/gallium/state_trackers/dri/common/dri_context.c delete mode 100644 src/gallium/state_trackers/dri/common/dri_context.h delete mode 100644 src/gallium/state_trackers/dri/common/dri_drawable.c delete mode 100644 src/gallium/state_trackers/dri/common/dri_drawable.h delete mode 100644 src/gallium/state_trackers/dri/common/dri_screen.c delete mode 100644 src/gallium/state_trackers/dri/common/dri_screen.h create mode 100644 src/gallium/state_trackers/dri/dri2.c create mode 100644 src/gallium/state_trackers/dri/dri2_buffer.h create mode 100644 src/gallium/state_trackers/dri/dri_context.c create mode 100644 src/gallium/state_trackers/dri/dri_context.h create mode 100644 src/gallium/state_trackers/dri/dri_drawable.c create mode 100644 src/gallium/state_trackers/dri/dri_drawable.h create mode 100644 src/gallium/state_trackers/dri/dri_screen.c create mode 100644 src/gallium/state_trackers/dri/dri_screen.h create mode 100644 src/gallium/state_trackers/dri/drisw.c delete mode 100644 src/gallium/state_trackers/dri/drm/Makefile.am delete mode 100644 src/gallium/state_trackers/dri/drm/Makefile.sources delete mode 100644 src/gallium/state_trackers/dri/drm/SConscript delete mode 100644 src/gallium/state_trackers/dri/drm/dri2.c delete mode 100644 src/gallium/state_trackers/dri/drm/dri2_buffer.h delete mode 120000 src/gallium/state_trackers/dri/drm/dri_context.c delete mode 120000 src/gallium/state_trackers/dri/drm/dri_drawable.c delete mode 120000 src/gallium/state_trackers/dri/drm/dri_screen.c delete mode 100644 src/gallium/state_trackers/dri/sw/Makefile.am delete mode 100644 src/gallium/state_trackers/dri/sw/Makefile.sources delete mode 100644 src/gallium/state_trackers/dri/sw/SConscript delete mode 120000 src/gallium/state_trackers/dri/sw/dri_context.c delete mode 120000 src/gallium/state_trackers/dri/sw/dri_drawable.c delete mode 120000 src/gallium/state_trackers/dri/sw/dri_screen.c delete mode 100644 src/gallium/state_trackers/dri/sw/drisw.c (limited to 'src/gallium/state_trackers/dri') diff --git a/src/gallium/state_trackers/dri/Makefile.am b/src/gallium/state_trackers/dri/Makefile.am index b89d02f2a2b..bda75c3f9b8 100644 --- a/src/gallium/state_trackers/dri/Makefile.am +++ b/src/gallium/state_trackers/dri/Makefile.am @@ -1,4 +1,5 @@ # Copyright © 2012 Intel Corporation +# Copyright © 2014 Emil Velikov # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), @@ -20,12 +21,39 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. -SUBDIRS = +include Makefile.sources +include $(top_srcdir)/src/gallium/Automake.inc + +AM_CPPFLAGS = \ + $(GALLIUM_PIPE_LOADER_DEFINES) \ + -DPIPE_SEARCH_DIR=\"$(libdir)/gallium-pipe\" \ + -I$(top_srcdir)/include \ + -I$(top_srcdir)/src/mapi \ + -I$(top_srcdir)/src/mesa \ + -I$(top_srcdir)/src/gallium/state_trackers/dri/common \ + -I$(top_srcdir)/src/mesa/drivers/dri/common \ + -I$(top_builddir)/src/mesa/drivers/dri/common \ + $(GALLIUM_CFLAGS) \ + $(LIBDRM_CFLAGS) \ + $(VISIBILITY_CFLAGS) + +if HAVE_GALLIUM_STATIC_TARGETS +AM_CPPFLAGS += \ + -DGALLIUM_STATIC_TARGETS=1 +endif # HAVE_GALLIUM_STATIC_TARGETS + +noinst_LTLIBRARIES = libdri.la +libdri_la_SOURCES = $(common_SOURCES) if HAVE_DRISW -SUBDIRS += sw +if !HAVE_DRI2 +AM_CPPFLAGS += \ + -D__NOT_HAVE_DRM_H endif +libdri_la_SOURCES += $(drisw_SOURCES) +endif + -if HAVE_LIBDRM -SUBDIRS += drm +if HAVE_DRI2 +libdri_la_SOURCES += $(dri2_SOURCES) endif diff --git a/src/gallium/state_trackers/dri/Makefile.sources b/src/gallium/state_trackers/dri/Makefile.sources new file mode 100644 index 00000000000..59677962c9e --- /dev/null +++ b/src/gallium/state_trackers/dri/Makefile.sources @@ -0,0 +1,14 @@ +common_SOURCES := \ + dri_context.c \ + dri_context.h \ + dri_drawable.c \ + dri_drawable.h \ + dri_screen.c \ + dri_screen.h + +dri2_SOURCES := \ + dri2.c \ + dri2_buffer.h + +drisw_SOURCES := \ + drisw.c diff --git a/src/gallium/state_trackers/dri/SConscript b/src/gallium/state_trackers/dri/SConscript index 7702d8e6323..89b035229bc 100644 --- a/src/gallium/state_trackers/dri/SConscript +++ b/src/gallium/state_trackers/dri/SConscript @@ -1,6 +1,35 @@ +####################################################################### +# SConscript for dri state_tracker + Import('*') -SConscript([ - 'sw/SConscript', - 'drm/SConscript', +env = env.Clone() + +# XXX: If HAVE_DRI2 +env.PkgUseModules(['DRM']) +# else +#env.Append(CPPDEFINES = [('__NOT_HAVE_DRM_H', '1')]) + +env.Append(CPPPATH = [ + '#/src/mapi', + '#/src/mesa', + '#/src/gallium/state_trackers/dri/common', + '#/src/mesa/drivers/dri/common', + xmlpool_options.dir.dir, # Dir to generated xmlpool/options.h ]) + +env.Append(CPPDEFINES = [('GALLIUM_STATIC_TARGETS', '1')]) + +sources = env.ParseSourceList('Makefile.sources', 'common_SOURCES') + +# XXX: if HAVE_DRISW +sources.append(env.ParseSourceList('Makefile.sources', 'drisw_SOURCES')) + +# XXX: if HAVE_DRI2 +sources.append(env.ParseSourceList('Makefile.sources', 'dri2_SOURCES')) + +st_dri = env.ConvenienceLibrary( + target = 'st_dri', + source = sources +) +Export('st_dri') diff --git a/src/gallium/state_trackers/dri/common/dri_context.c b/src/gallium/state_trackers/dri/common/dri_context.c deleted file mode 100644 index f6979a7c2d0..00000000000 --- a/src/gallium/state_trackers/dri/common/dri_context.c +++ /dev/null @@ -1,276 +0,0 @@ -/************************************************************************** - * - * 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 VMWARE 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. - * - **************************************************************************/ -/* - * Author: Keith Whitwell - * Author: Jakob Bornecrantz - */ - -#include "utils.h" - -#include "dri_screen.h" -#include "dri_drawable.h" -#include "dri_context.h" -#include "state_tracker/drm_driver.h" - -#include "pipe/p_context.h" -#include "state_tracker/st_context.h" - -static void -dri_fill_st_options(struct st_config_options *options, - const struct driOptionCache * optionCache) -{ - options->disable_blend_func_extended = - driQueryOptionb(optionCache, "disable_blend_func_extended"); - options->disable_glsl_line_continuations = - driQueryOptionb(optionCache, "disable_glsl_line_continuations"); - options->disable_shader_bit_encoding = - driQueryOptionb(optionCache, "disable_shader_bit_encoding"); - options->force_glsl_extensions_warn = - driQueryOptionb(optionCache, "force_glsl_extensions_warn"); - options->force_glsl_version = - driQueryOptioni(optionCache, "force_glsl_version"); - options->force_s3tc_enable = - driQueryOptionb(optionCache, "force_s3tc_enable"); -} - -GLboolean -dri_create_context(gl_api api, const struct gl_config * visual, - __DRIcontext * cPriv, - unsigned major_version, - unsigned minor_version, - uint32_t flags, - bool notify_reset, - unsigned *error, - void *sharedContextPrivate) -{ - __DRIscreen *sPriv = cPriv->driScreenPriv; - struct dri_screen *screen = dri_screen(sPriv); - struct st_api *stapi = screen->st_api; - struct dri_context *ctx = NULL; - struct st_context_iface *st_share = NULL; - struct st_context_attribs attribs; - enum st_context_error ctx_err = 0; - - memset(&attribs, 0, sizeof(attribs)); - switch (api) { - case API_OPENGLES: - attribs.profile = ST_PROFILE_OPENGL_ES1; - break; - case API_OPENGLES2: - attribs.profile = ST_PROFILE_OPENGL_ES2; - break; - case API_OPENGL_COMPAT: - case API_OPENGL_CORE: - attribs.profile = api == API_OPENGL_COMPAT ? ST_PROFILE_DEFAULT - : ST_PROFILE_OPENGL_CORE; - attribs.major = major_version; - attribs.minor = minor_version; - - if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) - attribs.flags |= ST_CONTEXT_FLAG_DEBUG; - - if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) - attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE; - break; - default: - *error = __DRI_CTX_ERROR_BAD_API; - goto fail; - } - - if (flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_FORWARD_COMPATIBLE)) { - *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; - goto fail; - } - - if (notify_reset) { - *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; - goto fail; - } - - if (sharedContextPrivate) { - st_share = ((struct dri_context *)sharedContextPrivate)->st; - } - - ctx = CALLOC_STRUCT(dri_context); - if (ctx == NULL) { - *error = __DRI_CTX_ERROR_NO_MEMORY; - goto fail; - } - - cPriv->driverPrivate = ctx; - ctx->cPriv = cPriv; - ctx->sPriv = sPriv; - - dri_fill_st_options(&attribs.options, &screen->optionCache); - dri_fill_st_visual(&attribs.visual, screen, visual); - ctx->st = stapi->create_context(stapi, &screen->base, &attribs, &ctx_err, - st_share); - if (ctx->st == NULL) { - switch (ctx_err) { - case ST_CONTEXT_SUCCESS: - *error = __DRI_CTX_ERROR_SUCCESS; - break; - case ST_CONTEXT_ERROR_NO_MEMORY: - *error = __DRI_CTX_ERROR_NO_MEMORY; - break; - case ST_CONTEXT_ERROR_BAD_API: - *error = __DRI_CTX_ERROR_BAD_API; - break; - case ST_CONTEXT_ERROR_BAD_VERSION: - *error = __DRI_CTX_ERROR_BAD_VERSION; - break; - case ST_CONTEXT_ERROR_BAD_FLAG: - *error = __DRI_CTX_ERROR_BAD_FLAG; - break; - case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE: - *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; - break; - case ST_CONTEXT_ERROR_UNKNOWN_FLAG: - *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; - break; - } - goto fail; - } - ctx->st->st_manager_private = (void *) ctx; - ctx->stapi = stapi; - - if (ctx->st->cso_context) { - ctx->pp = pp_init(ctx->st->pipe, screen->pp_enabled, ctx->st->cso_context); - ctx->hud = hud_create(ctx->st->pipe, ctx->st->cso_context); - } - - *error = __DRI_CTX_ERROR_SUCCESS; - return GL_TRUE; - - fail: - if (ctx && ctx->st) - ctx->st->destroy(ctx->st); - - free(ctx); - return GL_FALSE; -} - -void -dri_destroy_context(__DRIcontext * cPriv) -{ - struct dri_context *ctx = dri_context(cPriv); - - if (ctx->hud) { - hud_destroy(ctx->hud); - } - - /* No particular reason to wait for command completion before - * destroying a context, but we flush the context here - * to avoid having to add code elsewhere to cope with flushing a - * partially destroyed context. - */ - ctx->st->flush(ctx->st, 0, NULL); - ctx->st->destroy(ctx->st); - - if (ctx->pp) - pp_free(ctx->pp); - - free(ctx); -} - -GLboolean -dri_unbind_context(__DRIcontext * cPriv) -{ - /* dri_util.c ensures cPriv is not null */ - struct dri_screen *screen = dri_screen(cPriv->driScreenPriv); - struct dri_context *ctx = dri_context(cPriv); - struct st_api *stapi = screen->st_api; - - if (--ctx->bind_count == 0) { - if (ctx->st == ctx->stapi->get_current(ctx->stapi)) { - /* For conformance, unbind is supposed to flush the context. - * However, if we do it here we might end up flushing a partially - * destroyed context. Instead, we flush in dri_make_current and - * in dri_destroy_context which should cover all the cases. - */ - stapi->make_current(stapi, NULL, NULL, NULL); - } - } - - return GL_TRUE; -} - -GLboolean -dri_make_current(__DRIcontext * cPriv, - __DRIdrawable * driDrawPriv, - __DRIdrawable * driReadPriv) -{ - /* dri_util.c ensures cPriv is not null */ - struct dri_context *ctx = dri_context(cPriv); - struct dri_drawable *draw = dri_drawable(driDrawPriv); - struct dri_drawable *read = dri_drawable(driReadPriv); - struct st_context_iface *old_st = ctx->stapi->get_current(ctx->stapi); - - /* Flush the old context here so we don't have to flush on unbind() */ - if (old_st && old_st != ctx->st) - old_st->flush(old_st, ST_FLUSH_FRONT, NULL); - - ++ctx->bind_count; - - if (!draw && !read) - return ctx->stapi->make_current(ctx->stapi, ctx->st, NULL, NULL); - else if (!draw || !read) - return GL_FALSE; - - if (ctx->dPriv != driDrawPriv) { - ctx->dPriv = driDrawPriv; - draw->texture_stamp = driDrawPriv->lastStamp - 1; - } - if (ctx->rPriv != driReadPriv) { - ctx->rPriv = driReadPriv; - read->texture_stamp = driReadPriv->lastStamp - 1; - } - - ctx->stapi->make_current(ctx->stapi, ctx->st, &draw->base, &read->base); - - // This is ok to call here. If they are already init, it's a no-op. - if (draw->textures[ST_ATTACHMENT_BACK_LEFT] && draw->textures[ST_ATTACHMENT_DEPTH_STENCIL] - && ctx->pp) - pp_init_fbos(ctx->pp, draw->textures[ST_ATTACHMENT_BACK_LEFT]->width0, - draw->textures[ST_ATTACHMENT_BACK_LEFT]->height0); - - return GL_TRUE; -} - -struct dri_context * -dri_get_current(__DRIscreen *sPriv) -{ - struct dri_screen *screen = dri_screen(sPriv); - struct st_api *stapi = screen->st_api; - struct st_context_iface *st; - - st = stapi->get_current(stapi); - - return (struct dri_context *) st ? st->st_manager_private : NULL; -} - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/common/dri_context.h b/src/gallium/state_trackers/dri/common/dri_context.h deleted file mode 100644 index 56dfa2ccc70..00000000000 --- a/src/gallium/state_trackers/dri/common/dri_context.h +++ /dev/null @@ -1,98 +0,0 @@ -/************************************************************************** - * - * 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 VMWARE 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. - * - **************************************************************************/ -/* - * Author: Keith Whitwell - * Author: Jakob Bornecrantz - */ - -#ifndef DRI_CONTEXT_H -#define DRI_CONTEXT_H - -#include "dri_util.h" -#include "pipe/p_compiler.h" -#include "hud/hud_context.h" - -struct pipe_context; -struct pipe_fence; -struct st_api; -struct st_context_iface; -struct dri_drawable; - -struct dri_context -{ - /* dri */ - __DRIscreen *sPriv; - __DRIcontext *cPriv; - __DRIdrawable *dPriv; - __DRIdrawable *rPriv; - - unsigned int bind_count; - - /* gallium */ - struct st_api *stapi; - struct st_context_iface *st; - struct pp_queue_t *pp; - struct hud_context *hud; -}; - -static INLINE struct dri_context * -dri_context(__DRIcontext * driContextPriv) -{ - if (!driContextPriv) - return NULL; - return (struct dri_context *)driContextPriv->driverPrivate; -} - -/*********************************************************************** - * dri_context.c - */ -void dri_destroy_context(__DRIcontext * driContextPriv); - -boolean dri_unbind_context(__DRIcontext * driContextPriv); - -boolean -dri_make_current(__DRIcontext * driContextPriv, - __DRIdrawable * driDrawPriv, - __DRIdrawable * driReadPriv); - -struct dri_context * -dri_get_current(__DRIscreen * driScreenPriv); - -boolean -dri_create_context(gl_api api, - const struct gl_config * visual, - __DRIcontext * driContextPriv, - unsigned major_version, - unsigned minor_version, - uint32_t flags, - bool notify_reset, - unsigned *error, - void *sharedContextPrivate); - -#endif - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.c b/src/gallium/state_trackers/dri/common/dri_drawable.c deleted file mode 100644 index b7df053594c..00000000000 --- a/src/gallium/state_trackers/dri/common/dri_drawable.c +++ /dev/null @@ -1,571 +0,0 @@ -/************************************************************************** - * - * 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 VMWARE 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. - * - **************************************************************************/ -/* - * Author: Keith Whitwell - * Author: Jakob Bornecrantz - */ - -#include "dri_screen.h" -#include "dri_context.h" -#include "dri_drawable.h" - -#include "pipe/p_screen.h" -#include "util/u_format.h" -#include "util/u_memory.h" -#include "util/u_inlines.h" - -static void -swap_fences_unref(struct dri_drawable *draw); - -static boolean -dri_st_framebuffer_validate(struct st_context_iface *stctx, - struct st_framebuffer_iface *stfbi, - const enum st_attachment_type *statts, - unsigned count, - struct pipe_resource **out) -{ - struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; - struct dri_drawable *drawable = - (struct dri_drawable *) stfbi->st_manager_private; - struct dri_screen *screen = dri_screen(drawable->sPriv); - unsigned statt_mask, new_mask; - boolean new_stamp; - int i; - unsigned int lastStamp; - struct pipe_resource **textures = - drawable->stvis.samples > 1 ? drawable->msaa_textures - : drawable->textures; - - statt_mask = 0x0; - for (i = 0; i < count; i++) - statt_mask |= (1 << statts[i]); - - /* record newly allocated textures */ - new_mask = (statt_mask & ~drawable->texture_mask); - - /* - * dPriv->dri2.stamp is the server stamp. dPriv->lastStamp is the - * client stamp. It has the value of the server stamp when last - * checked. - */ - do { - lastStamp = drawable->dPriv->lastStamp; - new_stamp = (drawable->texture_stamp != lastStamp); - - if (new_stamp || new_mask || screen->broken_invalidate) { - if (new_stamp && drawable->update_drawable_info) - drawable->update_drawable_info(drawable); - - drawable->allocate_textures(ctx, drawable, statts, count); - - /* add existing textures */ - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - if (textures[i]) - statt_mask |= (1 << i); - } - - drawable->texture_stamp = lastStamp; - drawable->texture_mask = statt_mask; - } - } while (lastStamp != drawable->dPriv->lastStamp); - - if (!out) - return TRUE; - - /* Set the window-system buffers for the state tracker. */ - for (i = 0; i < count; i++) { - out[i] = NULL; - pipe_resource_reference(&out[i], textures[statts[i]]); - } - - return TRUE; -} - -static boolean -dri_st_framebuffer_flush_front(struct st_context_iface *stctx, - struct st_framebuffer_iface *stfbi, - enum st_attachment_type statt) -{ - struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; - struct dri_drawable *drawable = - (struct dri_drawable *) stfbi->st_manager_private; - - /* XXX remove this and just set the correct one on the framebuffer */ - drawable->flush_frontbuffer(ctx, drawable, statt); - - return TRUE; -} - -/** - * This is called when we need to set up GL rendering to a new X window. - */ -boolean -dri_create_buffer(__DRIscreen * sPriv, - __DRIdrawable * dPriv, - const struct gl_config * visual, boolean isPixmap) -{ - struct dri_screen *screen = sPriv->driverPrivate; - struct dri_drawable *drawable = NULL; - - if (isPixmap) - goto fail; /* not implemented */ - - drawable = CALLOC_STRUCT(dri_drawable); - if (drawable == NULL) - goto fail; - - dri_fill_st_visual(&drawable->stvis, screen, visual); - - /* setup the st_framebuffer_iface */ - drawable->base.visual = &drawable->stvis; - drawable->base.flush_front = dri_st_framebuffer_flush_front; - drawable->base.validate = dri_st_framebuffer_validate; - drawable->base.st_manager_private = (void *) drawable; - - drawable->screen = screen; - drawable->sPriv = sPriv; - drawable->dPriv = dPriv; - drawable->desired_fences = screen->default_throttle_frames; - if (drawable->desired_fences > DRI_SWAP_FENCES_MAX) - drawable->desired_fences = DRI_SWAP_FENCES_MAX; - - dPriv->driverPrivate = (void *)drawable; - p_atomic_set(&drawable->base.stamp, 1); - - return GL_TRUE; -fail: - FREE(drawable); - return GL_FALSE; -} - -void -dri_destroy_buffer(__DRIdrawable * dPriv) -{ - struct dri_drawable *drawable = dri_drawable(dPriv); - int i; - - pipe_surface_reference(&drawable->drisw_surface, NULL); - - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) - pipe_resource_reference(&drawable->textures[i], NULL); - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) - pipe_resource_reference(&drawable->msaa_textures[i], NULL); - - swap_fences_unref(drawable); - - FREE(drawable); -} - -/** - * Validate the texture at an attachment. Allocate the texture if it does not - * exist. Used by the TFP extension. - */ -static void -dri_drawable_validate_att(struct dri_context *ctx, - struct dri_drawable *drawable, - enum st_attachment_type statt) -{ - enum st_attachment_type statts[ST_ATTACHMENT_COUNT]; - unsigned i, count = 0; - - /* check if buffer already exists */ - if (drawable->texture_mask & (1 << statt)) - return; - - /* make sure DRI2 does not destroy existing buffers */ - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - if (drawable->texture_mask & (1 << i)) { - statts[count++] = i; - } - } - statts[count++] = statt; - - drawable->texture_stamp = drawable->dPriv->lastStamp - 1; - - drawable->base.validate(ctx->st, &drawable->base, statts, count, NULL); -} - -/** - * These are used for GLX_EXT_texture_from_pixmap - */ -static void -dri_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, - GLint format, __DRIdrawable *dPriv) -{ - struct dri_context *ctx = dri_context(pDRICtx); - struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_resource *pt; - - dri_drawable_validate_att(ctx, drawable, ST_ATTACHMENT_FRONT_LEFT); - - /* Use the pipe resource associated with the X drawable */ - pt = drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; - - if (pt) { - enum pipe_format internal_format = pt->format; - - if (format == __DRI_TEXTURE_FORMAT_RGB) { - /* only need to cover the formats recognized by dri_fill_st_visual */ - switch (internal_format) { - case PIPE_FORMAT_B8G8R8A8_UNORM: - internal_format = PIPE_FORMAT_B8G8R8X8_UNORM; - break; - case PIPE_FORMAT_A8R8G8B8_UNORM: - internal_format = PIPE_FORMAT_X8R8G8B8_UNORM; - break; - default: - break; - } - } - - drawable->update_tex_buffer(drawable, ctx, pt); - - ctx->st->teximage(ctx->st, - (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT, - 0, internal_format, pt, FALSE); - } -} - -static void -dri_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, - __DRIdrawable *dPriv) -{ - dri_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); -} - -const __DRItexBufferExtension driTexBufferExtension = { - .base = { __DRI_TEX_BUFFER, 2 }, - - .setTexBuffer = dri_set_tex_buffer, - .setTexBuffer2 = dri_set_tex_buffer2, - .releaseTexBuffer = NULL, -}; - -/** - * Get the format and binding of an attachment. - */ -void -dri_drawable_get_format(struct dri_drawable *drawable, - enum st_attachment_type statt, - enum pipe_format *format, - unsigned *bind) -{ - switch (statt) { - case ST_ATTACHMENT_FRONT_LEFT: - case ST_ATTACHMENT_BACK_LEFT: - case ST_ATTACHMENT_FRONT_RIGHT: - case ST_ATTACHMENT_BACK_RIGHT: - *format = drawable->stvis.color_format; - *bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; - break; - case ST_ATTACHMENT_DEPTH_STENCIL: - *format = drawable->stvis.depth_stencil_format; - *bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ - break; - default: - *format = PIPE_FORMAT_NONE; - *bind = 0; - break; - } -} - - -/** - * swap_fences_pop_front - pull a fence from the throttle queue - * - * If the throttle queue is filled to the desired number of fences, - * pull fences off the queue until the number is less than the desired - * number of fences, and return the last fence pulled. - */ -static struct pipe_fence_handle * -swap_fences_pop_front(struct dri_drawable *draw) -{ - struct pipe_screen *screen = draw->screen->base.screen; - struct pipe_fence_handle *fence = NULL; - - if (draw->desired_fences == 0) - return NULL; - - if (draw->cur_fences >= draw->desired_fences) { - screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]); - screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL); - draw->tail &= DRI_SWAP_FENCES_MASK; - --draw->cur_fences; - } - return fence; -} - - -/** - * swap_fences_push_back - push a fence onto the throttle queue - * - * push a fence onto the throttle queue and pull fences of the queue - * so that the desired number of fences are on the queue. - */ -static void -swap_fences_push_back(struct dri_drawable *draw, - struct pipe_fence_handle *fence) -{ - struct pipe_screen *screen = draw->screen->base.screen; - - if (!fence || draw->desired_fences == 0) - return; - - while(draw->cur_fences == draw->desired_fences) - swap_fences_pop_front(draw); - - draw->cur_fences++; - screen->fence_reference(screen, &draw->swap_fences[draw->head++], - fence); - draw->head &= DRI_SWAP_FENCES_MASK; -} - - -/** - * swap_fences_unref - empty the throttle queue - * - * pulls fences of the throttle queue until it is empty. - */ -static void -swap_fences_unref(struct dri_drawable *draw) -{ - struct pipe_screen *screen = draw->screen->base.screen; - - while(draw->cur_fences) { - screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL); - draw->tail &= DRI_SWAP_FENCES_MASK; - --draw->cur_fences; - } -} - -void -dri_pipe_blit(struct pipe_context *pipe, - struct pipe_resource *dst, - struct pipe_resource *src) -{ - struct pipe_blit_info blit; - - if (!dst || !src) - return; - - /* From the GL spec, version 4.2, section 4.1.11 (Additional Multisample - * Fragment Operations): - * - * If a framebuffer object is not bound, after all operations have - * been completed on the multisample buffer, the sample values for - * each color in the multisample buffer are combined to produce a - * single color value, and that value is written into the - * corresponding color buffers selected by DrawBuffer or - * DrawBuffers. An implementation may defer the writing of the color - * buffers until a later time, but the state of the framebuffer must - * behave as if the color buffers were updated as each fragment was - * processed. The method of combination is not specified. If the - * framebuffer contains sRGB values, then it is recommended that the - * an average of sample values is computed in a linearized space, as - * for blending (see section 4.1.7). - * - * In other words, to do a resolve operation in a linear space, we have - * to set sRGB formats if the original resources were sRGB, so don't use - * util_format_linear. - */ - - memset(&blit, 0, sizeof(blit)); - blit.dst.resource = dst; - blit.dst.box.width = dst->width0; - blit.dst.box.height = dst->height0; - blit.dst.box.depth = 1; - blit.dst.format = dst->format; - blit.src.resource = src; - blit.src.box.width = src->width0; - blit.src.box.height = src->height0; - blit.src.box.depth = 1; - blit.src.format = src->format; - blit.mask = PIPE_MASK_RGBA; - blit.filter = PIPE_TEX_FILTER_NEAREST; - - pipe->blit(pipe, &blit); -} - -static void -dri_postprocessing(struct dri_context *ctx, - struct dri_drawable *drawable, - enum st_attachment_type att) -{ - struct pipe_resource *src = drawable->textures[att]; - struct pipe_resource *zsbuf = drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]; - - if (ctx->pp && src && zsbuf) - pp_run(ctx->pp, src, src, zsbuf); -} - -/** - * DRI2 flush extension, the flush_with_flags function. - * - * \param context the context - * \param drawable the drawable to flush - * \param flags a combination of _DRI2_FLUSH_xxx flags - * \param throttle_reason the reason for throttling, 0 = no throttling - */ -void -dri_flush(__DRIcontext *cPriv, - __DRIdrawable *dPriv, - unsigned flags, - enum __DRI2throttleReason reason) -{ - struct dri_context *ctx = dri_context(cPriv); - struct dri_drawable *drawable = dri_drawable(dPriv); - unsigned flush_flags; - boolean swap_msaa_buffers = FALSE; - - if (!ctx) { - assert(0); - return; - } - - if (drawable) { - /* prevent recursion */ - if (drawable->flushing) - return; - - drawable->flushing = TRUE; - } - else { - flags &= ~__DRI2_FLUSH_DRAWABLE; - } - - /* Flush the drawable. */ - if ((flags & __DRI2_FLUSH_DRAWABLE) && - drawable->textures[ST_ATTACHMENT_BACK_LEFT]) { - struct pipe_context *pipe = ctx->st->pipe; - - if (drawable->stvis.samples > 1 && - reason == __DRI2_THROTTLE_SWAPBUFFER) { - /* Resolve the MSAA back buffer. */ - dri_pipe_blit(ctx->st->pipe, - drawable->textures[ST_ATTACHMENT_BACK_LEFT], - drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]); - - if (drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] && - drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]) { - swap_msaa_buffers = TRUE; - } - - /* FRONT_LEFT is resolved in drawable->flush_frontbuffer. */ - } - - dri_postprocessing(ctx, drawable, ST_ATTACHMENT_BACK_LEFT); - - if (ctx->hud) { - hud_draw(ctx->hud, drawable->textures[ST_ATTACHMENT_BACK_LEFT]); - } - - pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_BACK_LEFT]); - } - - flush_flags = 0; - if (flags & __DRI2_FLUSH_CONTEXT) - flush_flags |= ST_FLUSH_FRONT; - if (reason == __DRI2_THROTTLE_SWAPBUFFER) - flush_flags |= ST_FLUSH_END_OF_FRAME; - - /* Flush the context and throttle if needed. */ - if (dri_screen(ctx->sPriv)->throttling_enabled && - drawable && - (reason == __DRI2_THROTTLE_SWAPBUFFER || - reason == __DRI2_THROTTLE_FLUSHFRONT)) { - /* Throttle. - * - * This pulls a fence off the throttling queue and waits for it if the - * number of fences on the throttling queue has reached the desired - * number. - * - * Then flushes to insert a fence at the current rendering position, and - * pushes that fence on the queue. This requires that the st_context_iface - * flush method returns a fence even if there are no commands to flush. - */ - struct pipe_screen *screen = drawable->screen->base.screen; - struct pipe_fence_handle *fence; - - fence = swap_fences_pop_front(drawable); - if (fence) { - (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE); - screen->fence_reference(screen, &fence, NULL); - } - - ctx->st->flush(ctx->st, flush_flags, &fence); - - if (fence) { - swap_fences_push_back(drawable, fence); - screen->fence_reference(screen, &fence, NULL); - } - } - else if (flags & (__DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_CONTEXT)) { - ctx->st->flush(ctx->st, flush_flags, NULL); - } - - if (drawable) { - drawable->flushing = FALSE; - } - - /* Swap the MSAA front and back buffers, so that reading - * from the front buffer after SwapBuffers returns what was - * in the back buffer. - */ - if (swap_msaa_buffers) { - struct pipe_resource *tmp = - drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]; - - drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] = - drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]; - drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT] = tmp; - - /* Now that we have swapped the buffers, this tells the state - * tracker to revalidate the framebuffer. - */ - p_atomic_inc(&drawable->base.stamp); - } -} - -/** - * dri_throttle - A DRI2ThrottleExtension throttling function. - */ -static void -dri_throttle(__DRIcontext *cPriv, __DRIdrawable *dPriv, - enum __DRI2throttleReason reason) -{ - dri_flush(cPriv, dPriv, 0, reason); -} - - -const __DRI2throttleExtension dri2ThrottleExtension = { - .base = { __DRI2_THROTTLE, 1 }, - - .throttle = dri_throttle, -}; - - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/common/dri_drawable.h b/src/gallium/state_trackers/dri/common/dri_drawable.h deleted file mode 100644 index c5142181e89..00000000000 --- a/src/gallium/state_trackers/dri/common/dri_drawable.h +++ /dev/null @@ -1,128 +0,0 @@ -/************************************************************************** - * - * 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 VMWARE 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_DRAWABLE_H -#define DRI_DRAWABLE_H - -#include "pipe/p_compiler.h" -#include "pipe/p_format.h" -#include "state_tracker/st_api.h" - -struct pipe_surface; -struct st_framebuffer; -struct dri_context; - -#define DRI_SWAP_FENCES_MAX 4 -#define DRI_SWAP_FENCES_MASK 3 -#define DRI_SWAP_FENCES_DEFAULT 1 - -struct dri_drawable -{ - struct st_framebuffer_iface base; - struct st_visual stvis; - - struct dri_screen *screen; - - /* dri */ - __DRIdrawable *dPriv; - __DRIscreen *sPriv; - - __DRIbuffer old[8]; - unsigned old_num; - unsigned old_w; - unsigned old_h; - - struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; - struct pipe_resource *msaa_textures[ST_ATTACHMENT_COUNT]; - unsigned int texture_mask, texture_stamp; - - struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX]; - unsigned int cur_fences; - unsigned int head; - unsigned int tail; - unsigned int desired_fences; - boolean flushing; /* prevents recursion in dri_flush */ - - /* used only by DRISW */ - struct pipe_surface *drisw_surface; - - /* hooks filled in by dri2 & drisw */ - void (*allocate_textures)(struct dri_context *ctx, - struct dri_drawable *drawable, - const enum st_attachment_type *statts, - unsigned count); - - void (*update_drawable_info)(struct dri_drawable *drawable); - - void (*flush_frontbuffer)(struct dri_context *ctx, - struct dri_drawable *drawable, - enum st_attachment_type statt); - - void (*update_tex_buffer)(struct dri_drawable *drawable, - struct dri_context *ctx, - struct pipe_resource *res); -}; - -static INLINE struct dri_drawable * -dri_drawable(__DRIdrawable * driDrawPriv) -{ - return (struct dri_drawable *) (driDrawPriv) - ? driDrawPriv->driverPrivate : NULL; -} - -/*********************************************************************** - * dri_drawable.c - */ -boolean -dri_create_buffer(__DRIscreen * sPriv, - __DRIdrawable * dPriv, - const struct gl_config * visual, boolean isPixmap); - -void dri_destroy_buffer(__DRIdrawable * dPriv); - -void -dri_drawable_get_format(struct dri_drawable *drawable, - enum st_attachment_type statt, - enum pipe_format *format, - unsigned *bind); - -void -dri_pipe_blit(struct pipe_context *pipe, - struct pipe_resource *dst, - struct pipe_resource *src); - -void -dri_flush(__DRIcontext *cPriv, - __DRIdrawable *dPriv, - unsigned flags, - enum __DRI2throttleReason reason); - -extern const __DRItexBufferExtension driTexBufferExtension; -extern const __DRI2throttleExtension dri2ThrottleExtension; -#endif - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/common/dri_screen.c b/src/gallium/state_trackers/dri/common/dri_screen.c deleted file mode 100644 index dceb628015e..00000000000 --- a/src/gallium/state_trackers/dri/common/dri_screen.c +++ /dev/null @@ -1,482 +0,0 @@ -/************************************************************************** - * - * 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 VMWARE 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. - * - **************************************************************************/ -/* - * Author: Keith Whitwell - * Author: Jakob Bornecrantz - */ - -#include "utils.h" -#include "xmlpool.h" - -#include "dri_screen.h" - -#include "util/u_inlines.h" -#include "pipe/p_screen.h" -#include "pipe/p_format.h" -#include "pipe-loader/pipe_loader.h" -#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ -#include "state_tracker/drm_driver.h" - -#include "util/u_debug.h" -#include "util/u_format_s3tc.h" - -#define MSAA_VISUAL_MAX_SAMPLES 32 - -#undef false - -const __DRIconfigOptionsExtension gallium_config_options = { - .base = { __DRI_CONFIG_OPTIONS, 1 }, - .xml = - - DRI_CONF_BEGIN - DRI_CONF_SECTION_QUALITY - DRI_CONF_FORCE_S3TC_ENABLE("false") - DRI_CONF_PP_CELSHADE(0) - DRI_CONF_PP_NORED(0) - DRI_CONF_PP_NOGREEN(0) - DRI_CONF_PP_NOBLUE(0) - DRI_CONF_PP_JIMENEZMLAA(0, 0, 32) - DRI_CONF_PP_JIMENEZMLAA_COLOR(0, 0, 32) - DRI_CONF_SECTION_END - - DRI_CONF_SECTION_DEBUG - DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN("false") - DRI_CONF_DISABLE_GLSL_LINE_CONTINUATIONS("false") - DRI_CONF_DISABLE_BLEND_FUNC_EXTENDED("false") - DRI_CONF_DISABLE_SHADER_BIT_ENCODING("false") - DRI_CONF_FORCE_GLSL_VERSION(0) - DRI_CONF_SECTION_END - - DRI_CONF_SECTION_MISCELLANEOUS - DRI_CONF_ALWAYS_HAVE_DEPTH_BUFFER("false") - DRI_CONF_SECTION_END - DRI_CONF_END -}; - -#define false 0 - -static const __DRIconfig ** -dri_fill_in_modes(struct dri_screen *screen) -{ - static const mesa_format mesa_formats[3] = { - MESA_FORMAT_B8G8R8A8_UNORM, - MESA_FORMAT_B8G8R8X8_UNORM, - MESA_FORMAT_B5G6R5_UNORM, - }; - static const enum pipe_format pipe_formats[3] = { - PIPE_FORMAT_BGRA8888_UNORM, - PIPE_FORMAT_BGRX8888_UNORM, - PIPE_FORMAT_B5G6R5_UNORM, - }; - mesa_format format; - __DRIconfig **configs = NULL; - uint8_t depth_bits_array[5]; - uint8_t stencil_bits_array[5]; - unsigned depth_buffer_factor; - unsigned msaa_samples_max; - unsigned i; - struct pipe_screen *p_screen = screen->base.screen; - boolean pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32; - - static const GLenum back_buffer_modes[] = { - GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML - }; - - if (driQueryOptionb(&screen->optionCache, "always_have_depth_buffer")) { - /* all visuals will have a depth buffer */ - depth_buffer_factor = 0; - } - else { - depth_bits_array[0] = 0; - stencil_bits_array[0] = 0; - depth_buffer_factor = 1; - } - - msaa_samples_max = (screen->st_api->feature_mask & ST_API_FEATURE_MS_VISUALS_MASK) - ? MSAA_VISUAL_MAX_SAMPLES : 1; - - pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_DEPTH_STENCIL); - pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_DEPTH_STENCIL); - pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24_UNORM_S8_UINT, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_DEPTH_STENCIL); - pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8_UINT_Z24_UNORM, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_DEPTH_STENCIL); - pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_DEPTH_STENCIL); - pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM, - PIPE_TEXTURE_2D, 0, - PIPE_BIND_DEPTH_STENCIL); - - if (pf_z16) { - depth_bits_array[depth_buffer_factor] = 16; - stencil_bits_array[depth_buffer_factor++] = 0; - } - if (pf_x8z24 || pf_z24x8) { - depth_bits_array[depth_buffer_factor] = 24; - stencil_bits_array[depth_buffer_factor++] = 0; - screen->d_depth_bits_last = pf_x8z24; - } - if (pf_s8z24 || pf_z24s8) { - depth_bits_array[depth_buffer_factor] = 24; - stencil_bits_array[depth_buffer_factor++] = 8; - screen->sd_depth_bits_last = pf_s8z24; - } - if (pf_z32) { - depth_bits_array[depth_buffer_factor] = 32; - stencil_bits_array[depth_buffer_factor++] = 0; - } - - assert(Elements(mesa_formats) == Elements(pipe_formats)); - - /* Add configs. */ - for (format = 0; format < Elements(mesa_formats); format++) { - __DRIconfig **new_configs = NULL; - unsigned num_msaa_modes = 0; /* includes a single-sample mode */ - uint8_t msaa_modes[MSAA_VISUAL_MAX_SAMPLES]; - - for (i = 1; i <= msaa_samples_max; i++) { - int samples = i > 1 ? i : 0; - - if (p_screen->is_format_supported(p_screen, pipe_formats[format], - PIPE_TEXTURE_2D, samples, - PIPE_BIND_RENDER_TARGET)) { - msaa_modes[num_msaa_modes++] = samples; - } - } - - if (num_msaa_modes) { - /* Single-sample configs with an accumulation buffer. */ - new_configs = driCreateConfigs(mesa_formats[format], - depth_bits_array, stencil_bits_array, - depth_buffer_factor, back_buffer_modes, - Elements(back_buffer_modes), - msaa_modes, 1, - GL_TRUE); - configs = driConcatConfigs(configs, new_configs); - - /* Multi-sample configs without an accumulation buffer. */ - if (num_msaa_modes > 1) { - new_configs = driCreateConfigs(mesa_formats[format], - depth_bits_array, stencil_bits_array, - depth_buffer_factor, back_buffer_modes, - Elements(back_buffer_modes), - msaa_modes+1, num_msaa_modes-1, - GL_FALSE); - configs = driConcatConfigs(configs, new_configs); - } - } - } - - if (configs == NULL) { - debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__); - return NULL; - } - - return (const __DRIconfig **)configs; -} - -/* The Gallium way to force MSAA. */ -DEBUG_GET_ONCE_NUM_OPTION(msaa, "GALLIUM_MSAA", 0); - -/* The NVIDIA way to force MSAA. The same variable is used by the NVIDIA - * driver. */ -DEBUG_GET_ONCE_NUM_OPTION(msaa_nv, "__GL_FSAA_MODE", 0); - -static void -dri_force_msaa_visual(struct st_visual *stvis, - struct pipe_screen *screen) -{ - int i; - int samples = debug_get_option_msaa(); - - if (!samples) - samples = debug_get_option_msaa_nv(); - - if (samples <= 1) - return; /* nothing to do */ - - /* Choose a supported sample count greater than or equal to samples. */ - for (i = samples; i <= MSAA_VISUAL_MAX_SAMPLES; i++) { - if (screen->is_format_supported(screen, stvis->color_format, - PIPE_TEXTURE_2D, i, - PIPE_BIND_RENDER_TARGET)) { - stvis->samples = i; - break; - } - } -} - -/** - * Roughly the converse of dri_fill_in_modes. - */ -void -dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen, - const struct gl_config *mode) -{ - memset(stvis, 0, sizeof(*stvis)); - - if (!mode) - return; - - if (mode->redBits == 8) { - if (mode->alphaBits == 8) - stvis->color_format = PIPE_FORMAT_BGRA8888_UNORM; - else - stvis->color_format = PIPE_FORMAT_BGRX8888_UNORM; - } else { - stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM; - } - - if (mode->sampleBuffers) { - stvis->samples = mode->samples; - } - else { - /* This must be done after stvis->color_format is set. */ - dri_force_msaa_visual(stvis, screen->base.screen); - } - - switch (mode->depthBits) { - default: - case 0: - stvis->depth_stencil_format = PIPE_FORMAT_NONE; - break; - case 16: - stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; - break; - case 24: - if (mode->stencilBits == 0) { - stvis->depth_stencil_format = (screen->d_depth_bits_last) ? - PIPE_FORMAT_Z24X8_UNORM: - PIPE_FORMAT_X8Z24_UNORM; - } else { - stvis->depth_stencil_format = (screen->sd_depth_bits_last) ? - PIPE_FORMAT_Z24_UNORM_S8_UINT: - PIPE_FORMAT_S8_UINT_Z24_UNORM; - } - break; - case 32: - stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM; - break; - } - - stvis->accum_format = (mode->haveAccumBuffer) ? - PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; - - stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; - stvis->render_buffer = ST_ATTACHMENT_FRONT_LEFT; - if (mode->doubleBufferMode) { - stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; - stvis->render_buffer = ST_ATTACHMENT_BACK_LEFT; - } - if (mode->stereoMode) { - stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; - if (mode->doubleBufferMode) - stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; - } - - if (mode->haveDepthBuffer || mode->haveStencilBuffer) - stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; - /* let the state tracker allocate the accum buffer */ -} - -static boolean -dri_get_egl_image(struct st_manager *smapi, - void *egl_image, - struct st_egl_image *stimg) -{ - struct dri_screen *screen = (struct dri_screen *)smapi; - __DRIimage *img = NULL; - - if (screen->lookup_egl_image) { - img = screen->lookup_egl_image(screen, egl_image); - } - - if (!img) - return FALSE; - - stimg->texture = NULL; - pipe_resource_reference(&stimg->texture, img->texture); - stimg->level = img->level; - stimg->layer = img->layer; - - return TRUE; -} - -static int -dri_get_param(struct st_manager *smapi, - enum st_manager_param param) -{ - struct dri_screen *screen = (struct dri_screen *)smapi; - - switch(param) { - case ST_MANAGER_BROKEN_INVALIDATE: - return screen->broken_invalidate; - default: - return 0; - } -} - -static void -dri_destroy_option_cache(struct dri_screen * screen) -{ - int i; - - if (screen->optionCache.info) { - for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) { - free(screen->optionCache.info[i].name); - free(screen->optionCache.info[i].ranges); - } - free(screen->optionCache.info); - } - - free(screen->optionCache.values); - - /* Default values are copied to screen->optionCache->values in - * initOptionCache. The info field, however, is a pointer copy, so don't free - * that twice. - */ - free(screen->optionCacheDefaults.values); -} - -void -dri_destroy_screen_helper(struct dri_screen * screen) -{ - if (screen->st_api && screen->st_api->destroy) - screen->st_api->destroy(screen->st_api); - - if (screen->base.screen) - screen->base.screen->destroy(screen->base.screen); - - dri_destroy_option_cache(screen); -} - -void -dri_destroy_screen(__DRIscreen * sPriv) -{ - struct dri_screen *screen = dri_screen(sPriv); - - dri_destroy_screen_helper(screen); - -#if !SPLIT_TARGETS -#if !GALLIUM_STATIC_TARGETS - pipe_loader_release(&screen->dev, 1); -#endif // !GALLIUM_STATIC_TARGETS -#endif // !SPLIT_TARGETS - - free(screen); - sPriv->driverPrivate = NULL; - sPriv->extensions = NULL; -} - -static void -dri_postprocessing_init(struct dri_screen *screen) -{ - unsigned i; - - for (i = 0; i < PP_FILTERS; i++) { - screen->pp_enabled[i] = driQueryOptioni(&screen->optionCache, - pp_filters[i].name); - } -} - -const __DRIconfig ** -dri_init_screen_helper(struct dri_screen *screen, - struct pipe_screen *pscreen) -{ - screen->base.screen = pscreen; - if (!screen->base.screen) { - debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__); - return NULL; - } - - screen->base.get_egl_image = dri_get_egl_image; - screen->base.get_param = dri_get_param; - - screen->st_api = st_gl_api_create(); - if (!screen->st_api) - return NULL; - - if(pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES)) - screen->target = PIPE_TEXTURE_2D; - else - screen->target = PIPE_TEXTURE_RECT; - - driParseOptionInfo(&screen->optionCacheDefaults, gallium_config_options.xml); - - driParseConfigFiles(&screen->optionCache, - &screen->optionCacheDefaults, - screen->sPriv->myNum, -#if SPLIT_TARGETS - driver_descriptor.name); -#else -#if GALLIUM_STATIC_TARGETS - dd_driver_name()); -#else - screen->dev->driver_name); -#endif // GALLIUM_STATIC_TARGETS -#endif // SPLIT_TARGETS - - /* Handle force_s3tc_enable. */ - if (!util_format_s3tc_enabled && - driQueryOptionb(&screen->optionCache, "force_s3tc_enable")) { - /* Ensure libtxc_dxtn has been loaded if available. - * Forcing S3TC on before calling this would prevent loading - * the library. - * This is just a precaution, the driver should have called it - * already. - */ - util_format_s3tc_init(); - - util_format_s3tc_enabled = TRUE; - } - - dri_postprocessing_init(screen); - - /* gallium drivers don't declare what version of GL they support, so we - * check the computed Mesa context version after context creation and fail - * out then. - */ - if (screen->st_api->profile_mask & ST_PROFILE_DEFAULT_MASK) - screen->sPriv->max_gl_compat_version = 30; - if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_CORE_MASK) - screen->sPriv->max_gl_core_version = 33; - if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES1_MASK) - screen->sPriv->max_gl_es1_version = 11; - if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES2_MASK) - screen->sPriv->max_gl_es2_version = 30; - - return dri_fill_in_modes(screen); -} - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/common/dri_screen.h b/src/gallium/state_trackers/dri/common/dri_screen.h deleted file mode 100644 index 63758d2f7f7..00000000000 --- a/src/gallium/state_trackers/dri/common/dri_screen.h +++ /dev/null @@ -1,156 +0,0 @@ -/************************************************************************** - * - * 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 VMWARE 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. - * - **************************************************************************/ -/* - * Author: Keith Whitwell - * Author: Jakob Bornecrantz - */ - -#ifndef DRI_SCREEN_H -#define DRI_SCREEN_H - -#include "dri_util.h" -#include "xmlconfig.h" - -#include "pipe/p_compiler.h" -#include "pipe/p_context.h" -#include "pipe/p_state.h" -#include "state_tracker/st_api.h" -#include "postprocess/filters.h" - -struct dri_context; -struct dri_drawable; -struct pipe_loader_device; - -struct dri_screen -{ - /* st_api */ - struct st_manager base; - struct st_api *st_api; - - /* on old libGL's invalidate doesn't get called as it should */ - boolean broken_invalidate; - - /* dri */ - __DRIscreen *sPriv; - boolean throttling_enabled; - int default_throttle_frames; - - /** Configuration cache with default values for all contexts */ - driOptionCache optionCacheDefaults; - - /** The screen's effective configuration options */ - driOptionCache optionCache; - - /* Which postprocessing filters are enabled. */ - unsigned pp_enabled[PP_FILTERS]; - - /* drm */ - int fd; - - struct pipe_loader_device *dev; - - /* gallium */ - boolean d_depth_bits_last; - boolean sd_depth_bits_last; - boolean auto_fake_front; - enum pipe_texture_target target; - - /* hooks filled in by dri2 & drisw */ - __DRIimage * (*lookup_egl_image)(struct dri_screen *ctx, void *handle); -}; - -/** cast wrapper */ -static INLINE struct dri_screen * -dri_screen(__DRIscreen * sPriv) -{ - return (struct dri_screen *)sPriv->driverPrivate; -} - -struct __DRIimageRec { - struct pipe_resource *texture; - unsigned level; - unsigned layer; - uint32_t dri_format; - uint32_t dri_components; - - void *loader_private; - - /** - * Provided by EGL_EXT_image_dma_buf_import. - */ - enum __DRIYUVColorSpace yuv_color_space; - enum __DRISampleRange sample_range; - enum __DRIChromaSiting horizontal_siting; - enum __DRIChromaSiting vertical_siting; - -}; - -#ifndef __NOT_HAVE_DRM_H - -static INLINE boolean -dri_with_format(__DRIscreen * sPriv) -{ - const __DRIdri2LoaderExtension *loader = sPriv->dri2.loader; - - return loader - && (loader->base.version >= 3) - && (loader->getBuffersWithFormat != NULL); -} - -#else - -static INLINE boolean -dri_with_format(__DRIscreen * sPriv) -{ - return TRUE; -} - -#endif - -void -dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen, - const struct gl_config *mode); - -const __DRIconfig ** -dri_init_screen_helper(struct dri_screen *screen, - struct pipe_screen *pscreen); - -void -dri_destroy_screen_helper(struct dri_screen * screen); - -void -dri_destroy_screen(__DRIscreen * sPriv); - -extern const struct __DriverAPIRec galliumdrm_driver_api; -extern const __DRIextension *galliumdrm_driver_extensions[]; -extern const struct __DriverAPIRec galliumsw_driver_api; -extern const __DRIextension *galliumsw_driver_extensions[]; -extern const __DRIconfigOptionsExtension gallium_config_options; - -#endif - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c new file mode 100644 index 00000000000..fcca4875229 --- /dev/null +++ b/src/gallium/state_trackers/dri/dri2.c @@ -0,0 +1,1347 @@ +/* + * Mesa 3-D graphics library + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * Copyright (C) 2010 LunarG Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + * Authors: + * Keith Whitwell Jakob Bornecrantz + * Chia-I Wu + */ + +#include +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_format.h" +#include "util/u_debug.h" +#include "state_tracker/drm_driver.h" +#include "state_tracker/st_texture.h" +#include "state_tracker/st_context.h" +#include "pipe-loader/pipe_loader.h" +#include "main/texobj.h" + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" +#include "dri2_buffer.h" + +static int convert_fourcc(int format, int *dri_components_p) +{ + int dri_components; + switch(format) { + case __DRI_IMAGE_FOURCC_RGB565: + format = __DRI_IMAGE_FORMAT_RGB565; + dri_components = __DRI_IMAGE_COMPONENTS_RGB; + break; + case __DRI_IMAGE_FOURCC_ARGB8888: + format = __DRI_IMAGE_FORMAT_ARGB8888; + dri_components = __DRI_IMAGE_COMPONENTS_RGBA; + break; + case __DRI_IMAGE_FOURCC_XRGB8888: + format = __DRI_IMAGE_FORMAT_XRGB8888; + dri_components = __DRI_IMAGE_COMPONENTS_RGB; + break; + case __DRI_IMAGE_FOURCC_ABGR8888: + format = __DRI_IMAGE_FORMAT_ABGR8888; + dri_components = __DRI_IMAGE_COMPONENTS_RGBA; + break; + case __DRI_IMAGE_FOURCC_XBGR8888: + format = __DRI_IMAGE_FORMAT_XBGR8888; + dri_components = __DRI_IMAGE_COMPONENTS_RGB; + break; + default: + return -1; + } + *dri_components_p = dri_components; + return format; +} + +/** + * DRI2 flush extension. + */ +static void +dri2_flush_drawable(__DRIdrawable *dPriv) +{ + dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1); +} + +static void +dri2_invalidate_drawable(__DRIdrawable *dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + + dri2InvalidateDrawable(dPriv); + drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp; + + p_atomic_inc(&drawable->base.stamp); +} + +static const __DRI2flushExtension dri2FlushExtension = { + .base = { __DRI2_FLUSH, 4 }, + + .flush = dri2_flush_drawable, + .invalidate = dri2_invalidate_drawable, + .flush_with_flags = dri_flush, +}; + +/** + * Retrieve __DRIbuffer from the DRI loader. + */ +static __DRIbuffer * +dri2_drawable_get_buffers(struct dri_drawable *drawable, + const enum st_attachment_type *atts, + unsigned *count) +{ + __DRIdrawable *dri_drawable = drawable->dPriv; + const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; + boolean with_format; + __DRIbuffer *buffers; + int num_buffers; + unsigned attachments[10]; + unsigned num_attachments, i; + + assert(loader); + with_format = dri_with_format(drawable->sPriv); + + num_attachments = 0; + + /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */ + if (!with_format) + attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT; + + for (i = 0; i < *count; i++) { + enum pipe_format format; + unsigned bind; + int att, depth; + + dri_drawable_get_format(drawable, atts[i], &format, &bind); + if (format == PIPE_FORMAT_NONE) + continue; + + switch (atts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + /* already added */ + if (!with_format) + continue; + att = __DRI_BUFFER_FRONT_LEFT; + break; + case ST_ATTACHMENT_BACK_LEFT: + att = __DRI_BUFFER_BACK_LEFT; + break; + case ST_ATTACHMENT_FRONT_RIGHT: + att = __DRI_BUFFER_FRONT_RIGHT; + break; + case ST_ATTACHMENT_BACK_RIGHT: + att = __DRI_BUFFER_BACK_RIGHT; + break; + default: + continue; + } + + /* + * In this switch statement we must support all formats that + * may occur as the stvis->color_format. + */ + switch(format) { + case PIPE_FORMAT_B8G8R8A8_UNORM: + depth = 32; + break; + case PIPE_FORMAT_B8G8R8X8_UNORM: + depth = 24; + break; + case PIPE_FORMAT_B5G6R5_UNORM: + depth = 16; + break; + default: + depth = util_format_get_blocksizebits(format); + assert(!"Unexpected format in dri2_drawable_get_buffers()"); + } + + attachments[num_attachments++] = att; + if (with_format) { + attachments[num_attachments++] = depth; + } + } + + if (with_format) { + num_attachments /= 2; + buffers = loader->getBuffersWithFormat(dri_drawable, + &dri_drawable->w, &dri_drawable->h, + attachments, num_attachments, + &num_buffers, dri_drawable->loaderPrivate); + } + else { + buffers = loader->getBuffers(dri_drawable, + &dri_drawable->w, &dri_drawable->h, + attachments, num_attachments, + &num_buffers, dri_drawable->loaderPrivate); + } + + if (buffers) + *count = num_buffers; + + return buffers; +} + +static bool +dri_image_drawable_get_buffers(struct dri_drawable *drawable, + struct __DRIimageList *images, + const enum st_attachment_type *statts, + unsigned statts_count) +{ + __DRIdrawable *dPriv = drawable->dPriv; + __DRIscreen *sPriv = drawable->sPriv; + unsigned int image_format = __DRI_IMAGE_FORMAT_NONE; + enum pipe_format pf; + uint32_t buffer_mask = 0; + unsigned i, bind; + + for (i = 0; i < statts_count; i++) { + dri_drawable_get_format(drawable, statts[i], &pf, &bind); + if (pf == PIPE_FORMAT_NONE) + continue; + + switch (statts[i]) { + case ST_ATTACHMENT_FRONT_LEFT: + buffer_mask |= __DRI_IMAGE_BUFFER_FRONT; + break; + case ST_ATTACHMENT_BACK_LEFT: + buffer_mask |= __DRI_IMAGE_BUFFER_BACK; + break; + default: + continue; + } + + switch (pf) { + case PIPE_FORMAT_B5G6R5_UNORM: + image_format = __DRI_IMAGE_FORMAT_RGB565; + break; + case PIPE_FORMAT_B8G8R8X8_UNORM: + image_format = __DRI_IMAGE_FORMAT_XRGB8888; + break; + case PIPE_FORMAT_B8G8R8A8_UNORM: + image_format = __DRI_IMAGE_FORMAT_ARGB8888; + break; + case PIPE_FORMAT_R8G8B8A8_UNORM: + image_format = __DRI_IMAGE_FORMAT_ABGR8888; + break; + default: + image_format = __DRI_IMAGE_FORMAT_NONE; + break; + } + } + + return (*sPriv->image.loader->getBuffers) (dPriv, image_format, + (uint32_t *) &drawable->base.stamp, + dPriv->loaderPrivate, buffer_mask, + images); +} + +static __DRIbuffer * +dri2_allocate_buffer(__DRIscreen *sPriv, + unsigned attachment, unsigned format, + int width, int height) +{ + struct dri_screen *screen = dri_screen(sPriv); + struct dri2_buffer *buffer; + struct pipe_resource templ; + enum pipe_format pf; + unsigned bind = 0; + struct winsys_handle whandle; + + switch (attachment) { + case __DRI_BUFFER_FRONT_LEFT: + case __DRI_BUFFER_FAKE_FRONT_LEFT: + bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + break; + case __DRI_BUFFER_BACK_LEFT: + bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + break; + case __DRI_BUFFER_DEPTH: + case __DRI_BUFFER_DEPTH_STENCIL: + case __DRI_BUFFER_STENCIL: + bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ + break; + } + + /* because we get the handle and stride */ + bind |= PIPE_BIND_SHARED; + + switch (format) { + case 32: + pf = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + case 24: + pf = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case 16: + pf = PIPE_FORMAT_Z16_UNORM; + break; + default: + return NULL; + } + + buffer = CALLOC_STRUCT(dri2_buffer); + if (!buffer) + return NULL; + + memset(&templ, 0, sizeof(templ)); + templ.bind = bind; + templ.format = pf; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + + buffer->resource = + screen->base.screen->resource_create(screen->base.screen, &templ); + if (!buffer->resource) { + FREE(buffer); + return NULL; + } + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_SHARED; + screen->base.screen->resource_get_handle(screen->base.screen, + buffer->resource, &whandle); + + buffer->base.attachment = attachment; + buffer->base.name = whandle.handle; + buffer->base.cpp = util_format_get_blocksize(pf); + buffer->base.pitch = whandle.stride; + + return &buffer->base; +} + +static void +dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv) +{ + struct dri2_buffer *buffer = dri2_buffer(bPriv); + + pipe_resource_reference(&buffer->resource, NULL); + FREE(buffer); +} + +/* + * Backend functions for st_framebuffer interface. + */ + +static void +dri2_allocate_textures(struct dri_context *ctx, + struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned statts_count) +{ + __DRIscreen *sPriv = drawable->sPriv; + __DRIdrawable *dri_drawable = drawable->dPriv; + struct dri_screen *screen = dri_screen(sPriv); + struct pipe_resource templ; + boolean alloc_depthstencil = FALSE; + unsigned i, j, bind; + const __DRIimageLoaderExtension *image = sPriv->image.loader; + /* Image specific variables */ + struct __DRIimageList images; + /* Dri2 specific variables */ + __DRIbuffer *buffers; + struct winsys_handle whandle; + unsigned num_buffers = statts_count; + + /* First get the buffers from the loader */ + if (image) { + if (!dri_image_drawable_get_buffers(drawable, &images, + statts, statts_count)) + return; + } + else { + buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers); + if (!buffers || (drawable->old_num == num_buffers && + drawable->old_w == dri_drawable->w && + drawable->old_h == dri_drawable->h && + memcmp(drawable->old, buffers, + sizeof(__DRIbuffer) * num_buffers) == 0)) + return; + } + + /* Second clean useless resources*/ + + /* See if we need a depth-stencil buffer. */ + for (i = 0; i < statts_count; i++) { + if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { + alloc_depthstencil = TRUE; + break; + } + } + + /* Delete the resources we won't need. */ + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + /* Don't delete the depth-stencil buffer, we can reuse it. */ + if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil) + continue; + + /* Flush the texture before unreferencing, so that other clients can + * see what the driver has rendered. + */ + if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) { + struct pipe_context *pipe = ctx->st->pipe; + pipe->flush_resource(pipe, drawable->textures[i]); + } + + pipe_resource_reference(&drawable->textures[i], NULL); + } + + if (drawable->stvis.samples > 1) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + boolean del = TRUE; + + /* Don't delete MSAA resources for the attachments which are enabled, + * we can reuse them. */ + for (j = 0; j < statts_count; j++) { + if (i == statts[j]) { + del = FALSE; + break; + } + } + + if (del) { + pipe_resource_reference(&drawable->msaa_textures[i], NULL); + } + } + } + + /* Third use the buffers retrieved to fill the drawable info */ + + memset(&templ, 0, sizeof(templ)); + templ.target = screen->target; + templ.last_level = 0; + templ.depth0 = 1; + templ.array_size = 1; + + if (image) { + if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) { + struct pipe_resource **buf = + &drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; + struct pipe_resource *texture = images.front->texture; + + dri_drawable->w = texture->width0; + dri_drawable->h = texture->height0; + + pipe_resource_reference(buf, texture); + } + + if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) { + struct pipe_resource **buf = + &drawable->textures[ST_ATTACHMENT_BACK_LEFT]; + struct pipe_resource *texture = images.back->texture; + + dri_drawable->w = texture->width0; + dri_drawable->h = texture->height0; + + pipe_resource_reference(buf, texture); + } + + /* Note: if there is both a back and a front buffer, + * then they have the same size. + */ + templ.width0 = dri_drawable->w; + templ.height0 = dri_drawable->h; + } + else { + memset(&whandle, 0, sizeof(whandle)); + + /* Process DRI-provided buffers and get pipe_resources. */ + for (i = 0; i < num_buffers; i++) { + __DRIbuffer *buf = &buffers[i]; + enum st_attachment_type statt; + enum pipe_format format; + + switch (buf->attachment) { + case __DRI_BUFFER_FRONT_LEFT: + if (!screen->auto_fake_front) { + continue; /* invalid attachment */ + } + /* fallthrough */ + case __DRI_BUFFER_FAKE_FRONT_LEFT: + statt = ST_ATTACHMENT_FRONT_LEFT; + break; + case __DRI_BUFFER_BACK_LEFT: + statt = ST_ATTACHMENT_BACK_LEFT; + break; + default: + continue; /* invalid attachment */ + } + + dri_drawable_get_format(drawable, statt, &format, &bind); + if (format == PIPE_FORMAT_NONE) + continue; + + /* dri2_drawable_get_buffers has already filled dri_drawable->w + * and dri_drawable->h */ + templ.width0 = dri_drawable->w; + templ.height0 = dri_drawable->h; + templ.format = format; + templ.bind = bind; + whandle.type = DRM_API_HANDLE_TYPE_SHARED; + whandle.handle = buf->name; + whandle.stride = buf->pitch; + + drawable->textures[statt] = + screen->base.screen->resource_from_handle(screen->base.screen, + &templ, &whandle); + assert(drawable->textures[statt]); + } + } + + /* Allocate private MSAA colorbuffers. */ + if (drawable->stvis.samples > 1) { + for (i = 0; i < statts_count; i++) { + enum st_attachment_type statt = statts[i]; + + if (statt == ST_ATTACHMENT_DEPTH_STENCIL) + continue; + + if (drawable->textures[statt]) { + templ.format = drawable->textures[statt]->format; + templ.bind = drawable->textures[statt]->bind; + templ.nr_samples = drawable->stvis.samples; + + /* Try to reuse the resource. + * (the other resource parameters should be constant) + */ + if (!drawable->msaa_textures[statt] || + drawable->msaa_textures[statt]->width0 != templ.width0 || + drawable->msaa_textures[statt]->height0 != templ.height0) { + /* Allocate a new one. */ + pipe_resource_reference(&drawable->msaa_textures[statt], NULL); + + drawable->msaa_textures[statt] = + screen->base.screen->resource_create(screen->base.screen, + &templ); + assert(drawable->msaa_textures[statt]); + + /* If there are any MSAA resources, we should initialize them + * such that they contain the same data as the single-sample + * resources we just got from the X server. + * + * The reason for this is that the state tracker (and + * therefore the app) can access the MSAA resources only. + * The single-sample resources are not exposed + * to the state tracker. + * + */ + dri_pipe_blit(ctx->st->pipe, + drawable->msaa_textures[statt], + drawable->textures[statt]); + } + } + else { + pipe_resource_reference(&drawable->msaa_textures[statt], NULL); + } + } + } + + /* Allocate a private depth-stencil buffer. */ + if (alloc_depthstencil) { + enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL; + struct pipe_resource **zsbuf; + enum pipe_format format; + unsigned bind; + + dri_drawable_get_format(drawable, statt, &format, &bind); + + if (format) { + templ.format = format; + templ.bind = bind; + + if (drawable->stvis.samples > 1) { + templ.nr_samples = drawable->stvis.samples; + zsbuf = &drawable->msaa_textures[statt]; + } + else { + templ.nr_samples = 0; + zsbuf = &drawable->textures[statt]; + } + + /* Try to reuse the resource. + * (the other resource parameters should be constant) + */ + if (!*zsbuf || + (*zsbuf)->width0 != templ.width0 || + (*zsbuf)->height0 != templ.height0) { + /* Allocate a new one. */ + pipe_resource_reference(zsbuf, NULL); + *zsbuf = screen->base.screen->resource_create(screen->base.screen, + &templ); + assert(*zsbuf); + } + } + else { + pipe_resource_reference(&drawable->msaa_textures[statt], NULL); + pipe_resource_reference(&drawable->textures[statt], NULL); + } + } + + /* For DRI2, we may get the same buffers again from the server. + * To prevent useless imports of gem names, drawable->old* is used + * to bypass the import if we get the same buffers. This doesn't apply + * to DRI3/Wayland, users of image.loader, since the buffer is managed + * by the client (no import), and the back buffer is going to change + * at every redraw. + */ + if (!image) { + drawable->old_num = num_buffers; + drawable->old_w = dri_drawable->w; + drawable->old_h = dri_drawable->h; + memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers); + } +} + +static void +dri2_flush_frontbuffer(struct dri_context *ctx, + struct dri_drawable *drawable, + enum st_attachment_type statt) +{ + __DRIdrawable *dri_drawable = drawable->dPriv; + const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader; + const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; + struct pipe_context *pipe = ctx->st->pipe; + + if (statt != ST_ATTACHMENT_FRONT_LEFT) + return; + + if (drawable->stvis.samples > 1) { + /* Resolve the front buffer. */ + dri_pipe_blit(ctx->st->pipe, + drawable->textures[ST_ATTACHMENT_FRONT_LEFT], + drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]); + } + + if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) { + pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]); + } + + pipe->flush(pipe, NULL, 0); + + if (image) { + image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); + } + else if (loader->flushFrontBuffer) { + loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); + } +} + +static void +dri2_update_tex_buffer(struct dri_drawable *drawable, + struct dri_context *ctx, + struct pipe_resource *res) +{ + /* no-op */ +} + +static __DRIimage * +dri2_lookup_egl_image(struct dri_screen *screen, void *handle) +{ + const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image; + __DRIimage *img; + + if (!loader->lookupEGLImage) + return NULL; + + img = loader->lookupEGLImage(screen->sPriv, + handle, screen->sPriv->loaderPrivate); + + return img; +} + +static __DRIimage * +dri2_create_image_from_winsys(__DRIscreen *_screen, + int width, int height, int format, + struct winsys_handle *whandle, int pitch, + void *loaderPrivate) +{ + struct dri_screen *screen = dri_screen(_screen); + __DRIimage *img; + struct pipe_resource templ; + unsigned tex_usage; + enum pipe_format pf; + + tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + + switch (format) { + case __DRI_IMAGE_FORMAT_RGB565: + pf = PIPE_FORMAT_B5G6R5_UNORM; + break; + case __DRI_IMAGE_FORMAT_XRGB8888: + pf = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case __DRI_IMAGE_FORMAT_ARGB8888: + pf = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + case __DRI_IMAGE_FORMAT_ABGR8888: + pf = PIPE_FORMAT_R8G8B8A8_UNORM; + break; + default: + pf = PIPE_FORMAT_NONE; + break; + } + if (pf == PIPE_FORMAT_NONE) + return NULL; + + img = CALLOC_STRUCT(__DRIimageRec); + if (!img) + return NULL; + + memset(&templ, 0, sizeof(templ)); + templ.bind = tex_usage; + templ.format = pf; + templ.target = screen->target; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + + whandle->stride = pitch * util_format_get_blocksize(pf); + + img->texture = screen->base.screen->resource_from_handle(screen->base.screen, + &templ, whandle); + if (!img->texture) { + FREE(img); + return NULL; + } + + img->level = 0; + img->layer = 0; + img->dri_format = format; + img->loader_private = loaderPrivate; + + return img; +} + +static __DRIimage * +dri2_create_image_from_name(__DRIscreen *_screen, + int width, int height, int format, + int name, int pitch, void *loaderPrivate) +{ + struct winsys_handle whandle; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_SHARED; + whandle.handle = name; + + return dri2_create_image_from_winsys(_screen, width, height, format, + &whandle, pitch, loaderPrivate); +} + +static __DRIimage * +dri2_create_image_from_fd(__DRIscreen *_screen, + int width, int height, int format, + int fd, int pitch, void *loaderPrivate) +{ + struct winsys_handle whandle; + + if (fd < 0) + return NULL; + + memset(&whandle, 0, sizeof(whandle)); + whandle.type = DRM_API_HANDLE_TYPE_FD; + whandle.handle = (unsigned)fd; + + return dri2_create_image_from_winsys(_screen, width, height, format, + &whandle, pitch, loaderPrivate); +} + +static __DRIimage * +dri2_create_image_from_renderbuffer(__DRIcontext *context, + int renderbuffer, void *loaderPrivate) +{ + struct dri_context *ctx = dri_context(context); + + if (!ctx->st->get_resource_for_egl_image) + return NULL; + + /* TODO */ + return NULL; +} + +static __DRIimage * +dri2_create_image(__DRIscreen *_screen, + int width, int height, int format, + unsigned int use, void *loaderPrivate) +{ + struct dri_screen *screen = dri_screen(_screen); + __DRIimage *img; + struct pipe_resource templ; + unsigned tex_usage; + enum pipe_format pf; + + tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + if (use & __DRI_IMAGE_USE_SCANOUT) + tex_usage |= PIPE_BIND_SCANOUT; + if (use & __DRI_IMAGE_USE_SHARE) + tex_usage |= PIPE_BIND_SHARED; + if (use & __DRI_IMAGE_USE_LINEAR) + tex_usage |= PIPE_BIND_LINEAR; + if (use & __DRI_IMAGE_USE_CURSOR) { + if (width != 64 || height != 64) + return NULL; + tex_usage |= PIPE_BIND_CURSOR; + } + + switch (format) { + case __DRI_IMAGE_FORMAT_RGB565: + pf = PIPE_FORMAT_B5G6R5_UNORM; + break; + case __DRI_IMAGE_FORMAT_XRGB8888: + pf = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case __DRI_IMAGE_FORMAT_ARGB8888: + pf = PIPE_FORMAT_B8G8R8A8_UNORM; + break; + case __DRI_IMAGE_FORMAT_ABGR8888: + pf = PIPE_FORMAT_R8G8B8A8_UNORM; + break; + default: + pf = PIPE_FORMAT_NONE; + break; + } + if (pf == PIPE_FORMAT_NONE) + return NULL; + + img = CALLOC_STRUCT(__DRIimageRec); + if (!img) + return NULL; + + memset(&templ, 0, sizeof(templ)); + templ.bind = tex_usage; + templ.format = pf; + templ.target = PIPE_TEXTURE_2D; + templ.last_level = 0; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + + img->texture = screen->base.screen->resource_create(screen->base.screen, &templ); + if (!img->texture) { + FREE(img); + return NULL; + } + + img->level = 0; + img->layer = 0; + img->dri_format = format; + img->dri_components = 0; + + img->loader_private = loaderPrivate; + return img; +} + +static GLboolean +dri2_query_image(__DRIimage *image, int attrib, int *value) +{ + struct winsys_handle whandle; + memset(&whandle, 0, sizeof(whandle)); + + switch (attrib) { + case __DRI_IMAGE_ATTRIB_STRIDE: + whandle.type = DRM_API_HANDLE_TYPE_KMS; + image->texture->screen->resource_get_handle(image->texture->screen, + image->texture, &whandle); + *value = whandle.stride; + return GL_TRUE; + case __DRI_IMAGE_ATTRIB_HANDLE: + whandle.type = DRM_API_HANDLE_TYPE_KMS; + image->texture->screen->resource_get_handle(image->texture->screen, + image->texture, &whandle); + *value = whandle.handle; + return GL_TRUE; + case __DRI_IMAGE_ATTRIB_NAME: + whandle.type = DRM_API_HANDLE_TYPE_SHARED; + image->texture->screen->resource_get_handle(image->texture->screen, + image->texture, &whandle); + *value = whandle.handle; + return GL_TRUE; + case __DRI_IMAGE_ATTRIB_FD: + whandle.type= DRM_API_HANDLE_TYPE_FD; + image->texture->screen->resource_get_handle(image->texture->screen, + image->texture, &whandle); + *value = whandle.handle; + return GL_TRUE; + case __DRI_IMAGE_ATTRIB_FORMAT: + *value = image->dri_format; + return GL_TRUE; + case __DRI_IMAGE_ATTRIB_WIDTH: + *value = image->texture->width0; + return GL_TRUE; + case __DRI_IMAGE_ATTRIB_HEIGHT: + *value = image->texture->height0; + return GL_TRUE; + case __DRI_IMAGE_ATTRIB_COMPONENTS: + if (image->dri_components == 0) + return GL_FALSE; + *value = image->dri_components; + return GL_TRUE; + default: + return GL_FALSE; + } +} + +static __DRIimage * +dri2_dup_image(__DRIimage *image, void *loaderPrivate) +{ + __DRIimage *img; + + img = CALLOC_STRUCT(__DRIimageRec); + if (!img) + return NULL; + + img->texture = NULL; + pipe_resource_reference(&img->texture, image->texture); + img->level = image->level; + img->layer = image->layer; + img->dri_format = image->dri_format; + /* This should be 0 for sub images, but dup is also used for base images. */ + img->dri_components = image->dri_components; + img->loader_private = loaderPrivate; + + return img; +} + +static GLboolean +dri2_validate_usage(__DRIimage *image, unsigned int use) +{ + /* + * Gallium drivers are bad at adding usages to the resources + * once opened again in another process, which is the main use + * case for this, so we have to lie. + */ + if (image != NULL) + return GL_TRUE; + else + return GL_FALSE; +} + +static __DRIimage * +dri2_from_names(__DRIscreen *screen, int width, int height, int format, + int *names, int num_names, int *strides, int *offsets, + void *loaderPrivate) +{ + __DRIimage *img; + int stride, dri_components; + + if (num_names != 1) + return NULL; + if (offsets[0] != 0) + return NULL; + + format = convert_fourcc(format, &dri_components); + if (format == -1) + return NULL; + + /* Strides are in bytes not pixels. */ + stride = strides[0] /4; + + img = dri2_create_image_from_name(screen, width, height, format, + names[0], stride, loaderPrivate); + if (img == NULL) + return NULL; + + img->dri_components = dri_components; + return img; +} + +static __DRIimage * +dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate) +{ + __DRIimage *img; + + if (plane != 0) + return NULL; + + if (image->dri_components == 0) + return NULL; + + img = dri2_dup_image(image, loaderPrivate); + if (img == NULL) + return NULL; + + /* set this to 0 for sub images. */ + img->dri_components = 0; + return img; +} + +static __DRIimage * +dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture, + int depth, int level, unsigned *error, + void *loaderPrivate) +{ + __DRIimage *img; + struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx; + struct gl_texture_object *obj; + struct pipe_resource *tex; + GLuint face = 0; + + obj = _mesa_lookup_texture(ctx, texture); + if (!obj || obj->Target != target) { + *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; + return NULL; + } + + tex = st_get_texobj_resource(obj); + if (!tex) { + *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; + return NULL; + } + + if (target == GL_TEXTURE_CUBE_MAP) + face = depth; + + _mesa_test_texobj_completeness(ctx, obj); + if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) { + *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; + return NULL; + } + + if (level < obj->BaseLevel || level > obj->_MaxLevel) { + *error = __DRI_IMAGE_ERROR_BAD_MATCH; + return NULL; + } + + if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) { + *error = __DRI_IMAGE_ERROR_BAD_MATCH; + return NULL; + } + + img = CALLOC_STRUCT(__DRIimageRec); + if (!img) { + *error = __DRI_IMAGE_ERROR_BAD_ALLOC; + return NULL; + } + + img->level = level; + img->layer = depth; + img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat); + + img->loader_private = loaderPrivate; + + if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) { + *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; + free(img); + return NULL; + } + + pipe_resource_reference(&img->texture, tex); + + *error = __DRI_IMAGE_ERROR_SUCCESS; + return img; +} + +static __DRIimage * +dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc, + int *fds, int num_fds, int *strides, int *offsets, + void *loaderPrivate) +{ + __DRIimage *img; + int format, stride, dri_components; + + if (num_fds != 1) + return NULL; + if (offsets[0] != 0) + return NULL; + + format = convert_fourcc(fourcc, &dri_components); + if (format == -1) + return NULL; + + /* Strides are in bytes not pixels. */ + stride = strides[0] /4; + + img = dri2_create_image_from_fd(screen, width, height, format, + fds[0], stride, loaderPrivate); + if (img == NULL) + return NULL; + + img->dri_components = dri_components; + return img; +} + +static __DRIimage * +dri2_from_dma_bufs(__DRIscreen *screen, + int width, int height, int fourcc, + int *fds, int num_fds, + int *strides, int *offsets, + enum __DRIYUVColorSpace yuv_color_space, + enum __DRISampleRange sample_range, + enum __DRIChromaSiting horizontal_siting, + enum __DRIChromaSiting vertical_siting, + unsigned *error, + void *loaderPrivate) +{ + __DRIimage *img; + int format, stride, dri_components; + + if (num_fds != 1 || offsets[0] != 0) { + *error = __DRI_IMAGE_ERROR_BAD_MATCH; + return NULL; + } + + format = convert_fourcc(fourcc, &dri_components); + if (format == -1) { + *error = __DRI_IMAGE_ERROR_BAD_MATCH; + return NULL; + } + + /* Strides are in bytes not pixels. */ + stride = strides[0] /4; + + img = dri2_create_image_from_fd(screen, width, height, format, + fds[0], stride, loaderPrivate); + if (img == NULL) { + *error = __DRI_IMAGE_ERROR_BAD_ALLOC; + return NULL; + } + + img->yuv_color_space = yuv_color_space; + img->sample_range = sample_range; + img->horizontal_siting = horizontal_siting; + img->vertical_siting = vertical_siting; + img->dri_components = dri_components; + + *error = __DRI_IMAGE_ERROR_SUCCESS; + return img; +} + +static void +dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src, + int dstx0, int dsty0, int dstwidth, int dstheight, + int srcx0, int srcy0, int srcwidth, int srcheight, + int flush_flag) +{ + struct dri_context *ctx = dri_context(context); + struct pipe_context *pipe = ctx->st->pipe; + struct pipe_screen *screen; + struct pipe_fence_handle *fence; + struct pipe_blit_info blit; + + if (!dst || !src) + return; + + memset(&blit, 0, sizeof(blit)); + blit.dst.resource = dst->texture; + blit.dst.box.x = dstx0; + blit.dst.box.y = dsty0; + blit.dst.box.width = dstwidth; + blit.dst.box.height = dstheight; + blit.dst.box.depth = 1; + blit.dst.format = dst->texture->format; + blit.src.resource = src->texture; + blit.src.box.x = srcx0; + blit.src.box.y = srcy0; + blit.src.box.width = srcwidth; + blit.src.box.height = srcheight; + blit.src.box.depth = 1; + blit.src.format = src->texture->format; + blit.mask = PIPE_MASK_RGBA; + blit.filter = PIPE_TEX_FILTER_NEAREST; + + pipe->blit(pipe, &blit); + + if (flush_flag == __BLIT_FLAG_FLUSH) { + pipe->flush_resource(pipe, dst->texture); + ctx->st->flush(ctx->st, 0, NULL); + } else if (flush_flag == __BLIT_FLAG_FINISH) { + screen = dri_screen(ctx->sPriv)->base.screen; + pipe->flush_resource(pipe, dst->texture); + ctx->st->flush(ctx->st, 0, &fence); + (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE); + screen->fence_reference(screen, &fence, NULL); + } +} + +static void +dri2_destroy_image(__DRIimage *img) +{ + pipe_resource_reference(&img->texture, NULL); + FREE(img); +} + +/* The extension is modified during runtime if DRI_PRIME is detected */ +static __DRIimageExtension dri2ImageExtension = { + .base = { __DRI_IMAGE, 9 }, + + .createImageFromName = dri2_create_image_from_name, + .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer, + .destroyImage = dri2_destroy_image, + .createImage = dri2_create_image, + .queryImage = dri2_query_image, + .dupImage = dri2_dup_image, + .validateUsage = dri2_validate_usage, + .createImageFromNames = dri2_from_names, + .fromPlanar = dri2_from_planar, + .createImageFromTexture = dri2_create_from_texture, + .createImageFromFds = NULL, + .createImageFromDmaBufs = NULL, + .blitImage = dri2_blit_image, +}; + +/* + * Backend function init_screen. + */ + +static const __DRIextension *dri_screen_extensions[] = { + &driTexBufferExtension.base, + &dri2FlushExtension.base, + &dri2ImageExtension.base, + &dri2ConfigQueryExtension.base, + &dri2ThrottleExtension.base, + NULL +}; + +/** + * This is the driver specific part of the createNewScreen entry point. + * + * Returns the struct gl_config supported by this driver. + */ +static const __DRIconfig ** +dri2_init_screen(__DRIscreen * sPriv) +{ + const __DRIconfig **configs; + struct dri_screen *screen; + struct pipe_screen *pscreen = NULL; + const struct drm_conf_ret *throttle_ret = NULL; + const struct drm_conf_ret *dmabuf_ret = NULL; + + screen = CALLOC_STRUCT(dri_screen); + if (!screen) + return NULL; + + screen->sPriv = sPriv; + screen->fd = sPriv->fd; + + sPriv->driverPrivate = (void *)screen; + +#if GALLIUM_STATIC_TARGETS + pscreen = dd_create_screen(screen->fd); + + throttle_ret = dd_configuration(DRM_CONF_THROTTLE); + dmabuf_ret = dd_configuration(DRM_CONF_SHARE_FD); +#else + if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd, true)) { + pscreen = pipe_loader_create_screen(screen->dev, PIPE_SEARCH_DIR); + + throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE); + dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD); + } +#endif // GALLIUM_STATIC_TARGETS + + if (throttle_ret && throttle_ret->val.val_int != -1) { + screen->throttling_enabled = TRUE; + screen->default_throttle_frames = throttle_ret->val.val_int; + } + + if (dmabuf_ret && dmabuf_ret->val.val_bool) { + uint64_t cap; + + if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 && + (cap & DRM_PRIME_CAP_IMPORT)) { + dri2ImageExtension.createImageFromFds = dri2_from_fds; + dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs; + } + } + + sPriv->extensions = dri_screen_extensions; + + /* dri_init_screen_helper checks pscreen for us */ + +#if GALLIUM_STATIC_TARGETS + configs = dri_init_screen_helper(screen, pscreen, dd_driver_name()); +#else + configs = dri_init_screen_helper(screen, pscreen, screen->dev->driver_name); +#endif // GALLIUM_STATIC_TARGETS + if (!configs) + goto fail; + + screen->auto_fake_front = dri_with_format(sPriv); + screen->broken_invalidate = !sPriv->dri2.useInvalidate; + screen->lookup_egl_image = dri2_lookup_egl_image; + + return configs; +fail: + dri_destroy_screen_helper(screen); +#if !GALLIUM_STATIC_TARGETS + if (screen->dev) + pipe_loader_release(&screen->dev, 1); +#endif // !GALLIUM_STATIC_TARGETS + FREE(screen); + return NULL; +} + +static boolean +dri2_create_buffer(__DRIscreen * sPriv, + __DRIdrawable * dPriv, + const struct gl_config * visual, boolean isPixmap) +{ + struct dri_drawable *drawable = NULL; + + if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) + return FALSE; + + drawable = dPriv->driverPrivate; + + drawable->allocate_textures = dri2_allocate_textures; + drawable->flush_frontbuffer = dri2_flush_frontbuffer; + drawable->update_tex_buffer = dri2_update_tex_buffer; + + return TRUE; +} + +/** + * DRI driver virtual function table. + * + * DRI versions differ in their implementation of init_screen and swap_buffers. + */ +const struct __DriverAPIRec galliumdrm_driver_api = { + .InitScreen = dri2_init_screen, + .DestroyScreen = dri_destroy_screen, + .CreateContext = dri_create_context, + .DestroyContext = dri_destroy_context, + .CreateBuffer = dri2_create_buffer, + .DestroyBuffer = dri_destroy_buffer, + .MakeCurrent = dri_make_current, + .UnbindContext = dri_unbind_context, + + .AllocateBuffer = dri2_allocate_buffer, + .ReleaseBuffer = dri2_release_buffer, +}; + +/* This is the table of extensions that the loader will dlsym() for. */ +const __DRIextension *galliumdrm_driver_extensions[] = { + &driCoreExtension.base, + &driImageDriverExtension.base, + &driDRI2Extension.base, + &gallium_config_options.base, + NULL +}; + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri2_buffer.h b/src/gallium/state_trackers/dri/dri2_buffer.h new file mode 100644 index 00000000000..e8e474ddb76 --- /dev/null +++ b/src/gallium/state_trackers/dri/dri2_buffer.h @@ -0,0 +1,22 @@ +#ifndef DRI2_BUFFER_H +#define DRI2_BUFFER_H + +#include "dri_util.h" + +struct pipe_surface; + +struct dri2_buffer +{ + __DRIbuffer base; + struct pipe_resource *resource; +}; + +static INLINE struct dri2_buffer * +dri2_buffer(__DRIbuffer * driBufferPriv) +{ + return (struct dri2_buffer *) driBufferPriv; +} + +#endif + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_context.c b/src/gallium/state_trackers/dri/dri_context.c new file mode 100644 index 00000000000..f6979a7c2d0 --- /dev/null +++ b/src/gallium/state_trackers/dri/dri_context.c @@ -0,0 +1,276 @@ +/************************************************************************** + * + * 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 VMWARE 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. + * + **************************************************************************/ +/* + * Author: Keith Whitwell + * Author: Jakob Bornecrantz + */ + +#include "utils.h" + +#include "dri_screen.h" +#include "dri_drawable.h" +#include "dri_context.h" +#include "state_tracker/drm_driver.h" + +#include "pipe/p_context.h" +#include "state_tracker/st_context.h" + +static void +dri_fill_st_options(struct st_config_options *options, + const struct driOptionCache * optionCache) +{ + options->disable_blend_func_extended = + driQueryOptionb(optionCache, "disable_blend_func_extended"); + options->disable_glsl_line_continuations = + driQueryOptionb(optionCache, "disable_glsl_line_continuations"); + options->disable_shader_bit_encoding = + driQueryOptionb(optionCache, "disable_shader_bit_encoding"); + options->force_glsl_extensions_warn = + driQueryOptionb(optionCache, "force_glsl_extensions_warn"); + options->force_glsl_version = + driQueryOptioni(optionCache, "force_glsl_version"); + options->force_s3tc_enable = + driQueryOptionb(optionCache, "force_s3tc_enable"); +} + +GLboolean +dri_create_context(gl_api api, const struct gl_config * visual, + __DRIcontext * cPriv, + unsigned major_version, + unsigned minor_version, + uint32_t flags, + bool notify_reset, + unsigned *error, + void *sharedContextPrivate) +{ + __DRIscreen *sPriv = cPriv->driScreenPriv; + struct dri_screen *screen = dri_screen(sPriv); + struct st_api *stapi = screen->st_api; + struct dri_context *ctx = NULL; + struct st_context_iface *st_share = NULL; + struct st_context_attribs attribs; + enum st_context_error ctx_err = 0; + + memset(&attribs, 0, sizeof(attribs)); + switch (api) { + case API_OPENGLES: + attribs.profile = ST_PROFILE_OPENGL_ES1; + break; + case API_OPENGLES2: + attribs.profile = ST_PROFILE_OPENGL_ES2; + break; + case API_OPENGL_COMPAT: + case API_OPENGL_CORE: + attribs.profile = api == API_OPENGL_COMPAT ? ST_PROFILE_DEFAULT + : ST_PROFILE_OPENGL_CORE; + attribs.major = major_version; + attribs.minor = minor_version; + + if ((flags & __DRI_CTX_FLAG_DEBUG) != 0) + attribs.flags |= ST_CONTEXT_FLAG_DEBUG; + + if ((flags & __DRI_CTX_FLAG_FORWARD_COMPATIBLE) != 0) + attribs.flags |= ST_CONTEXT_FLAG_FORWARD_COMPATIBLE; + break; + default: + *error = __DRI_CTX_ERROR_BAD_API; + goto fail; + } + + if (flags & ~(__DRI_CTX_FLAG_DEBUG | __DRI_CTX_FLAG_FORWARD_COMPATIBLE)) { + *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; + goto fail; + } + + if (notify_reset) { + *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; + goto fail; + } + + if (sharedContextPrivate) { + st_share = ((struct dri_context *)sharedContextPrivate)->st; + } + + ctx = CALLOC_STRUCT(dri_context); + if (ctx == NULL) { + *error = __DRI_CTX_ERROR_NO_MEMORY; + goto fail; + } + + cPriv->driverPrivate = ctx; + ctx->cPriv = cPriv; + ctx->sPriv = sPriv; + + dri_fill_st_options(&attribs.options, &screen->optionCache); + dri_fill_st_visual(&attribs.visual, screen, visual); + ctx->st = stapi->create_context(stapi, &screen->base, &attribs, &ctx_err, + st_share); + if (ctx->st == NULL) { + switch (ctx_err) { + case ST_CONTEXT_SUCCESS: + *error = __DRI_CTX_ERROR_SUCCESS; + break; + case ST_CONTEXT_ERROR_NO_MEMORY: + *error = __DRI_CTX_ERROR_NO_MEMORY; + break; + case ST_CONTEXT_ERROR_BAD_API: + *error = __DRI_CTX_ERROR_BAD_API; + break; + case ST_CONTEXT_ERROR_BAD_VERSION: + *error = __DRI_CTX_ERROR_BAD_VERSION; + break; + case ST_CONTEXT_ERROR_BAD_FLAG: + *error = __DRI_CTX_ERROR_BAD_FLAG; + break; + case ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE: + *error = __DRI_CTX_ERROR_UNKNOWN_ATTRIBUTE; + break; + case ST_CONTEXT_ERROR_UNKNOWN_FLAG: + *error = __DRI_CTX_ERROR_UNKNOWN_FLAG; + break; + } + goto fail; + } + ctx->st->st_manager_private = (void *) ctx; + ctx->stapi = stapi; + + if (ctx->st->cso_context) { + ctx->pp = pp_init(ctx->st->pipe, screen->pp_enabled, ctx->st->cso_context); + ctx->hud = hud_create(ctx->st->pipe, ctx->st->cso_context); + } + + *error = __DRI_CTX_ERROR_SUCCESS; + return GL_TRUE; + + fail: + if (ctx && ctx->st) + ctx->st->destroy(ctx->st); + + free(ctx); + return GL_FALSE; +} + +void +dri_destroy_context(__DRIcontext * cPriv) +{ + struct dri_context *ctx = dri_context(cPriv); + + if (ctx->hud) { + hud_destroy(ctx->hud); + } + + /* No particular reason to wait for command completion before + * destroying a context, but we flush the context here + * to avoid having to add code elsewhere to cope with flushing a + * partially destroyed context. + */ + ctx->st->flush(ctx->st, 0, NULL); + ctx->st->destroy(ctx->st); + + if (ctx->pp) + pp_free(ctx->pp); + + free(ctx); +} + +GLboolean +dri_unbind_context(__DRIcontext * cPriv) +{ + /* dri_util.c ensures cPriv is not null */ + struct dri_screen *screen = dri_screen(cPriv->driScreenPriv); + struct dri_context *ctx = dri_context(cPriv); + struct st_api *stapi = screen->st_api; + + if (--ctx->bind_count == 0) { + if (ctx->st == ctx->stapi->get_current(ctx->stapi)) { + /* For conformance, unbind is supposed to flush the context. + * However, if we do it here we might end up flushing a partially + * destroyed context. Instead, we flush in dri_make_current and + * in dri_destroy_context which should cover all the cases. + */ + stapi->make_current(stapi, NULL, NULL, NULL); + } + } + + return GL_TRUE; +} + +GLboolean +dri_make_current(__DRIcontext * cPriv, + __DRIdrawable * driDrawPriv, + __DRIdrawable * driReadPriv) +{ + /* dri_util.c ensures cPriv is not null */ + struct dri_context *ctx = dri_context(cPriv); + struct dri_drawable *draw = dri_drawable(driDrawPriv); + struct dri_drawable *read = dri_drawable(driReadPriv); + struct st_context_iface *old_st = ctx->stapi->get_current(ctx->stapi); + + /* Flush the old context here so we don't have to flush on unbind() */ + if (old_st && old_st != ctx->st) + old_st->flush(old_st, ST_FLUSH_FRONT, NULL); + + ++ctx->bind_count; + + if (!draw && !read) + return ctx->stapi->make_current(ctx->stapi, ctx->st, NULL, NULL); + else if (!draw || !read) + return GL_FALSE; + + if (ctx->dPriv != driDrawPriv) { + ctx->dPriv = driDrawPriv; + draw->texture_stamp = driDrawPriv->lastStamp - 1; + } + if (ctx->rPriv != driReadPriv) { + ctx->rPriv = driReadPriv; + read->texture_stamp = driReadPriv->lastStamp - 1; + } + + ctx->stapi->make_current(ctx->stapi, ctx->st, &draw->base, &read->base); + + // This is ok to call here. If they are already init, it's a no-op. + if (draw->textures[ST_ATTACHMENT_BACK_LEFT] && draw->textures[ST_ATTACHMENT_DEPTH_STENCIL] + && ctx->pp) + pp_init_fbos(ctx->pp, draw->textures[ST_ATTACHMENT_BACK_LEFT]->width0, + draw->textures[ST_ATTACHMENT_BACK_LEFT]->height0); + + return GL_TRUE; +} + +struct dri_context * +dri_get_current(__DRIscreen *sPriv) +{ + struct dri_screen *screen = dri_screen(sPriv); + struct st_api *stapi = screen->st_api; + struct st_context_iface *st; + + st = stapi->get_current(stapi); + + return (struct dri_context *) st ? st->st_manager_private : NULL; +} + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_context.h b/src/gallium/state_trackers/dri/dri_context.h new file mode 100644 index 00000000000..56dfa2ccc70 --- /dev/null +++ b/src/gallium/state_trackers/dri/dri_context.h @@ -0,0 +1,98 @@ +/************************************************************************** + * + * 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 VMWARE 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. + * + **************************************************************************/ +/* + * Author: Keith Whitwell + * Author: Jakob Bornecrantz + */ + +#ifndef DRI_CONTEXT_H +#define DRI_CONTEXT_H + +#include "dri_util.h" +#include "pipe/p_compiler.h" +#include "hud/hud_context.h" + +struct pipe_context; +struct pipe_fence; +struct st_api; +struct st_context_iface; +struct dri_drawable; + +struct dri_context +{ + /* dri */ + __DRIscreen *sPriv; + __DRIcontext *cPriv; + __DRIdrawable *dPriv; + __DRIdrawable *rPriv; + + unsigned int bind_count; + + /* gallium */ + struct st_api *stapi; + struct st_context_iface *st; + struct pp_queue_t *pp; + struct hud_context *hud; +}; + +static INLINE struct dri_context * +dri_context(__DRIcontext * driContextPriv) +{ + if (!driContextPriv) + return NULL; + return (struct dri_context *)driContextPriv->driverPrivate; +} + +/*********************************************************************** + * dri_context.c + */ +void dri_destroy_context(__DRIcontext * driContextPriv); + +boolean dri_unbind_context(__DRIcontext * driContextPriv); + +boolean +dri_make_current(__DRIcontext * driContextPriv, + __DRIdrawable * driDrawPriv, + __DRIdrawable * driReadPriv); + +struct dri_context * +dri_get_current(__DRIscreen * driScreenPriv); + +boolean +dri_create_context(gl_api api, + const struct gl_config * visual, + __DRIcontext * driContextPriv, + unsigned major_version, + unsigned minor_version, + uint32_t flags, + bool notify_reset, + unsigned *error, + void *sharedContextPrivate); + +#endif + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_drawable.c b/src/gallium/state_trackers/dri/dri_drawable.c new file mode 100644 index 00000000000..b7df053594c --- /dev/null +++ b/src/gallium/state_trackers/dri/dri_drawable.c @@ -0,0 +1,571 @@ +/************************************************************************** + * + * 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 VMWARE 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. + * + **************************************************************************/ +/* + * Author: Keith Whitwell + * Author: Jakob Bornecrantz + */ + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" + +#include "pipe/p_screen.h" +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" + +static void +swap_fences_unref(struct dri_drawable *draw); + +static boolean +dri_st_framebuffer_validate(struct st_context_iface *stctx, + struct st_framebuffer_iface *stfbi, + const enum st_attachment_type *statts, + unsigned count, + struct pipe_resource **out) +{ + struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; + struct dri_drawable *drawable = + (struct dri_drawable *) stfbi->st_manager_private; + struct dri_screen *screen = dri_screen(drawable->sPriv); + unsigned statt_mask, new_mask; + boolean new_stamp; + int i; + unsigned int lastStamp; + struct pipe_resource **textures = + drawable->stvis.samples > 1 ? drawable->msaa_textures + : drawable->textures; + + statt_mask = 0x0; + for (i = 0; i < count; i++) + statt_mask |= (1 << statts[i]); + + /* record newly allocated textures */ + new_mask = (statt_mask & ~drawable->texture_mask); + + /* + * dPriv->dri2.stamp is the server stamp. dPriv->lastStamp is the + * client stamp. It has the value of the server stamp when last + * checked. + */ + do { + lastStamp = drawable->dPriv->lastStamp; + new_stamp = (drawable->texture_stamp != lastStamp); + + if (new_stamp || new_mask || screen->broken_invalidate) { + if (new_stamp && drawable->update_drawable_info) + drawable->update_drawable_info(drawable); + + drawable->allocate_textures(ctx, drawable, statts, count); + + /* add existing textures */ + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + if (textures[i]) + statt_mask |= (1 << i); + } + + drawable->texture_stamp = lastStamp; + drawable->texture_mask = statt_mask; + } + } while (lastStamp != drawable->dPriv->lastStamp); + + if (!out) + return TRUE; + + /* Set the window-system buffers for the state tracker. */ + for (i = 0; i < count; i++) { + out[i] = NULL; + pipe_resource_reference(&out[i], textures[statts[i]]); + } + + return TRUE; +} + +static boolean +dri_st_framebuffer_flush_front(struct st_context_iface *stctx, + struct st_framebuffer_iface *stfbi, + enum st_attachment_type statt) +{ + struct dri_context *ctx = (struct dri_context *)stctx->st_manager_private; + struct dri_drawable *drawable = + (struct dri_drawable *) stfbi->st_manager_private; + + /* XXX remove this and just set the correct one on the framebuffer */ + drawable->flush_frontbuffer(ctx, drawable, statt); + + return TRUE; +} + +/** + * This is called when we need to set up GL rendering to a new X window. + */ +boolean +dri_create_buffer(__DRIscreen * sPriv, + __DRIdrawable * dPriv, + const struct gl_config * visual, boolean isPixmap) +{ + struct dri_screen *screen = sPriv->driverPrivate; + struct dri_drawable *drawable = NULL; + + if (isPixmap) + goto fail; /* not implemented */ + + drawable = CALLOC_STRUCT(dri_drawable); + if (drawable == NULL) + goto fail; + + dri_fill_st_visual(&drawable->stvis, screen, visual); + + /* setup the st_framebuffer_iface */ + drawable->base.visual = &drawable->stvis; + drawable->base.flush_front = dri_st_framebuffer_flush_front; + drawable->base.validate = dri_st_framebuffer_validate; + drawable->base.st_manager_private = (void *) drawable; + + drawable->screen = screen; + drawable->sPriv = sPriv; + drawable->dPriv = dPriv; + drawable->desired_fences = screen->default_throttle_frames; + if (drawable->desired_fences > DRI_SWAP_FENCES_MAX) + drawable->desired_fences = DRI_SWAP_FENCES_MAX; + + dPriv->driverPrivate = (void *)drawable; + p_atomic_set(&drawable->base.stamp, 1); + + return GL_TRUE; +fail: + FREE(drawable); + return GL_FALSE; +} + +void +dri_destroy_buffer(__DRIdrawable * dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + int i; + + pipe_surface_reference(&drawable->drisw_surface, NULL); + + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&drawable->textures[i], NULL); + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&drawable->msaa_textures[i], NULL); + + swap_fences_unref(drawable); + + FREE(drawable); +} + +/** + * Validate the texture at an attachment. Allocate the texture if it does not + * exist. Used by the TFP extension. + */ +static void +dri_drawable_validate_att(struct dri_context *ctx, + struct dri_drawable *drawable, + enum st_attachment_type statt) +{ + enum st_attachment_type statts[ST_ATTACHMENT_COUNT]; + unsigned i, count = 0; + + /* check if buffer already exists */ + if (drawable->texture_mask & (1 << statt)) + return; + + /* make sure DRI2 does not destroy existing buffers */ + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { + if (drawable->texture_mask & (1 << i)) { + statts[count++] = i; + } + } + statts[count++] = statt; + + drawable->texture_stamp = drawable->dPriv->lastStamp - 1; + + drawable->base.validate(ctx->st, &drawable->base, statts, count, NULL); +} + +/** + * These are used for GLX_EXT_texture_from_pixmap + */ +static void +dri_set_tex_buffer2(__DRIcontext *pDRICtx, GLint target, + GLint format, __DRIdrawable *dPriv) +{ + struct dri_context *ctx = dri_context(pDRICtx); + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_resource *pt; + + dri_drawable_validate_att(ctx, drawable, ST_ATTACHMENT_FRONT_LEFT); + + /* Use the pipe resource associated with the X drawable */ + pt = drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; + + if (pt) { + enum pipe_format internal_format = pt->format; + + if (format == __DRI_TEXTURE_FORMAT_RGB) { + /* only need to cover the formats recognized by dri_fill_st_visual */ + switch (internal_format) { + case PIPE_FORMAT_B8G8R8A8_UNORM: + internal_format = PIPE_FORMAT_B8G8R8X8_UNORM; + break; + case PIPE_FORMAT_A8R8G8B8_UNORM: + internal_format = PIPE_FORMAT_X8R8G8B8_UNORM; + break; + default: + break; + } + } + + drawable->update_tex_buffer(drawable, ctx, pt); + + ctx->st->teximage(ctx->st, + (target == GL_TEXTURE_2D) ? ST_TEXTURE_2D : ST_TEXTURE_RECT, + 0, internal_format, pt, FALSE); + } +} + +static void +dri_set_tex_buffer(__DRIcontext *pDRICtx, GLint target, + __DRIdrawable *dPriv) +{ + dri_set_tex_buffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv); +} + +const __DRItexBufferExtension driTexBufferExtension = { + .base = { __DRI_TEX_BUFFER, 2 }, + + .setTexBuffer = dri_set_tex_buffer, + .setTexBuffer2 = dri_set_tex_buffer2, + .releaseTexBuffer = NULL, +}; + +/** + * Get the format and binding of an attachment. + */ +void +dri_drawable_get_format(struct dri_drawable *drawable, + enum st_attachment_type statt, + enum pipe_format *format, + unsigned *bind) +{ + switch (statt) { + case ST_ATTACHMENT_FRONT_LEFT: + case ST_ATTACHMENT_BACK_LEFT: + case ST_ATTACHMENT_FRONT_RIGHT: + case ST_ATTACHMENT_BACK_RIGHT: + *format = drawable->stvis.color_format; + *bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; + break; + case ST_ATTACHMENT_DEPTH_STENCIL: + *format = drawable->stvis.depth_stencil_format; + *bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ + break; + default: + *format = PIPE_FORMAT_NONE; + *bind = 0; + break; + } +} + + +/** + * swap_fences_pop_front - pull a fence from the throttle queue + * + * If the throttle queue is filled to the desired number of fences, + * pull fences off the queue until the number is less than the desired + * number of fences, and return the last fence pulled. + */ +static struct pipe_fence_handle * +swap_fences_pop_front(struct dri_drawable *draw) +{ + struct pipe_screen *screen = draw->screen->base.screen; + struct pipe_fence_handle *fence = NULL; + + if (draw->desired_fences == 0) + return NULL; + + if (draw->cur_fences >= draw->desired_fences) { + screen->fence_reference(screen, &fence, draw->swap_fences[draw->tail]); + screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL); + draw->tail &= DRI_SWAP_FENCES_MASK; + --draw->cur_fences; + } + return fence; +} + + +/** + * swap_fences_push_back - push a fence onto the throttle queue + * + * push a fence onto the throttle queue and pull fences of the queue + * so that the desired number of fences are on the queue. + */ +static void +swap_fences_push_back(struct dri_drawable *draw, + struct pipe_fence_handle *fence) +{ + struct pipe_screen *screen = draw->screen->base.screen; + + if (!fence || draw->desired_fences == 0) + return; + + while(draw->cur_fences == draw->desired_fences) + swap_fences_pop_front(draw); + + draw->cur_fences++; + screen->fence_reference(screen, &draw->swap_fences[draw->head++], + fence); + draw->head &= DRI_SWAP_FENCES_MASK; +} + + +/** + * swap_fences_unref - empty the throttle queue + * + * pulls fences of the throttle queue until it is empty. + */ +static void +swap_fences_unref(struct dri_drawable *draw) +{ + struct pipe_screen *screen = draw->screen->base.screen; + + while(draw->cur_fences) { + screen->fence_reference(screen, &draw->swap_fences[draw->tail++], NULL); + draw->tail &= DRI_SWAP_FENCES_MASK; + --draw->cur_fences; + } +} + +void +dri_pipe_blit(struct pipe_context *pipe, + struct pipe_resource *dst, + struct pipe_resource *src) +{ + struct pipe_blit_info blit; + + if (!dst || !src) + return; + + /* From the GL spec, version 4.2, section 4.1.11 (Additional Multisample + * Fragment Operations): + * + * If a framebuffer object is not bound, after all operations have + * been completed on the multisample buffer, the sample values for + * each color in the multisample buffer are combined to produce a + * single color value, and that value is written into the + * corresponding color buffers selected by DrawBuffer or + * DrawBuffers. An implementation may defer the writing of the color + * buffers until a later time, but the state of the framebuffer must + * behave as if the color buffers were updated as each fragment was + * processed. The method of combination is not specified. If the + * framebuffer contains sRGB values, then it is recommended that the + * an average of sample values is computed in a linearized space, as + * for blending (see section 4.1.7). + * + * In other words, to do a resolve operation in a linear space, we have + * to set sRGB formats if the original resources were sRGB, so don't use + * util_format_linear. + */ + + memset(&blit, 0, sizeof(blit)); + blit.dst.resource = dst; + blit.dst.box.width = dst->width0; + blit.dst.box.height = dst->height0; + blit.dst.box.depth = 1; + blit.dst.format = dst->format; + blit.src.resource = src; + blit.src.box.width = src->width0; + blit.src.box.height = src->height0; + blit.src.box.depth = 1; + blit.src.format = src->format; + blit.mask = PIPE_MASK_RGBA; + blit.filter = PIPE_TEX_FILTER_NEAREST; + + pipe->blit(pipe, &blit); +} + +static void +dri_postprocessing(struct dri_context *ctx, + struct dri_drawable *drawable, + enum st_attachment_type att) +{ + struct pipe_resource *src = drawable->textures[att]; + struct pipe_resource *zsbuf = drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]; + + if (ctx->pp && src && zsbuf) + pp_run(ctx->pp, src, src, zsbuf); +} + +/** + * DRI2 flush extension, the flush_with_flags function. + * + * \param context the context + * \param drawable the drawable to flush + * \param flags a combination of _DRI2_FLUSH_xxx flags + * \param throttle_reason the reason for throttling, 0 = no throttling + */ +void +dri_flush(__DRIcontext *cPriv, + __DRIdrawable *dPriv, + unsigned flags, + enum __DRI2throttleReason reason) +{ + struct dri_context *ctx = dri_context(cPriv); + struct dri_drawable *drawable = dri_drawable(dPriv); + unsigned flush_flags; + boolean swap_msaa_buffers = FALSE; + + if (!ctx) { + assert(0); + return; + } + + if (drawable) { + /* prevent recursion */ + if (drawable->flushing) + return; + + drawable->flushing = TRUE; + } + else { + flags &= ~__DRI2_FLUSH_DRAWABLE; + } + + /* Flush the drawable. */ + if ((flags & __DRI2_FLUSH_DRAWABLE) && + drawable->textures[ST_ATTACHMENT_BACK_LEFT]) { + struct pipe_context *pipe = ctx->st->pipe; + + if (drawable->stvis.samples > 1 && + reason == __DRI2_THROTTLE_SWAPBUFFER) { + /* Resolve the MSAA back buffer. */ + dri_pipe_blit(ctx->st->pipe, + drawable->textures[ST_ATTACHMENT_BACK_LEFT], + drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]); + + if (drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] && + drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]) { + swap_msaa_buffers = TRUE; + } + + /* FRONT_LEFT is resolved in drawable->flush_frontbuffer. */ + } + + dri_postprocessing(ctx, drawable, ST_ATTACHMENT_BACK_LEFT); + + if (ctx->hud) { + hud_draw(ctx->hud, drawable->textures[ST_ATTACHMENT_BACK_LEFT]); + } + + pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_BACK_LEFT]); + } + + flush_flags = 0; + if (flags & __DRI2_FLUSH_CONTEXT) + flush_flags |= ST_FLUSH_FRONT; + if (reason == __DRI2_THROTTLE_SWAPBUFFER) + flush_flags |= ST_FLUSH_END_OF_FRAME; + + /* Flush the context and throttle if needed. */ + if (dri_screen(ctx->sPriv)->throttling_enabled && + drawable && + (reason == __DRI2_THROTTLE_SWAPBUFFER || + reason == __DRI2_THROTTLE_FLUSHFRONT)) { + /* Throttle. + * + * This pulls a fence off the throttling queue and waits for it if the + * number of fences on the throttling queue has reached the desired + * number. + * + * Then flushes to insert a fence at the current rendering position, and + * pushes that fence on the queue. This requires that the st_context_iface + * flush method returns a fence even if there are no commands to flush. + */ + struct pipe_screen *screen = drawable->screen->base.screen; + struct pipe_fence_handle *fence; + + fence = swap_fences_pop_front(drawable); + if (fence) { + (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE); + screen->fence_reference(screen, &fence, NULL); + } + + ctx->st->flush(ctx->st, flush_flags, &fence); + + if (fence) { + swap_fences_push_back(drawable, fence); + screen->fence_reference(screen, &fence, NULL); + } + } + else if (flags & (__DRI2_FLUSH_DRAWABLE | __DRI2_FLUSH_CONTEXT)) { + ctx->st->flush(ctx->st, flush_flags, NULL); + } + + if (drawable) { + drawable->flushing = FALSE; + } + + /* Swap the MSAA front and back buffers, so that reading + * from the front buffer after SwapBuffers returns what was + * in the back buffer. + */ + if (swap_msaa_buffers) { + struct pipe_resource *tmp = + drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]; + + drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT] = + drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]; + drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT] = tmp; + + /* Now that we have swapped the buffers, this tells the state + * tracker to revalidate the framebuffer. + */ + p_atomic_inc(&drawable->base.stamp); + } +} + +/** + * dri_throttle - A DRI2ThrottleExtension throttling function. + */ +static void +dri_throttle(__DRIcontext *cPriv, __DRIdrawable *dPriv, + enum __DRI2throttleReason reason) +{ + dri_flush(cPriv, dPriv, 0, reason); +} + + +const __DRI2throttleExtension dri2ThrottleExtension = { + .base = { __DRI2_THROTTLE, 1 }, + + .throttle = dri_throttle, +}; + + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_drawable.h b/src/gallium/state_trackers/dri/dri_drawable.h new file mode 100644 index 00000000000..c5142181e89 --- /dev/null +++ b/src/gallium/state_trackers/dri/dri_drawable.h @@ -0,0 +1,128 @@ +/************************************************************************** + * + * 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 VMWARE 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_DRAWABLE_H +#define DRI_DRAWABLE_H + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "state_tracker/st_api.h" + +struct pipe_surface; +struct st_framebuffer; +struct dri_context; + +#define DRI_SWAP_FENCES_MAX 4 +#define DRI_SWAP_FENCES_MASK 3 +#define DRI_SWAP_FENCES_DEFAULT 1 + +struct dri_drawable +{ + struct st_framebuffer_iface base; + struct st_visual stvis; + + struct dri_screen *screen; + + /* dri */ + __DRIdrawable *dPriv; + __DRIscreen *sPriv; + + __DRIbuffer old[8]; + unsigned old_num; + unsigned old_w; + unsigned old_h; + + struct pipe_resource *textures[ST_ATTACHMENT_COUNT]; + struct pipe_resource *msaa_textures[ST_ATTACHMENT_COUNT]; + unsigned int texture_mask, texture_stamp; + + struct pipe_fence_handle *swap_fences[DRI_SWAP_FENCES_MAX]; + unsigned int cur_fences; + unsigned int head; + unsigned int tail; + unsigned int desired_fences; + boolean flushing; /* prevents recursion in dri_flush */ + + /* used only by DRISW */ + struct pipe_surface *drisw_surface; + + /* hooks filled in by dri2 & drisw */ + void (*allocate_textures)(struct dri_context *ctx, + struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned count); + + void (*update_drawable_info)(struct dri_drawable *drawable); + + void (*flush_frontbuffer)(struct dri_context *ctx, + struct dri_drawable *drawable, + enum st_attachment_type statt); + + void (*update_tex_buffer)(struct dri_drawable *drawable, + struct dri_context *ctx, + struct pipe_resource *res); +}; + +static INLINE struct dri_drawable * +dri_drawable(__DRIdrawable * driDrawPriv) +{ + return (struct dri_drawable *) (driDrawPriv) + ? driDrawPriv->driverPrivate : NULL; +} + +/*********************************************************************** + * dri_drawable.c + */ +boolean +dri_create_buffer(__DRIscreen * sPriv, + __DRIdrawable * dPriv, + const struct gl_config * visual, boolean isPixmap); + +void dri_destroy_buffer(__DRIdrawable * dPriv); + +void +dri_drawable_get_format(struct dri_drawable *drawable, + enum st_attachment_type statt, + enum pipe_format *format, + unsigned *bind); + +void +dri_pipe_blit(struct pipe_context *pipe, + struct pipe_resource *dst, + struct pipe_resource *src); + +void +dri_flush(__DRIcontext *cPriv, + __DRIdrawable *dPriv, + unsigned flags, + enum __DRI2throttleReason reason); + +extern const __DRItexBufferExtension driTexBufferExtension; +extern const __DRI2throttleExtension dri2ThrottleExtension; +#endif + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_screen.c b/src/gallium/state_trackers/dri/dri_screen.c new file mode 100644 index 00000000000..650dcb7b49a --- /dev/null +++ b/src/gallium/state_trackers/dri/dri_screen.c @@ -0,0 +1,473 @@ +/************************************************************************** + * + * 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 VMWARE 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. + * + **************************************************************************/ +/* + * Author: Keith Whitwell + * Author: Jakob Bornecrantz + */ + +#include "utils.h" +#include "xmlpool.h" + +#include "dri_screen.h" + +#include "util/u_inlines.h" +#include "pipe/p_screen.h" +#include "pipe/p_format.h" +#include "pipe-loader/pipe_loader.h" +#include "state_tracker/st_gl_api.h" /* for st_gl_api_create */ +#include "state_tracker/drm_driver.h" + +#include "util/u_debug.h" +#include "util/u_format_s3tc.h" + +#define MSAA_VISUAL_MAX_SAMPLES 32 + +#undef false + +const __DRIconfigOptionsExtension gallium_config_options = { + .base = { __DRI_CONFIG_OPTIONS, 1 }, + .xml = + + DRI_CONF_BEGIN + DRI_CONF_SECTION_QUALITY + DRI_CONF_FORCE_S3TC_ENABLE("false") + DRI_CONF_PP_CELSHADE(0) + DRI_CONF_PP_NORED(0) + DRI_CONF_PP_NOGREEN(0) + DRI_CONF_PP_NOBLUE(0) + DRI_CONF_PP_JIMENEZMLAA(0, 0, 32) + DRI_CONF_PP_JIMENEZMLAA_COLOR(0, 0, 32) + DRI_CONF_SECTION_END + + DRI_CONF_SECTION_DEBUG + DRI_CONF_FORCE_GLSL_EXTENSIONS_WARN("false") + DRI_CONF_DISABLE_GLSL_LINE_CONTINUATIONS("false") + DRI_CONF_DISABLE_BLEND_FUNC_EXTENDED("false") + DRI_CONF_DISABLE_SHADER_BIT_ENCODING("false") + DRI_CONF_FORCE_GLSL_VERSION(0) + DRI_CONF_SECTION_END + + DRI_CONF_SECTION_MISCELLANEOUS + DRI_CONF_ALWAYS_HAVE_DEPTH_BUFFER("false") + DRI_CONF_SECTION_END + DRI_CONF_END +}; + +#define false 0 + +static const __DRIconfig ** +dri_fill_in_modes(struct dri_screen *screen) +{ + static const mesa_format mesa_formats[3] = { + MESA_FORMAT_B8G8R8A8_UNORM, + MESA_FORMAT_B8G8R8X8_UNORM, + MESA_FORMAT_B5G6R5_UNORM, + }; + static const enum pipe_format pipe_formats[3] = { + PIPE_FORMAT_BGRA8888_UNORM, + PIPE_FORMAT_BGRX8888_UNORM, + PIPE_FORMAT_B5G6R5_UNORM, + }; + mesa_format format; + __DRIconfig **configs = NULL; + uint8_t depth_bits_array[5]; + uint8_t stencil_bits_array[5]; + unsigned depth_buffer_factor; + unsigned msaa_samples_max; + unsigned i; + struct pipe_screen *p_screen = screen->base.screen; + boolean pf_z16, pf_x8z24, pf_z24x8, pf_s8z24, pf_z24s8, pf_z32; + + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML + }; + + if (driQueryOptionb(&screen->optionCache, "always_have_depth_buffer")) { + /* all visuals will have a depth buffer */ + depth_buffer_factor = 0; + } + else { + depth_bits_array[0] = 0; + stencil_bits_array[0] = 0; + depth_buffer_factor = 1; + } + + msaa_samples_max = (screen->st_api->feature_mask & ST_API_FEATURE_MS_VISUALS_MASK) + ? MSAA_VISUAL_MAX_SAMPLES : 1; + + pf_x8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24X8_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_DEPTH_STENCIL); + pf_z24x8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_X8Z24_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_DEPTH_STENCIL); + pf_s8z24 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z24_UNORM_S8_UINT, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_DEPTH_STENCIL); + pf_z24s8 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_S8_UINT_Z24_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_DEPTH_STENCIL); + pf_z16 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z16_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_DEPTH_STENCIL); + pf_z32 = p_screen->is_format_supported(p_screen, PIPE_FORMAT_Z32_UNORM, + PIPE_TEXTURE_2D, 0, + PIPE_BIND_DEPTH_STENCIL); + + if (pf_z16) { + depth_bits_array[depth_buffer_factor] = 16; + stencil_bits_array[depth_buffer_factor++] = 0; + } + if (pf_x8z24 || pf_z24x8) { + depth_bits_array[depth_buffer_factor] = 24; + stencil_bits_array[depth_buffer_factor++] = 0; + screen->d_depth_bits_last = pf_x8z24; + } + if (pf_s8z24 || pf_z24s8) { + depth_bits_array[depth_buffer_factor] = 24; + stencil_bits_array[depth_buffer_factor++] = 8; + screen->sd_depth_bits_last = pf_s8z24; + } + if (pf_z32) { + depth_bits_array[depth_buffer_factor] = 32; + stencil_bits_array[depth_buffer_factor++] = 0; + } + + assert(Elements(mesa_formats) == Elements(pipe_formats)); + + /* Add configs. */ + for (format = 0; format < Elements(mesa_formats); format++) { + __DRIconfig **new_configs = NULL; + unsigned num_msaa_modes = 0; /* includes a single-sample mode */ + uint8_t msaa_modes[MSAA_VISUAL_MAX_SAMPLES]; + + for (i = 1; i <= msaa_samples_max; i++) { + int samples = i > 1 ? i : 0; + + if (p_screen->is_format_supported(p_screen, pipe_formats[format], + PIPE_TEXTURE_2D, samples, + PIPE_BIND_RENDER_TARGET)) { + msaa_modes[num_msaa_modes++] = samples; + } + } + + if (num_msaa_modes) { + /* Single-sample configs with an accumulation buffer. */ + new_configs = driCreateConfigs(mesa_formats[format], + depth_bits_array, stencil_bits_array, + depth_buffer_factor, back_buffer_modes, + Elements(back_buffer_modes), + msaa_modes, 1, + GL_TRUE); + configs = driConcatConfigs(configs, new_configs); + + /* Multi-sample configs without an accumulation buffer. */ + if (num_msaa_modes > 1) { + new_configs = driCreateConfigs(mesa_formats[format], + depth_bits_array, stencil_bits_array, + depth_buffer_factor, back_buffer_modes, + Elements(back_buffer_modes), + msaa_modes+1, num_msaa_modes-1, + GL_FALSE); + configs = driConcatConfigs(configs, new_configs); + } + } + } + + if (configs == NULL) { + debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__); + return NULL; + } + + return (const __DRIconfig **)configs; +} + +/* The Gallium way to force MSAA. */ +DEBUG_GET_ONCE_NUM_OPTION(msaa, "GALLIUM_MSAA", 0); + +/* The NVIDIA way to force MSAA. The same variable is used by the NVIDIA + * driver. */ +DEBUG_GET_ONCE_NUM_OPTION(msaa_nv, "__GL_FSAA_MODE", 0); + +static void +dri_force_msaa_visual(struct st_visual *stvis, + struct pipe_screen *screen) +{ + int i; + int samples = debug_get_option_msaa(); + + if (!samples) + samples = debug_get_option_msaa_nv(); + + if (samples <= 1) + return; /* nothing to do */ + + /* Choose a supported sample count greater than or equal to samples. */ + for (i = samples; i <= MSAA_VISUAL_MAX_SAMPLES; i++) { + if (screen->is_format_supported(screen, stvis->color_format, + PIPE_TEXTURE_2D, i, + PIPE_BIND_RENDER_TARGET)) { + stvis->samples = i; + break; + } + } +} + +/** + * Roughly the converse of dri_fill_in_modes. + */ +void +dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen, + const struct gl_config *mode) +{ + memset(stvis, 0, sizeof(*stvis)); + + if (!mode) + return; + + if (mode->redBits == 8) { + if (mode->alphaBits == 8) + stvis->color_format = PIPE_FORMAT_BGRA8888_UNORM; + else + stvis->color_format = PIPE_FORMAT_BGRX8888_UNORM; + } else { + stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM; + } + + if (mode->sampleBuffers) { + stvis->samples = mode->samples; + } + else { + /* This must be done after stvis->color_format is set. */ + dri_force_msaa_visual(stvis, screen->base.screen); + } + + switch (mode->depthBits) { + default: + case 0: + stvis->depth_stencil_format = PIPE_FORMAT_NONE; + break; + case 16: + stvis->depth_stencil_format = PIPE_FORMAT_Z16_UNORM; + break; + case 24: + if (mode->stencilBits == 0) { + stvis->depth_stencil_format = (screen->d_depth_bits_last) ? + PIPE_FORMAT_Z24X8_UNORM: + PIPE_FORMAT_X8Z24_UNORM; + } else { + stvis->depth_stencil_format = (screen->sd_depth_bits_last) ? + PIPE_FORMAT_Z24_UNORM_S8_UINT: + PIPE_FORMAT_S8_UINT_Z24_UNORM; + } + break; + case 32: + stvis->depth_stencil_format = PIPE_FORMAT_Z32_UNORM; + break; + } + + stvis->accum_format = (mode->haveAccumBuffer) ? + PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE; + + stvis->buffer_mask |= ST_ATTACHMENT_FRONT_LEFT_MASK; + stvis->render_buffer = ST_ATTACHMENT_FRONT_LEFT; + if (mode->doubleBufferMode) { + stvis->buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK; + stvis->render_buffer = ST_ATTACHMENT_BACK_LEFT; + } + if (mode->stereoMode) { + stvis->buffer_mask |= ST_ATTACHMENT_FRONT_RIGHT_MASK; + if (mode->doubleBufferMode) + stvis->buffer_mask |= ST_ATTACHMENT_BACK_RIGHT_MASK; + } + + if (mode->haveDepthBuffer || mode->haveStencilBuffer) + stvis->buffer_mask |= ST_ATTACHMENT_DEPTH_STENCIL_MASK; + /* let the state tracker allocate the accum buffer */ +} + +static boolean +dri_get_egl_image(struct st_manager *smapi, + void *egl_image, + struct st_egl_image *stimg) +{ + struct dri_screen *screen = (struct dri_screen *)smapi; + __DRIimage *img = NULL; + + if (screen->lookup_egl_image) { + img = screen->lookup_egl_image(screen, egl_image); + } + + if (!img) + return FALSE; + + stimg->texture = NULL; + pipe_resource_reference(&stimg->texture, img->texture); + stimg->level = img->level; + stimg->layer = img->layer; + + return TRUE; +} + +static int +dri_get_param(struct st_manager *smapi, + enum st_manager_param param) +{ + struct dri_screen *screen = (struct dri_screen *)smapi; + + switch(param) { + case ST_MANAGER_BROKEN_INVALIDATE: + return screen->broken_invalidate; + default: + return 0; + } +} + +static void +dri_destroy_option_cache(struct dri_screen * screen) +{ + int i; + + if (screen->optionCache.info) { + for (i = 0; i < (1 << screen->optionCache.tableSize); ++i) { + free(screen->optionCache.info[i].name); + free(screen->optionCache.info[i].ranges); + } + free(screen->optionCache.info); + } + + free(screen->optionCache.values); + + /* Default values are copied to screen->optionCache->values in + * initOptionCache. The info field, however, is a pointer copy, so don't free + * that twice. + */ + free(screen->optionCacheDefaults.values); +} + +void +dri_destroy_screen_helper(struct dri_screen * screen) +{ + if (screen->st_api && screen->st_api->destroy) + screen->st_api->destroy(screen->st_api); + + if (screen->base.screen) + screen->base.screen->destroy(screen->base.screen); + + dri_destroy_option_cache(screen); +} + +void +dri_destroy_screen(__DRIscreen * sPriv) +{ + struct dri_screen *screen = dri_screen(sPriv); + + dri_destroy_screen_helper(screen); + +#if !GALLIUM_STATIC_TARGETS + pipe_loader_release(&screen->dev, 1); +#endif // !GALLIUM_STATIC_TARGETS + + free(screen); + sPriv->driverPrivate = NULL; + sPriv->extensions = NULL; +} + +static void +dri_postprocessing_init(struct dri_screen *screen) +{ + unsigned i; + + for (i = 0; i < PP_FILTERS; i++) { + screen->pp_enabled[i] = driQueryOptioni(&screen->optionCache, + pp_filters[i].name); + } +} + +const __DRIconfig ** +dri_init_screen_helper(struct dri_screen *screen, + struct pipe_screen *pscreen, + const char* driver_name) +{ + screen->base.screen = pscreen; + if (!screen->base.screen) { + debug_printf("%s: failed to create pipe_screen\n", __FUNCTION__); + return NULL; + } + + screen->base.get_egl_image = dri_get_egl_image; + screen->base.get_param = dri_get_param; + + screen->st_api = st_gl_api_create(); + if (!screen->st_api) + return NULL; + + if(pscreen->get_param(pscreen, PIPE_CAP_NPOT_TEXTURES)) + screen->target = PIPE_TEXTURE_2D; + else + screen->target = PIPE_TEXTURE_RECT; + + driParseOptionInfo(&screen->optionCacheDefaults, gallium_config_options.xml); + + driParseConfigFiles(&screen->optionCache, + &screen->optionCacheDefaults, + screen->sPriv->myNum, + driver_name); + + /* Handle force_s3tc_enable. */ + if (!util_format_s3tc_enabled && + driQueryOptionb(&screen->optionCache, "force_s3tc_enable")) { + /* Ensure libtxc_dxtn has been loaded if available. + * Forcing S3TC on before calling this would prevent loading + * the library. + * This is just a precaution, the driver should have called it + * already. + */ + util_format_s3tc_init(); + + util_format_s3tc_enabled = TRUE; + } + + dri_postprocessing_init(screen); + + /* gallium drivers don't declare what version of GL they support, so we + * check the computed Mesa context version after context creation and fail + * out then. + */ + if (screen->st_api->profile_mask & ST_PROFILE_DEFAULT_MASK) + screen->sPriv->max_gl_compat_version = 30; + if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_CORE_MASK) + screen->sPriv->max_gl_core_version = 33; + if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES1_MASK) + screen->sPriv->max_gl_es1_version = 11; + if (screen->st_api->profile_mask & ST_PROFILE_OPENGL_ES2_MASK) + screen->sPriv->max_gl_es2_version = 30; + + return dri_fill_in_modes(screen); +} + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/dri_screen.h b/src/gallium/state_trackers/dri/dri_screen.h new file mode 100644 index 00000000000..f421b68aed7 --- /dev/null +++ b/src/gallium/state_trackers/dri/dri_screen.h @@ -0,0 +1,157 @@ +/************************************************************************** + * + * 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 VMWARE 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. + * + **************************************************************************/ +/* + * Author: Keith Whitwell + * Author: Jakob Bornecrantz + */ + +#ifndef DRI_SCREEN_H +#define DRI_SCREEN_H + +#include "dri_util.h" +#include "xmlconfig.h" + +#include "pipe/p_compiler.h" +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "state_tracker/st_api.h" +#include "postprocess/filters.h" + +struct dri_context; +struct dri_drawable; +struct pipe_loader_device; + +struct dri_screen +{ + /* st_api */ + struct st_manager base; + struct st_api *st_api; + + /* on old libGL's invalidate doesn't get called as it should */ + boolean broken_invalidate; + + /* dri */ + __DRIscreen *sPriv; + boolean throttling_enabled; + int default_throttle_frames; + + /** Configuration cache with default values for all contexts */ + driOptionCache optionCacheDefaults; + + /** The screen's effective configuration options */ + driOptionCache optionCache; + + /* Which postprocessing filters are enabled. */ + unsigned pp_enabled[PP_FILTERS]; + + /* drm */ + int fd; + + struct pipe_loader_device *dev; + + /* gallium */ + boolean d_depth_bits_last; + boolean sd_depth_bits_last; + boolean auto_fake_front; + enum pipe_texture_target target; + + /* hooks filled in by dri2 & drisw */ + __DRIimage * (*lookup_egl_image)(struct dri_screen *ctx, void *handle); +}; + +/** cast wrapper */ +static INLINE struct dri_screen * +dri_screen(__DRIscreen * sPriv) +{ + return (struct dri_screen *)sPriv->driverPrivate; +} + +struct __DRIimageRec { + struct pipe_resource *texture; + unsigned level; + unsigned layer; + uint32_t dri_format; + uint32_t dri_components; + + void *loader_private; + + /** + * Provided by EGL_EXT_image_dma_buf_import. + */ + enum __DRIYUVColorSpace yuv_color_space; + enum __DRISampleRange sample_range; + enum __DRIChromaSiting horizontal_siting; + enum __DRIChromaSiting vertical_siting; + +}; + +#ifndef __NOT_HAVE_DRM_H + +static INLINE boolean +dri_with_format(__DRIscreen * sPriv) +{ + const __DRIdri2LoaderExtension *loader = sPriv->dri2.loader; + + return loader + && (loader->base.version >= 3) + && (loader->getBuffersWithFormat != NULL); +} + +#else + +static INLINE boolean +dri_with_format(__DRIscreen * sPriv) +{ + return TRUE; +} + +#endif + +void +dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen, + const struct gl_config *mode); + +const __DRIconfig ** +dri_init_screen_helper(struct dri_screen *screen, + struct pipe_screen *pscreen, + const char* driver_name); + +void +dri_destroy_screen_helper(struct dri_screen * screen); + +void +dri_destroy_screen(__DRIscreen * sPriv); + +extern const struct __DriverAPIRec galliumdrm_driver_api; +extern const __DRIextension *galliumdrm_driver_extensions[]; +extern const struct __DriverAPIRec galliumsw_driver_api; +extern const __DRIextension *galliumsw_driver_extensions[]; +extern const __DRIconfigOptionsExtension gallium_config_options; + +#endif + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/drisw.c b/src/gallium/state_trackers/dri/drisw.c new file mode 100644 index 00000000000..607d22297fe --- /dev/null +++ b/src/gallium/state_trackers/dri/drisw.c @@ -0,0 +1,422 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * Copyright 2010 George Sapountzis + * + * 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 VMWARE 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. + * + **************************************************************************/ + +/* TODO: + * + * xshm / EGLImage: + * + * Allow the loaders to use the XSHM extension. It probably requires callbacks + * for createImage/destroyImage similar to DRI2 getBuffers. + */ + +#include "util/u_format.h" +#include "util/u_memory.h" +#include "util/u_inlines.h" +#include "util/u_box.h" +#include "pipe/p_context.h" +#include "state_tracker/drisw_api.h" +#include "state_tracker/st_context.h" + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_drawable.h" + +DEBUG_GET_ONCE_BOOL_OPTION(swrast_no_present, "SWRAST_NO_PRESENT", FALSE); +static boolean swrast_no_present = FALSE; + +static INLINE void +get_drawable_info(__DRIdrawable *dPriv, int *x, int *y, int *w, int *h) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + + loader->getDrawableInfo(dPriv, + x, y, w, h, + dPriv->loaderPrivate); +} + +static INLINE void +put_image(__DRIdrawable *dPriv, void *data, unsigned width, unsigned height) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + + loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, + 0, 0, width, height, + data, dPriv->loaderPrivate); +} + +static INLINE void +put_image2(__DRIdrawable *dPriv, void *data, int x, int y, + unsigned width, unsigned height, unsigned stride) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + + loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, + x, y, width, height, stride, + data, dPriv->loaderPrivate); +} + +static INLINE void +get_image(__DRIdrawable *dPriv, int x, int y, int width, int height, void *data) +{ + __DRIscreen *sPriv = dPriv->driScreenPriv; + const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; + + loader->getImage(dPriv, + x, y, width, height, + data, dPriv->loaderPrivate); +} + +static void +drisw_update_drawable_info(struct dri_drawable *drawable) +{ + __DRIdrawable *dPriv = drawable->dPriv; + int x, y; + + get_drawable_info(dPriv, &x, &y, &dPriv->w, &dPriv->h); +} + +static void +drisw_put_image(struct dri_drawable *drawable, + void *data, unsigned width, unsigned height) +{ + __DRIdrawable *dPriv = drawable->dPriv; + + put_image(dPriv, data, width, height); +} + +static void +drisw_put_image2(struct dri_drawable *drawable, + void *data, int x, int y, unsigned width, unsigned height, + unsigned stride) +{ + __DRIdrawable *dPriv = drawable->dPriv; + + put_image2(dPriv, data, x, y, width, height, stride); +} + +static INLINE void +drisw_present_texture(__DRIdrawable *dPriv, + struct pipe_resource *ptex, struct pipe_box *sub_box) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct dri_screen *screen = dri_screen(drawable->sPriv); + + if (swrast_no_present) + return; + + screen->base.screen->flush_frontbuffer(screen->base.screen, ptex, 0, 0, drawable, sub_box); +} + +static INLINE void +drisw_invalidate_drawable(__DRIdrawable *dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + + drawable->texture_stamp = dPriv->lastStamp - 1; + + p_atomic_inc(&drawable->base.stamp); +} + +static INLINE void +drisw_copy_to_front(__DRIdrawable * dPriv, + struct pipe_resource *ptex) +{ + drisw_present_texture(dPriv, ptex, NULL); + + drisw_invalidate_drawable(dPriv); +} + +/* + * Backend functions for st_framebuffer interface and swap_buffers. + */ + +static void +drisw_swap_buffers(__DRIdrawable *dPriv) +{ + struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_resource *ptex; + + if (!ctx) + return; + + ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; + + if (ptex) { + if (ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) + pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); + + ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL); + + drisw_copy_to_front(dPriv, ptex); + } +} + +static void +drisw_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y, + int w, int h) +{ + struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_resource *ptex; + struct pipe_box box; + if (!ctx) + return; + + ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; + + if (ptex) { + if (ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) + pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); + + ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL); + + u_box_2d(x, dPriv->h - y - h, w, h, &box); + drisw_present_texture(dPriv, ptex, &box); + } +} + +static void +drisw_flush_frontbuffer(struct dri_context *ctx, + struct dri_drawable *drawable, + enum st_attachment_type statt) +{ + struct pipe_resource *ptex; + + if (!ctx) + return; + + ptex = drawable->textures[statt]; + + if (ptex) { + drisw_copy_to_front(ctx->dPriv, ptex); + } +} + +/** + * Allocate framebuffer attachments. + * + * During fixed-size operation, the function keeps allocating new attachments + * as they are requested. Unused attachments are not removed, not until the + * framebuffer is resized or destroyed. + */ +static void +drisw_allocate_textures(struct dri_context *stctx, + struct dri_drawable *drawable, + const enum st_attachment_type *statts, + unsigned count) +{ + struct dri_screen *screen = dri_screen(drawable->sPriv); + struct pipe_resource templ; + unsigned width, height; + boolean resized; + unsigned i; + + width = drawable->dPriv->w; + height = drawable->dPriv->h; + + resized = (drawable->old_w != width || + drawable->old_h != height); + + /* remove outdated textures */ + if (resized) { + for (i = 0; i < ST_ATTACHMENT_COUNT; i++) + pipe_resource_reference(&drawable->textures[i], NULL); + } + + memset(&templ, 0, sizeof(templ)); + templ.target = screen->target; + templ.width0 = width; + templ.height0 = height; + templ.depth0 = 1; + templ.array_size = 1; + templ.last_level = 0; + + for (i = 0; i < count; i++) { + enum pipe_format format; + unsigned bind; + + /* the texture already exists or not requested */ + if (drawable->textures[statts[i]]) + continue; + + dri_drawable_get_format(drawable, statts[i], &format, &bind); + + /* if we don't do any present, no need for display targets */ + if (statts[i] != ST_ATTACHMENT_DEPTH_STENCIL && !swrast_no_present) + bind |= PIPE_BIND_DISPLAY_TARGET; + + if (format == PIPE_FORMAT_NONE) + continue; + + templ.format = format; + templ.bind = bind; + + drawable->textures[statts[i]] = + screen->base.screen->resource_create(screen->base.screen, &templ); + } + + drawable->old_w = width; + drawable->old_h = height; +} + +static void +drisw_update_tex_buffer(struct dri_drawable *drawable, + struct dri_context *ctx, + struct pipe_resource *res) +{ + __DRIdrawable *dPriv = drawable->dPriv; + + struct st_context *st_ctx = (struct st_context *)ctx->st; + struct pipe_context *pipe = st_ctx->pipe; + struct pipe_transfer *transfer; + char *map; + int x, y, w, h; + int ximage_stride, line; + int cpp = util_format_get_blocksize(res->format); + + get_drawable_info(dPriv, &x, &y, &w, &h); + + map = pipe_transfer_map(pipe, res, + 0, 0, // level, layer, + PIPE_TRANSFER_WRITE, + x, y, w, h, &transfer); + + /* Copy the Drawable content to the mapped texture buffer */ + get_image(dPriv, x, y, w, h, map); + + /* The pipe transfer has a pitch rounded up to the nearest 64 pixels. + get_image() has a pitch rounded up to 4 bytes. */ + ximage_stride = ((w * cpp) + 3) & -4; + for (line = h-1; line; --line) { + memmove(&map[line * transfer->stride], + &map[line * ximage_stride], + ximage_stride); + } + + pipe_transfer_unmap(pipe, transfer); +} + +/* + * Backend function for init_screen. + */ + +static const __DRIextension *drisw_screen_extensions[] = { + &driTexBufferExtension.base, + NULL +}; + +static struct drisw_loader_funcs drisw_lf = { + .put_image = drisw_put_image, + .put_image2 = drisw_put_image2 +}; + +static const __DRIconfig ** +drisw_init_screen(__DRIscreen * sPriv) +{ + const __DRIconfig **configs; + struct dri_screen *screen; + struct pipe_screen *pscreen; + + screen = CALLOC_STRUCT(dri_screen); + if (!screen) + return NULL; + + screen->sPriv = sPriv; + screen->fd = -1; + + swrast_no_present = debug_get_option_swrast_no_present(); + + sPriv->driverPrivate = (void *)screen; + sPriv->extensions = drisw_screen_extensions; + + pscreen = drisw_create_screen(&drisw_lf); + /* dri_init_screen_helper checks pscreen for us */ + + configs = dri_init_screen_helper(screen, pscreen, "swrast"); + if (!configs) + goto fail; + + return configs; +fail: + dri_destroy_screen_helper(screen); + FREE(screen); + return NULL; +} + +static boolean +drisw_create_buffer(__DRIscreen * sPriv, + __DRIdrawable * dPriv, + const struct gl_config * visual, boolean isPixmap) +{ + struct dri_drawable *drawable = NULL; + + if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) + return FALSE; + + drawable = dPriv->driverPrivate; + + drawable->allocate_textures = drisw_allocate_textures; + drawable->update_drawable_info = drisw_update_drawable_info; + drawable->flush_frontbuffer = drisw_flush_frontbuffer; + drawable->update_tex_buffer = drisw_update_tex_buffer; + + return TRUE; +} + +/** + * DRI driver virtual function table. + * + * DRI versions differ in their implementation of init_screen and swap_buffers. + */ +const struct __DriverAPIRec galliumsw_driver_api = { + .InitScreen = drisw_init_screen, + .DestroyScreen = dri_destroy_screen, + .CreateContext = dri_create_context, + .DestroyContext = dri_destroy_context, + .CreateBuffer = drisw_create_buffer, + .DestroyBuffer = dri_destroy_buffer, + .SwapBuffers = drisw_swap_buffers, + .MakeCurrent = dri_make_current, + .UnbindContext = dri_unbind_context, + .CopySubBuffer = drisw_copy_sub_buffer, +}; + +/* This is the table of extensions that the loader will dlsym() for. */ +const __DRIextension *galliumsw_driver_extensions[] = { + &driCoreExtension.base, + &driSWRastExtension.base, + &driCopySubBufferExtension.base, + &gallium_config_options.base, + NULL +}; + +/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/drm/Makefile.am b/src/gallium/state_trackers/dri/drm/Makefile.am deleted file mode 100644 index 8052e6bf750..00000000000 --- a/src/gallium/state_trackers/dri/drm/Makefile.am +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright © 2012 Intel Corporation -# -# 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 (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 -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -include Makefile.sources -include $(top_srcdir)/src/gallium/Automake.inc - -AM_CPPFLAGS = \ - $(GALLIUM_PIPE_LOADER_DEFINES) \ - -DPIPE_SEARCH_DIR=\"$(libdir)/gallium-pipe\" \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/src/mapi \ - -I$(top_srcdir)/src/mesa \ - -I$(top_srcdir)/src/gallium/state_trackers/dri/common \ - -I$(top_srcdir)/src/mesa/drivers/dri/common \ - -I$(top_builddir)/src/mesa/drivers/dri/common \ - $(GALLIUM_CFLAGS) \ - $(LIBDRM_CFLAGS) \ - $(VISIBILITY_CFLAGS) - -if HAVE_GALLIUM_STATIC_TARGETS -AM_CPPFLAGS += \ - -DGALLIUM_STATIC_TARGETS=1 -endif # HAVE_GALLIUM_STATIC_TARGETS - -noinst_LTLIBRARIES = libdridrm.la - -libdridrm_la_SOURCES = $(C_SOURCES) diff --git a/src/gallium/state_trackers/dri/drm/Makefile.sources b/src/gallium/state_trackers/dri/drm/Makefile.sources deleted file mode 100644 index b9b93a24e8a..00000000000 --- a/src/gallium/state_trackers/dri/drm/Makefile.sources +++ /dev/null @@ -1,5 +0,0 @@ -C_SOURCES := \ - dri_context.c \ - dri_screen.c \ - dri_drawable.c \ - dri2.c diff --git a/src/gallium/state_trackers/dri/drm/SConscript b/src/gallium/state_trackers/dri/drm/SConscript deleted file mode 100644 index 761603942c3..00000000000 --- a/src/gallium/state_trackers/dri/drm/SConscript +++ /dev/null @@ -1,24 +0,0 @@ -####################################################################### -# SConscript for dri state_tracker - -Import('*') - -env = env.Clone() - -env.PkgUseModules(['DRM']) - -env.Append(CPPPATH = [ - '#/src/mapi', - '#/src/mesa', - '#/src/gallium/state_trackers/dri/common', - '#/src/mesa/drivers/dri/common', - xmlpool_options.dir.dir, # Dir to generated xmlpool/options.h -]) - -env.Append(CPPDEFINES = [('GALLIUM_STATIC_TARGETS', '1')]) - -st_dri = env.ConvenienceLibrary( - target = 'st_dri', - source = env.ParseSourceList('Makefile.sources', 'C_SOURCES') -) -Export('st_dri') diff --git a/src/gallium/state_trackers/dri/drm/dri2.c b/src/gallium/state_trackers/dri/drm/dri2.c deleted file mode 100644 index f6a4fe679f3..00000000000 --- a/src/gallium/state_trackers/dri/drm/dri2.c +++ /dev/null @@ -1,1354 +0,0 @@ -/* - * Mesa 3-D graphics library - * - * Copyright 2009, VMware, Inc. - * All Rights Reserved. - * Copyright (C) 2010 LunarG Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell Jakob Bornecrantz - * Chia-I Wu - */ - -#include -#include "util/u_memory.h" -#include "util/u_inlines.h" -#include "util/u_format.h" -#include "util/u_debug.h" -#include "state_tracker/drm_driver.h" -#include "state_tracker/st_texture.h" -#include "state_tracker/st_context.h" -#include "pipe-loader/pipe_loader.h" -#include "main/texobj.h" - -#include "dri_screen.h" -#include "dri_context.h" -#include "dri_drawable.h" -#include "dri2_buffer.h" - -static int convert_fourcc(int format, int *dri_components_p) -{ - int dri_components; - switch(format) { - case __DRI_IMAGE_FOURCC_RGB565: - format = __DRI_IMAGE_FORMAT_RGB565; - dri_components = __DRI_IMAGE_COMPONENTS_RGB; - break; - case __DRI_IMAGE_FOURCC_ARGB8888: - format = __DRI_IMAGE_FORMAT_ARGB8888; - dri_components = __DRI_IMAGE_COMPONENTS_RGBA; - break; - case __DRI_IMAGE_FOURCC_XRGB8888: - format = __DRI_IMAGE_FORMAT_XRGB8888; - dri_components = __DRI_IMAGE_COMPONENTS_RGB; - break; - case __DRI_IMAGE_FOURCC_ABGR8888: - format = __DRI_IMAGE_FORMAT_ABGR8888; - dri_components = __DRI_IMAGE_COMPONENTS_RGBA; - break; - case __DRI_IMAGE_FOURCC_XBGR8888: - format = __DRI_IMAGE_FORMAT_XBGR8888; - dri_components = __DRI_IMAGE_COMPONENTS_RGB; - break; - default: - return -1; - } - *dri_components_p = dri_components; - return format; -} - -/** - * DRI2 flush extension. - */ -static void -dri2_flush_drawable(__DRIdrawable *dPriv) -{ - dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1); -} - -static void -dri2_invalidate_drawable(__DRIdrawable *dPriv) -{ - struct dri_drawable *drawable = dri_drawable(dPriv); - - dri2InvalidateDrawable(dPriv); - drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp; - - p_atomic_inc(&drawable->base.stamp); -} - -static const __DRI2flushExtension dri2FlushExtension = { - .base = { __DRI2_FLUSH, 4 }, - - .flush = dri2_flush_drawable, - .invalidate = dri2_invalidate_drawable, - .flush_with_flags = dri_flush, -}; - -/** - * Retrieve __DRIbuffer from the DRI loader. - */ -static __DRIbuffer * -dri2_drawable_get_buffers(struct dri_drawable *drawable, - const enum st_attachment_type *atts, - unsigned *count) -{ - __DRIdrawable *dri_drawable = drawable->dPriv; - const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; - boolean with_format; - __DRIbuffer *buffers; - int num_buffers; - unsigned attachments[10]; - unsigned num_attachments, i; - - assert(loader); - with_format = dri_with_format(drawable->sPriv); - - num_attachments = 0; - - /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */ - if (!with_format) - attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT; - - for (i = 0; i < *count; i++) { - enum pipe_format format; - unsigned bind; - int att, depth; - - dri_drawable_get_format(drawable, atts[i], &format, &bind); - if (format == PIPE_FORMAT_NONE) - continue; - - switch (atts[i]) { - case ST_ATTACHMENT_FRONT_LEFT: - /* already added */ - if (!with_format) - continue; - att = __DRI_BUFFER_FRONT_LEFT; - break; - case ST_ATTACHMENT_BACK_LEFT: - att = __DRI_BUFFER_BACK_LEFT; - break; - case ST_ATTACHMENT_FRONT_RIGHT: - att = __DRI_BUFFER_FRONT_RIGHT; - break; - case ST_ATTACHMENT_BACK_RIGHT: - att = __DRI_BUFFER_BACK_RIGHT; - break; - default: - continue; - } - - /* - * In this switch statement we must support all formats that - * may occur as the stvis->color_format. - */ - switch(format) { - case PIPE_FORMAT_B8G8R8A8_UNORM: - depth = 32; - break; - case PIPE_FORMAT_B8G8R8X8_UNORM: - depth = 24; - break; - case PIPE_FORMAT_B5G6R5_UNORM: - depth = 16; - break; - default: - depth = util_format_get_blocksizebits(format); - assert(!"Unexpected format in dri2_drawable_get_buffers()"); - } - - attachments[num_attachments++] = att; - if (with_format) { - attachments[num_attachments++] = depth; - } - } - - if (with_format) { - num_attachments /= 2; - buffers = loader->getBuffersWithFormat(dri_drawable, - &dri_drawable->w, &dri_drawable->h, - attachments, num_attachments, - &num_buffers, dri_drawable->loaderPrivate); - } - else { - buffers = loader->getBuffers(dri_drawable, - &dri_drawable->w, &dri_drawable->h, - attachments, num_attachments, - &num_buffers, dri_drawable->loaderPrivate); - } - - if (buffers) - *count = num_buffers; - - return buffers; -} - -static bool -dri_image_drawable_get_buffers(struct dri_drawable *drawable, - struct __DRIimageList *images, - const enum st_attachment_type *statts, - unsigned statts_count) -{ - __DRIdrawable *dPriv = drawable->dPriv; - __DRIscreen *sPriv = drawable->sPriv; - unsigned int image_format = __DRI_IMAGE_FORMAT_NONE; - enum pipe_format pf; - uint32_t buffer_mask = 0; - unsigned i, bind; - - for (i = 0; i < statts_count; i++) { - dri_drawable_get_format(drawable, statts[i], &pf, &bind); - if (pf == PIPE_FORMAT_NONE) - continue; - - switch (statts[i]) { - case ST_ATTACHMENT_FRONT_LEFT: - buffer_mask |= __DRI_IMAGE_BUFFER_FRONT; - break; - case ST_ATTACHMENT_BACK_LEFT: - buffer_mask |= __DRI_IMAGE_BUFFER_BACK; - break; - default: - continue; - } - - switch (pf) { - case PIPE_FORMAT_B5G6R5_UNORM: - image_format = __DRI_IMAGE_FORMAT_RGB565; - break; - case PIPE_FORMAT_B8G8R8X8_UNORM: - image_format = __DRI_IMAGE_FORMAT_XRGB8888; - break; - case PIPE_FORMAT_B8G8R8A8_UNORM: - image_format = __DRI_IMAGE_FORMAT_ARGB8888; - break; - case PIPE_FORMAT_R8G8B8A8_UNORM: - image_format = __DRI_IMAGE_FORMAT_ABGR8888; - break; - default: - image_format = __DRI_IMAGE_FORMAT_NONE; - break; - } - } - - return (*sPriv->image.loader->getBuffers) (dPriv, image_format, - (uint32_t *) &drawable->base.stamp, - dPriv->loaderPrivate, buffer_mask, - images); -} - -static __DRIbuffer * -dri2_allocate_buffer(__DRIscreen *sPriv, - unsigned attachment, unsigned format, - int width, int height) -{ - struct dri_screen *screen = dri_screen(sPriv); - struct dri2_buffer *buffer; - struct pipe_resource templ; - enum pipe_format pf; - unsigned bind = 0; - struct winsys_handle whandle; - - switch (attachment) { - case __DRI_BUFFER_FRONT_LEFT: - case __DRI_BUFFER_FAKE_FRONT_LEFT: - bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; - break; - case __DRI_BUFFER_BACK_LEFT: - bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; - break; - case __DRI_BUFFER_DEPTH: - case __DRI_BUFFER_DEPTH_STENCIL: - case __DRI_BUFFER_STENCIL: - bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ - break; - } - - /* because we get the handle and stride */ - bind |= PIPE_BIND_SHARED; - - switch (format) { - case 32: - pf = PIPE_FORMAT_B8G8R8A8_UNORM; - break; - case 24: - pf = PIPE_FORMAT_B8G8R8X8_UNORM; - break; - case 16: - pf = PIPE_FORMAT_Z16_UNORM; - break; - default: - return NULL; - } - - buffer = CALLOC_STRUCT(dri2_buffer); - if (!buffer) - return NULL; - - memset(&templ, 0, sizeof(templ)); - templ.bind = bind; - templ.format = pf; - templ.target = PIPE_TEXTURE_2D; - templ.last_level = 0; - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - - buffer->resource = - screen->base.screen->resource_create(screen->base.screen, &templ); - if (!buffer->resource) { - FREE(buffer); - return NULL; - } - - memset(&whandle, 0, sizeof(whandle)); - whandle.type = DRM_API_HANDLE_TYPE_SHARED; - screen->base.screen->resource_get_handle(screen->base.screen, - buffer->resource, &whandle); - - buffer->base.attachment = attachment; - buffer->base.name = whandle.handle; - buffer->base.cpp = util_format_get_blocksize(pf); - buffer->base.pitch = whandle.stride; - - return &buffer->base; -} - -static void -dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv) -{ - struct dri2_buffer *buffer = dri2_buffer(bPriv); - - pipe_resource_reference(&buffer->resource, NULL); - FREE(buffer); -} - -/* - * Backend functions for st_framebuffer interface. - */ - -static void -dri2_allocate_textures(struct dri_context *ctx, - struct dri_drawable *drawable, - const enum st_attachment_type *statts, - unsigned statts_count) -{ - __DRIscreen *sPriv = drawable->sPriv; - __DRIdrawable *dri_drawable = drawable->dPriv; - struct dri_screen *screen = dri_screen(sPriv); - struct pipe_resource templ; - boolean alloc_depthstencil = FALSE; - unsigned i, j, bind; - const __DRIimageLoaderExtension *image = sPriv->image.loader; - /* Image specific variables */ - struct __DRIimageList images; - /* Dri2 specific variables */ - __DRIbuffer *buffers; - struct winsys_handle whandle; - unsigned num_buffers = statts_count; - - /* First get the buffers from the loader */ - if (image) { - if (!dri_image_drawable_get_buffers(drawable, &images, - statts, statts_count)) - return; - } - else { - buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers); - if (!buffers || (drawable->old_num == num_buffers && - drawable->old_w == dri_drawable->w && - drawable->old_h == dri_drawable->h && - memcmp(drawable->old, buffers, - sizeof(__DRIbuffer) * num_buffers) == 0)) - return; - } - - /* Second clean useless resources*/ - - /* See if we need a depth-stencil buffer. */ - for (i = 0; i < statts_count; i++) { - if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { - alloc_depthstencil = TRUE; - break; - } - } - - /* Delete the resources we won't need. */ - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - /* Don't delete the depth-stencil buffer, we can reuse it. */ - if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil) - continue; - - /* Flush the texture before unreferencing, so that other clients can - * see what the driver has rendered. - */ - if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) { - struct pipe_context *pipe = ctx->st->pipe; - pipe->flush_resource(pipe, drawable->textures[i]); - } - - pipe_resource_reference(&drawable->textures[i], NULL); - } - - if (drawable->stvis.samples > 1) { - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { - boolean del = TRUE; - - /* Don't delete MSAA resources for the attachments which are enabled, - * we can reuse them. */ - for (j = 0; j < statts_count; j++) { - if (i == statts[j]) { - del = FALSE; - break; - } - } - - if (del) { - pipe_resource_reference(&drawable->msaa_textures[i], NULL); - } - } - } - - /* Third use the buffers retrieved to fill the drawable info */ - - memset(&templ, 0, sizeof(templ)); - templ.target = screen->target; - templ.last_level = 0; - templ.depth0 = 1; - templ.array_size = 1; - - if (image) { - if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) { - struct pipe_resource **buf = - &drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; - struct pipe_resource *texture = images.front->texture; - - dri_drawable->w = texture->width0; - dri_drawable->h = texture->height0; - - pipe_resource_reference(buf, texture); - } - - if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) { - struct pipe_resource **buf = - &drawable->textures[ST_ATTACHMENT_BACK_LEFT]; - struct pipe_resource *texture = images.back->texture; - - dri_drawable->w = texture->width0; - dri_drawable->h = texture->height0; - - pipe_resource_reference(buf, texture); - } - - /* Note: if there is both a back and a front buffer, - * then they have the same size. - */ - templ.width0 = dri_drawable->w; - templ.height0 = dri_drawable->h; - } - else { - memset(&whandle, 0, sizeof(whandle)); - - /* Process DRI-provided buffers and get pipe_resources. */ - for (i = 0; i < num_buffers; i++) { - __DRIbuffer *buf = &buffers[i]; - enum st_attachment_type statt; - enum pipe_format format; - - switch (buf->attachment) { - case __DRI_BUFFER_FRONT_LEFT: - if (!screen->auto_fake_front) { - continue; /* invalid attachment */ - } - /* fallthrough */ - case __DRI_BUFFER_FAKE_FRONT_LEFT: - statt = ST_ATTACHMENT_FRONT_LEFT; - break; - case __DRI_BUFFER_BACK_LEFT: - statt = ST_ATTACHMENT_BACK_LEFT; - break; - default: - continue; /* invalid attachment */ - } - - dri_drawable_get_format(drawable, statt, &format, &bind); - if (format == PIPE_FORMAT_NONE) - continue; - - /* dri2_drawable_get_buffers has already filled dri_drawable->w - * and dri_drawable->h */ - templ.width0 = dri_drawable->w; - templ.height0 = dri_drawable->h; - templ.format = format; - templ.bind = bind; - whandle.type = DRM_API_HANDLE_TYPE_SHARED; - whandle.handle = buf->name; - whandle.stride = buf->pitch; - - drawable->textures[statt] = - screen->base.screen->resource_from_handle(screen->base.screen, - &templ, &whandle); - assert(drawable->textures[statt]); - } - } - - /* Allocate private MSAA colorbuffers. */ - if (drawable->stvis.samples > 1) { - for (i = 0; i < statts_count; i++) { - enum st_attachment_type statt = statts[i]; - - if (statt == ST_ATTACHMENT_DEPTH_STENCIL) - continue; - - if (drawable->textures[statt]) { - templ.format = drawable->textures[statt]->format; - templ.bind = drawable->textures[statt]->bind; - templ.nr_samples = drawable->stvis.samples; - - /* Try to reuse the resource. - * (the other resource parameters should be constant) - */ - if (!drawable->msaa_textures[statt] || - drawable->msaa_textures[statt]->width0 != templ.width0 || - drawable->msaa_textures[statt]->height0 != templ.height0) { - /* Allocate a new one. */ - pipe_resource_reference(&drawable->msaa_textures[statt], NULL); - - drawable->msaa_textures[statt] = - screen->base.screen->resource_create(screen->base.screen, - &templ); - assert(drawable->msaa_textures[statt]); - - /* If there are any MSAA resources, we should initialize them - * such that they contain the same data as the single-sample - * resources we just got from the X server. - * - * The reason for this is that the state tracker (and - * therefore the app) can access the MSAA resources only. - * The single-sample resources are not exposed - * to the state tracker. - * - */ - dri_pipe_blit(ctx->st->pipe, - drawable->msaa_textures[statt], - drawable->textures[statt]); - } - } - else { - pipe_resource_reference(&drawable->msaa_textures[statt], NULL); - } - } - } - - /* Allocate a private depth-stencil buffer. */ - if (alloc_depthstencil) { - enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL; - struct pipe_resource **zsbuf; - enum pipe_format format; - unsigned bind; - - dri_drawable_get_format(drawable, statt, &format, &bind); - - if (format) { - templ.format = format; - templ.bind = bind; - - if (drawable->stvis.samples > 1) { - templ.nr_samples = drawable->stvis.samples; - zsbuf = &drawable->msaa_textures[statt]; - } - else { - templ.nr_samples = 0; - zsbuf = &drawable->textures[statt]; - } - - /* Try to reuse the resource. - * (the other resource parameters should be constant) - */ - if (!*zsbuf || - (*zsbuf)->width0 != templ.width0 || - (*zsbuf)->height0 != templ.height0) { - /* Allocate a new one. */ - pipe_resource_reference(zsbuf, NULL); - *zsbuf = screen->base.screen->resource_create(screen->base.screen, - &templ); - assert(*zsbuf); - } - } - else { - pipe_resource_reference(&drawable->msaa_textures[statt], NULL); - pipe_resource_reference(&drawable->textures[statt], NULL); - } - } - - /* For DRI2, we may get the same buffers again from the server. - * To prevent useless imports of gem names, drawable->old* is used - * to bypass the import if we get the same buffers. This doesn't apply - * to DRI3/Wayland, users of image.loader, since the buffer is managed - * by the client (no import), and the back buffer is going to change - * at every redraw. - */ - if (!image) { - drawable->old_num = num_buffers; - drawable->old_w = dri_drawable->w; - drawable->old_h = dri_drawable->h; - memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers); - } -} - -static void -dri2_flush_frontbuffer(struct dri_context *ctx, - struct dri_drawable *drawable, - enum st_attachment_type statt) -{ - __DRIdrawable *dri_drawable = drawable->dPriv; - const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader; - const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; - struct pipe_context *pipe = ctx->st->pipe; - - if (statt != ST_ATTACHMENT_FRONT_LEFT) - return; - - if (drawable->stvis.samples > 1) { - /* Resolve the front buffer. */ - dri_pipe_blit(ctx->st->pipe, - drawable->textures[ST_ATTACHMENT_FRONT_LEFT], - drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]); - } - - if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) { - pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]); - } - - pipe->flush(pipe, NULL, 0); - - if (image) { - image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); - } - else if (loader->flushFrontBuffer) { - loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); - } -} - -static void -dri2_update_tex_buffer(struct dri_drawable *drawable, - struct dri_context *ctx, - struct pipe_resource *res) -{ - /* no-op */ -} - -static __DRIimage * -dri2_lookup_egl_image(struct dri_screen *screen, void *handle) -{ - const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image; - __DRIimage *img; - - if (!loader->lookupEGLImage) - return NULL; - - img = loader->lookupEGLImage(screen->sPriv, - handle, screen->sPriv->loaderPrivate); - - return img; -} - -static __DRIimage * -dri2_create_image_from_winsys(__DRIscreen *_screen, - int width, int height, int format, - struct winsys_handle *whandle, int pitch, - void *loaderPrivate) -{ - struct dri_screen *screen = dri_screen(_screen); - __DRIimage *img; - struct pipe_resource templ; - unsigned tex_usage; - enum pipe_format pf; - - tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; - - switch (format) { - case __DRI_IMAGE_FORMAT_RGB565: - pf = PIPE_FORMAT_B5G6R5_UNORM; - break; - case __DRI_IMAGE_FORMAT_XRGB8888: - pf = PIPE_FORMAT_B8G8R8X8_UNORM; - break; - case __DRI_IMAGE_FORMAT_ARGB8888: - pf = PIPE_FORMAT_B8G8R8A8_UNORM; - break; - case __DRI_IMAGE_FORMAT_ABGR8888: - pf = PIPE_FORMAT_R8G8B8A8_UNORM; - break; - default: - pf = PIPE_FORMAT_NONE; - break; - } - if (pf == PIPE_FORMAT_NONE) - return NULL; - - img = CALLOC_STRUCT(__DRIimageRec); - if (!img) - return NULL; - - memset(&templ, 0, sizeof(templ)); - templ.bind = tex_usage; - templ.format = pf; - templ.target = screen->target; - templ.last_level = 0; - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - - whandle->stride = pitch * util_format_get_blocksize(pf); - - img->texture = screen->base.screen->resource_from_handle(screen->base.screen, - &templ, whandle); - if (!img->texture) { - FREE(img); - return NULL; - } - - img->level = 0; - img->layer = 0; - img->dri_format = format; - img->loader_private = loaderPrivate; - - return img; -} - -static __DRIimage * -dri2_create_image_from_name(__DRIscreen *_screen, - int width, int height, int format, - int name, int pitch, void *loaderPrivate) -{ - struct winsys_handle whandle; - - memset(&whandle, 0, sizeof(whandle)); - whandle.type = DRM_API_HANDLE_TYPE_SHARED; - whandle.handle = name; - - return dri2_create_image_from_winsys(_screen, width, height, format, - &whandle, pitch, loaderPrivate); -} - -static __DRIimage * -dri2_create_image_from_fd(__DRIscreen *_screen, - int width, int height, int format, - int fd, int pitch, void *loaderPrivate) -{ - struct winsys_handle whandle; - - if (fd < 0) - return NULL; - - memset(&whandle, 0, sizeof(whandle)); - whandle.type = DRM_API_HANDLE_TYPE_FD; - whandle.handle = (unsigned)fd; - - return dri2_create_image_from_winsys(_screen, width, height, format, - &whandle, pitch, loaderPrivate); -} - -static __DRIimage * -dri2_create_image_from_renderbuffer(__DRIcontext *context, - int renderbuffer, void *loaderPrivate) -{ - struct dri_context *ctx = dri_context(context); - - if (!ctx->st->get_resource_for_egl_image) - return NULL; - - /* TODO */ - return NULL; -} - -static __DRIimage * -dri2_create_image(__DRIscreen *_screen, - int width, int height, int format, - unsigned int use, void *loaderPrivate) -{ - struct dri_screen *screen = dri_screen(_screen); - __DRIimage *img; - struct pipe_resource templ; - unsigned tex_usage; - enum pipe_format pf; - - tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; - if (use & __DRI_IMAGE_USE_SCANOUT) - tex_usage |= PIPE_BIND_SCANOUT; - if (use & __DRI_IMAGE_USE_SHARE) - tex_usage |= PIPE_BIND_SHARED; - if (use & __DRI_IMAGE_USE_LINEAR) - tex_usage |= PIPE_BIND_LINEAR; - if (use & __DRI_IMAGE_USE_CURSOR) { - if (width != 64 || height != 64) - return NULL; - tex_usage |= PIPE_BIND_CURSOR; - } - - switch (format) { - case __DRI_IMAGE_FORMAT_RGB565: - pf = PIPE_FORMAT_B5G6R5_UNORM; - break; - case __DRI_IMAGE_FORMAT_XRGB8888: - pf = PIPE_FORMAT_B8G8R8X8_UNORM; - break; - case __DRI_IMAGE_FORMAT_ARGB8888: - pf = PIPE_FORMAT_B8G8R8A8_UNORM; - break; - case __DRI_IMAGE_FORMAT_ABGR8888: - pf = PIPE_FORMAT_R8G8B8A8_UNORM; - break; - default: - pf = PIPE_FORMAT_NONE; - break; - } - if (pf == PIPE_FORMAT_NONE) - return NULL; - - img = CALLOC_STRUCT(__DRIimageRec); - if (!img) - return NULL; - - memset(&templ, 0, sizeof(templ)); - templ.bind = tex_usage; - templ.format = pf; - templ.target = PIPE_TEXTURE_2D; - templ.last_level = 0; - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - - img->texture = screen->base.screen->resource_create(screen->base.screen, &templ); - if (!img->texture) { - FREE(img); - return NULL; - } - - img->level = 0; - img->layer = 0; - img->dri_format = format; - img->dri_components = 0; - - img->loader_private = loaderPrivate; - return img; -} - -static GLboolean -dri2_query_image(__DRIimage *image, int attrib, int *value) -{ - struct winsys_handle whandle; - memset(&whandle, 0, sizeof(whandle)); - - switch (attrib) { - case __DRI_IMAGE_ATTRIB_STRIDE: - whandle.type = DRM_API_HANDLE_TYPE_KMS; - image->texture->screen->resource_get_handle(image->texture->screen, - image->texture, &whandle); - *value = whandle.stride; - return GL_TRUE; - case __DRI_IMAGE_ATTRIB_HANDLE: - whandle.type = DRM_API_HANDLE_TYPE_KMS; - image->texture->screen->resource_get_handle(image->texture->screen, - image->texture, &whandle); - *value = whandle.handle; - return GL_TRUE; - case __DRI_IMAGE_ATTRIB_NAME: - whandle.type = DRM_API_HANDLE_TYPE_SHARED; - image->texture->screen->resource_get_handle(image->texture->screen, - image->texture, &whandle); - *value = whandle.handle; - return GL_TRUE; - case __DRI_IMAGE_ATTRIB_FD: - whandle.type= DRM_API_HANDLE_TYPE_FD; - image->texture->screen->resource_get_handle(image->texture->screen, - image->texture, &whandle); - *value = whandle.handle; - return GL_TRUE; - case __DRI_IMAGE_ATTRIB_FORMAT: - *value = image->dri_format; - return GL_TRUE; - case __DRI_IMAGE_ATTRIB_WIDTH: - *value = image->texture->width0; - return GL_TRUE; - case __DRI_IMAGE_ATTRIB_HEIGHT: - *value = image->texture->height0; - return GL_TRUE; - case __DRI_IMAGE_ATTRIB_COMPONENTS: - if (image->dri_components == 0) - return GL_FALSE; - *value = image->dri_components; - return GL_TRUE; - default: - return GL_FALSE; - } -} - -static __DRIimage * -dri2_dup_image(__DRIimage *image, void *loaderPrivate) -{ - __DRIimage *img; - - img = CALLOC_STRUCT(__DRIimageRec); - if (!img) - return NULL; - - img->texture = NULL; - pipe_resource_reference(&img->texture, image->texture); - img->level = image->level; - img->layer = image->layer; - img->dri_format = image->dri_format; - /* This should be 0 for sub images, but dup is also used for base images. */ - img->dri_components = image->dri_components; - img->loader_private = loaderPrivate; - - return img; -} - -static GLboolean -dri2_validate_usage(__DRIimage *image, unsigned int use) -{ - /* - * Gallium drivers are bad at adding usages to the resources - * once opened again in another process, which is the main use - * case for this, so we have to lie. - */ - if (image != NULL) - return GL_TRUE; - else - return GL_FALSE; -} - -static __DRIimage * -dri2_from_names(__DRIscreen *screen, int width, int height, int format, - int *names, int num_names, int *strides, int *offsets, - void *loaderPrivate) -{ - __DRIimage *img; - int stride, dri_components; - - if (num_names != 1) - return NULL; - if (offsets[0] != 0) - return NULL; - - format = convert_fourcc(format, &dri_components); - if (format == -1) - return NULL; - - /* Strides are in bytes not pixels. */ - stride = strides[0] /4; - - img = dri2_create_image_from_name(screen, width, height, format, - names[0], stride, loaderPrivate); - if (img == NULL) - return NULL; - - img->dri_components = dri_components; - return img; -} - -static __DRIimage * -dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate) -{ - __DRIimage *img; - - if (plane != 0) - return NULL; - - if (image->dri_components == 0) - return NULL; - - img = dri2_dup_image(image, loaderPrivate); - if (img == NULL) - return NULL; - - /* set this to 0 for sub images. */ - img->dri_components = 0; - return img; -} - -static __DRIimage * -dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture, - int depth, int level, unsigned *error, - void *loaderPrivate) -{ - __DRIimage *img; - struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx; - struct gl_texture_object *obj; - struct pipe_resource *tex; - GLuint face = 0; - - obj = _mesa_lookup_texture(ctx, texture); - if (!obj || obj->Target != target) { - *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; - return NULL; - } - - tex = st_get_texobj_resource(obj); - if (!tex) { - *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; - return NULL; - } - - if (target == GL_TEXTURE_CUBE_MAP) - face = depth; - - _mesa_test_texobj_completeness(ctx, obj); - if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) { - *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; - return NULL; - } - - if (level < obj->BaseLevel || level > obj->_MaxLevel) { - *error = __DRI_IMAGE_ERROR_BAD_MATCH; - return NULL; - } - - if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) { - *error = __DRI_IMAGE_ERROR_BAD_MATCH; - return NULL; - } - - img = CALLOC_STRUCT(__DRIimageRec); - if (!img) { - *error = __DRI_IMAGE_ERROR_BAD_ALLOC; - return NULL; - } - - img->level = level; - img->layer = depth; - img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat); - - img->loader_private = loaderPrivate; - - if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) { - *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; - free(img); - return NULL; - } - - pipe_resource_reference(&img->texture, tex); - - *error = __DRI_IMAGE_ERROR_SUCCESS; - return img; -} - -static __DRIimage * -dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc, - int *fds, int num_fds, int *strides, int *offsets, - void *loaderPrivate) -{ - __DRIimage *img; - int format, stride, dri_components; - - if (num_fds != 1) - return NULL; - if (offsets[0] != 0) - return NULL; - - format = convert_fourcc(fourcc, &dri_components); - if (format == -1) - return NULL; - - /* Strides are in bytes not pixels. */ - stride = strides[0] /4; - - img = dri2_create_image_from_fd(screen, width, height, format, - fds[0], stride, loaderPrivate); - if (img == NULL) - return NULL; - - img->dri_components = dri_components; - return img; -} - -static __DRIimage * -dri2_from_dma_bufs(__DRIscreen *screen, - int width, int height, int fourcc, - int *fds, int num_fds, - int *strides, int *offsets, - enum __DRIYUVColorSpace yuv_color_space, - enum __DRISampleRange sample_range, - enum __DRIChromaSiting horizontal_siting, - enum __DRIChromaSiting vertical_siting, - unsigned *error, - void *loaderPrivate) -{ - __DRIimage *img; - int format, stride, dri_components; - - if (num_fds != 1 || offsets[0] != 0) { - *error = __DRI_IMAGE_ERROR_BAD_MATCH; - return NULL; - } - - format = convert_fourcc(fourcc, &dri_components); - if (format == -1) { - *error = __DRI_IMAGE_ERROR_BAD_MATCH; - return NULL; - } - - /* Strides are in bytes not pixels. */ - stride = strides[0] /4; - - img = dri2_create_image_from_fd(screen, width, height, format, - fds[0], stride, loaderPrivate); - if (img == NULL) { - *error = __DRI_IMAGE_ERROR_BAD_ALLOC; - return NULL; - } - - img->yuv_color_space = yuv_color_space; - img->sample_range = sample_range; - img->horizontal_siting = horizontal_siting; - img->vertical_siting = vertical_siting; - img->dri_components = dri_components; - - *error = __DRI_IMAGE_ERROR_SUCCESS; - return img; -} - -static void -dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src, - int dstx0, int dsty0, int dstwidth, int dstheight, - int srcx0, int srcy0, int srcwidth, int srcheight, - int flush_flag) -{ - struct dri_context *ctx = dri_context(context); - struct pipe_context *pipe = ctx->st->pipe; - struct pipe_screen *screen; - struct pipe_fence_handle *fence; - struct pipe_blit_info blit; - - if (!dst || !src) - return; - - memset(&blit, 0, sizeof(blit)); - blit.dst.resource = dst->texture; - blit.dst.box.x = dstx0; - blit.dst.box.y = dsty0; - blit.dst.box.width = dstwidth; - blit.dst.box.height = dstheight; - blit.dst.box.depth = 1; - blit.dst.format = dst->texture->format; - blit.src.resource = src->texture; - blit.src.box.x = srcx0; - blit.src.box.y = srcy0; - blit.src.box.width = srcwidth; - blit.src.box.height = srcheight; - blit.src.box.depth = 1; - blit.src.format = src->texture->format; - blit.mask = PIPE_MASK_RGBA; - blit.filter = PIPE_TEX_FILTER_NEAREST; - - pipe->blit(pipe, &blit); - - if (flush_flag == __BLIT_FLAG_FLUSH) { - pipe->flush_resource(pipe, dst->texture); - ctx->st->flush(ctx->st, 0, NULL); - } else if (flush_flag == __BLIT_FLAG_FINISH) { - screen = dri_screen(ctx->sPriv)->base.screen; - pipe->flush_resource(pipe, dst->texture); - ctx->st->flush(ctx->st, 0, &fence); - (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE); - screen->fence_reference(screen, &fence, NULL); - } -} - -static void -dri2_destroy_image(__DRIimage *img) -{ - pipe_resource_reference(&img->texture, NULL); - FREE(img); -} - -/* The extension is modified during runtime if DRI_PRIME is detected */ -static __DRIimageExtension dri2ImageExtension = { - .base = { __DRI_IMAGE, 9 }, - - .createImageFromName = dri2_create_image_from_name, - .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer, - .destroyImage = dri2_destroy_image, - .createImage = dri2_create_image, - .queryImage = dri2_query_image, - .dupImage = dri2_dup_image, - .validateUsage = dri2_validate_usage, - .createImageFromNames = dri2_from_names, - .fromPlanar = dri2_from_planar, - .createImageFromTexture = dri2_create_from_texture, - .createImageFromFds = NULL, - .createImageFromDmaBufs = NULL, - .blitImage = dri2_blit_image, -}; - -/* - * Backend function init_screen. - */ - -static const __DRIextension *dri_screen_extensions[] = { - &driTexBufferExtension.base, - &dri2FlushExtension.base, - &dri2ImageExtension.base, - &dri2ConfigQueryExtension.base, - &dri2ThrottleExtension.base, - NULL -}; - -/** - * This is the driver specific part of the createNewScreen entry point. - * - * Returns the struct gl_config supported by this driver. - */ -static const __DRIconfig ** -dri2_init_screen(__DRIscreen * sPriv) -{ - const __DRIconfig **configs; - struct dri_screen *screen; - struct pipe_screen *pscreen = NULL; - const struct drm_conf_ret *throttle_ret = NULL; - const struct drm_conf_ret *dmabuf_ret = NULL; - - screen = CALLOC_STRUCT(dri_screen); - if (!screen) - return NULL; - - screen->sPriv = sPriv; - screen->fd = sPriv->fd; - - sPriv->driverPrivate = (void *)screen; - -#if SPLIT_TARGETS - pscreen = driver_descriptor.create_screen(screen->fd); - if (driver_descriptor.configuration) { - throttle_ret = driver_descriptor.configuration(DRM_CONF_THROTTLE); - dmabuf_ret = driver_descriptor.configuration(DRM_CONF_SHARE_FD); - } - -#else -#if GALLIUM_STATIC_TARGETS - pscreen = dd_create_screen(screen->fd); - - throttle_ret = dd_configuration(DRM_CONF_THROTTLE); - dmabuf_ret = dd_configuration(DRM_CONF_SHARE_FD); -#else - if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd, true)) { - pscreen = pipe_loader_create_screen(screen->dev, PIPE_SEARCH_DIR); - - throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE); - dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD); - } -#endif // GALLIUM_STATIC_TARGETS -#endif // SPLIT_TARGETS - - if (throttle_ret && throttle_ret->val.val_int != -1) { - screen->throttling_enabled = TRUE; - screen->default_throttle_frames = throttle_ret->val.val_int; - } - - if (dmabuf_ret && dmabuf_ret->val.val_bool) { - uint64_t cap; - - if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 && - (cap & DRM_PRIME_CAP_IMPORT)) { - dri2ImageExtension.createImageFromFds = dri2_from_fds; - dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs; - } - } - - sPriv->extensions = dri_screen_extensions; - - /* dri_init_screen_helper checks pscreen for us */ - - configs = dri_init_screen_helper(screen, pscreen); - if (!configs) - goto fail; - - screen->auto_fake_front = dri_with_format(sPriv); - screen->broken_invalidate = !sPriv->dri2.useInvalidate; - screen->lookup_egl_image = dri2_lookup_egl_image; - - return configs; -fail: - dri_destroy_screen_helper(screen); -#if !SPLIT_TARGETS -#if !GALLIUM_STATIC_TARGETS - if (screen->dev) - pipe_loader_release(&screen->dev, 1); -#endif // !GALLIUM_STATIC_TARGETS -#endif // !SPLIT_TARGETS - FREE(screen); - return NULL; -} - -static boolean -dri2_create_buffer(__DRIscreen * sPriv, - __DRIdrawable * dPriv, - const struct gl_config * visual, boolean isPixmap) -{ - struct dri_drawable *drawable = NULL; - - if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) - return FALSE; - - drawable = dPriv->driverPrivate; - - drawable->allocate_textures = dri2_allocate_textures; - drawable->flush_frontbuffer = dri2_flush_frontbuffer; - drawable->update_tex_buffer = dri2_update_tex_buffer; - - return TRUE; -} - -/** - * DRI driver virtual function table. - * - * DRI versions differ in their implementation of init_screen and swap_buffers. - */ -const struct __DriverAPIRec galliumdrm_driver_api = { - .InitScreen = dri2_init_screen, - .DestroyScreen = dri_destroy_screen, - .CreateContext = dri_create_context, - .DestroyContext = dri_destroy_context, - .CreateBuffer = dri2_create_buffer, - .DestroyBuffer = dri_destroy_buffer, - .MakeCurrent = dri_make_current, - .UnbindContext = dri_unbind_context, - - .AllocateBuffer = dri2_allocate_buffer, - .ReleaseBuffer = dri2_release_buffer, -}; - -/* This is the table of extensions that the loader will dlsym() for. */ -const __DRIextension *galliumdrm_driver_extensions[] = { - &driCoreExtension.base, - &driImageDriverExtension.base, - &driDRI2Extension.base, - &gallium_config_options.base, - NULL -}; - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/drm/dri2_buffer.h b/src/gallium/state_trackers/dri/drm/dri2_buffer.h deleted file mode 100644 index e8e474ddb76..00000000000 --- a/src/gallium/state_trackers/dri/drm/dri2_buffer.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef DRI2_BUFFER_H -#define DRI2_BUFFER_H - -#include "dri_util.h" - -struct pipe_surface; - -struct dri2_buffer -{ - __DRIbuffer base; - struct pipe_resource *resource; -}; - -static INLINE struct dri2_buffer * -dri2_buffer(__DRIbuffer * driBufferPriv) -{ - return (struct dri2_buffer *) driBufferPriv; -} - -#endif - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ diff --git a/src/gallium/state_trackers/dri/drm/dri_context.c b/src/gallium/state_trackers/dri/drm/dri_context.c deleted file mode 120000 index 5cfbbaeb068..00000000000 --- a/src/gallium/state_trackers/dri/drm/dri_context.c +++ /dev/null @@ -1 +0,0 @@ -../common/dri_context.c \ No newline at end of file diff --git a/src/gallium/state_trackers/dri/drm/dri_drawable.c b/src/gallium/state_trackers/dri/drm/dri_drawable.c deleted file mode 120000 index 0fc19be6ea6..00000000000 --- a/src/gallium/state_trackers/dri/drm/dri_drawable.c +++ /dev/null @@ -1 +0,0 @@ -../common/dri_drawable.c \ No newline at end of file diff --git a/src/gallium/state_trackers/dri/drm/dri_screen.c b/src/gallium/state_trackers/dri/drm/dri_screen.c deleted file mode 120000 index 847f6515f25..00000000000 --- a/src/gallium/state_trackers/dri/drm/dri_screen.c +++ /dev/null @@ -1 +0,0 @@ -../common/dri_screen.c \ No newline at end of file diff --git a/src/gallium/state_trackers/dri/sw/Makefile.am b/src/gallium/state_trackers/dri/sw/Makefile.am deleted file mode 100644 index 0cebd6df5fa..00000000000 --- a/src/gallium/state_trackers/dri/sw/Makefile.am +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright © 2012 Intel Corporation -# -# 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 (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 -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -# DEALINGS IN THE SOFTWARE. - -include Makefile.sources -include $(top_srcdir)/src/gallium/Automake.inc - -AM_CPPFLAGS = \ - $(GALLIUM_PIPE_LOADER_DEFINES) \ - -DPIPE_SEARCH_DIR=\"$(libdir)/gallium-pipe\" \ - -DSPLIT_TARGETS=1 \ - -I$(top_srcdir)/src/mapi \ - -I$(top_srcdir)/src/mesa \ - -I$(top_srcdir)/src/gallium/state_trackers/dri/common \ - -I$(top_srcdir)/src/mesa/drivers/dri/common \ - -I$(top_builddir)/src/mesa/drivers/dri/common \ - $(GALLIUM_CFLAGS) \ - $(LIBDRM_CFLAGS) \ - $(VISIBILITY_CFLAGS) \ - -D__NOT_HAVE_DRM_H - -noinst_LTLIBRARIES = libdrisw.la - -libdrisw_la_SOURCES = $(C_SOURCES) diff --git a/src/gallium/state_trackers/dri/sw/Makefile.sources b/src/gallium/state_trackers/dri/sw/Makefile.sources deleted file mode 100644 index 1255934cabc..00000000000 --- a/src/gallium/state_trackers/dri/sw/Makefile.sources +++ /dev/null @@ -1,5 +0,0 @@ -C_SOURCES := \ - dri_context.c \ - dri_screen.c \ - dri_drawable.c \ - drisw.c diff --git a/src/gallium/state_trackers/dri/sw/SConscript b/src/gallium/state_trackers/dri/sw/SConscript deleted file mode 100644 index 5a71b2246f0..00000000000 --- a/src/gallium/state_trackers/dri/sw/SConscript +++ /dev/null @@ -1,23 +0,0 @@ -####################################################################### -# SConscript for dri state_tracker - -Import('*') - -env = env.Clone() - -env.Append(CPPPATH = [ - '#/src/mapi', - '#/src/mesa', - '#/src/gallium/state_trackers/dri/common', - '#/src/mesa/drivers/dri/common', - xmlpool_options.dir.dir, # Dir to generated xmlpool/options.h -]) - -env.Append(CPPDEFINES = [('__NOT_HAVE_DRM_H', '1')]) -env.Append(CPPDEFINES = [('SPLIT_TARGETS', '1')]) - -st_drisw = env.ConvenienceLibrary( - target = 'st_drisw', - source = env.ParseSourceList('Makefile.sources', 'C_SOURCES') -) -Export('st_drisw') diff --git a/src/gallium/state_trackers/dri/sw/dri_context.c b/src/gallium/state_trackers/dri/sw/dri_context.c deleted file mode 120000 index 5cfbbaeb068..00000000000 --- a/src/gallium/state_trackers/dri/sw/dri_context.c +++ /dev/null @@ -1 +0,0 @@ -../common/dri_context.c \ No newline at end of file diff --git a/src/gallium/state_trackers/dri/sw/dri_drawable.c b/src/gallium/state_trackers/dri/sw/dri_drawable.c deleted file mode 120000 index 0fc19be6ea6..00000000000 --- a/src/gallium/state_trackers/dri/sw/dri_drawable.c +++ /dev/null @@ -1 +0,0 @@ -../common/dri_drawable.c \ No newline at end of file diff --git a/src/gallium/state_trackers/dri/sw/dri_screen.c b/src/gallium/state_trackers/dri/sw/dri_screen.c deleted file mode 120000 index 847f6515f25..00000000000 --- a/src/gallium/state_trackers/dri/sw/dri_screen.c +++ /dev/null @@ -1 +0,0 @@ -../common/dri_screen.c \ No newline at end of file diff --git a/src/gallium/state_trackers/dri/sw/drisw.c b/src/gallium/state_trackers/dri/sw/drisw.c deleted file mode 100644 index f1d5a067148..00000000000 --- a/src/gallium/state_trackers/dri/sw/drisw.c +++ /dev/null @@ -1,422 +0,0 @@ -/************************************************************************** - * - * Copyright 2009, VMware, Inc. - * All Rights Reserved. - * Copyright 2010 George Sapountzis - * - * 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 VMWARE 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. - * - **************************************************************************/ - -/* TODO: - * - * xshm / EGLImage: - * - * Allow the loaders to use the XSHM extension. It probably requires callbacks - * for createImage/destroyImage similar to DRI2 getBuffers. - */ - -#include "util/u_format.h" -#include "util/u_memory.h" -#include "util/u_inlines.h" -#include "util/u_box.h" -#include "pipe/p_context.h" -#include "state_tracker/drisw_api.h" -#include "state_tracker/st_context.h" - -#include "dri_screen.h" -#include "dri_context.h" -#include "dri_drawable.h" - -DEBUG_GET_ONCE_BOOL_OPTION(swrast_no_present, "SWRAST_NO_PRESENT", FALSE); -static boolean swrast_no_present = FALSE; - -static INLINE void -get_drawable_info(__DRIdrawable *dPriv, int *x, int *y, int *w, int *h) -{ - __DRIscreen *sPriv = dPriv->driScreenPriv; - const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; - - loader->getDrawableInfo(dPriv, - x, y, w, h, - dPriv->loaderPrivate); -} - -static INLINE void -put_image(__DRIdrawable *dPriv, void *data, unsigned width, unsigned height) -{ - __DRIscreen *sPriv = dPriv->driScreenPriv; - const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; - - loader->putImage(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, - 0, 0, width, height, - data, dPriv->loaderPrivate); -} - -static INLINE void -put_image2(__DRIdrawable *dPriv, void *data, int x, int y, - unsigned width, unsigned height, unsigned stride) -{ - __DRIscreen *sPriv = dPriv->driScreenPriv; - const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; - - loader->putImage2(dPriv, __DRI_SWRAST_IMAGE_OP_SWAP, - x, y, width, height, stride, - data, dPriv->loaderPrivate); -} - -static INLINE void -get_image(__DRIdrawable *dPriv, int x, int y, int width, int height, void *data) -{ - __DRIscreen *sPriv = dPriv->driScreenPriv; - const __DRIswrastLoaderExtension *loader = sPriv->swrast_loader; - - loader->getImage(dPriv, - x, y, width, height, - data, dPriv->loaderPrivate); -} - -static void -drisw_update_drawable_info(struct dri_drawable *drawable) -{ - __DRIdrawable *dPriv = drawable->dPriv; - int x, y; - - get_drawable_info(dPriv, &x, &y, &dPriv->w, &dPriv->h); -} - -static void -drisw_put_image(struct dri_drawable *drawable, - void *data, unsigned width, unsigned height) -{ - __DRIdrawable *dPriv = drawable->dPriv; - - put_image(dPriv, data, width, height); -} - -static void -drisw_put_image2(struct dri_drawable *drawable, - void *data, int x, int y, unsigned width, unsigned height, - unsigned stride) -{ - __DRIdrawable *dPriv = drawable->dPriv; - - put_image2(dPriv, data, x, y, width, height, stride); -} - -static INLINE void -drisw_present_texture(__DRIdrawable *dPriv, - struct pipe_resource *ptex, struct pipe_box *sub_box) -{ - struct dri_drawable *drawable = dri_drawable(dPriv); - struct dri_screen *screen = dri_screen(drawable->sPriv); - - if (swrast_no_present) - return; - - screen->base.screen->flush_frontbuffer(screen->base.screen, ptex, 0, 0, drawable, sub_box); -} - -static INLINE void -drisw_invalidate_drawable(__DRIdrawable *dPriv) -{ - struct dri_drawable *drawable = dri_drawable(dPriv); - - drawable->texture_stamp = dPriv->lastStamp - 1; - - p_atomic_inc(&drawable->base.stamp); -} - -static INLINE void -drisw_copy_to_front(__DRIdrawable * dPriv, - struct pipe_resource *ptex) -{ - drisw_present_texture(dPriv, ptex, NULL); - - drisw_invalidate_drawable(dPriv); -} - -/* - * Backend functions for st_framebuffer interface and swap_buffers. - */ - -static void -drisw_swap_buffers(__DRIdrawable *dPriv) -{ - struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); - struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_resource *ptex; - - if (!ctx) - return; - - ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; - - if (ptex) { - if (ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) - pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); - - ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL); - - drisw_copy_to_front(dPriv, ptex); - } -} - -static void -drisw_copy_sub_buffer(__DRIdrawable *dPriv, int x, int y, - int w, int h) -{ - struct dri_context *ctx = dri_get_current(dPriv->driScreenPriv); - struct dri_drawable *drawable = dri_drawable(dPriv); - struct pipe_resource *ptex; - struct pipe_box box; - if (!ctx) - return; - - ptex = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; - - if (ptex) { - if (ctx->pp && drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]) - pp_run(ctx->pp, ptex, ptex, drawable->textures[ST_ATTACHMENT_DEPTH_STENCIL]); - - ctx->st->flush(ctx->st, ST_FLUSH_FRONT, NULL); - - u_box_2d(x, dPriv->h - y - h, w, h, &box); - drisw_present_texture(dPriv, ptex, &box); - } -} - -static void -drisw_flush_frontbuffer(struct dri_context *ctx, - struct dri_drawable *drawable, - enum st_attachment_type statt) -{ - struct pipe_resource *ptex; - - if (!ctx) - return; - - ptex = drawable->textures[statt]; - - if (ptex) { - drisw_copy_to_front(ctx->dPriv, ptex); - } -} - -/** - * Allocate framebuffer attachments. - * - * During fixed-size operation, the function keeps allocating new attachments - * as they are requested. Unused attachments are not removed, not until the - * framebuffer is resized or destroyed. - */ -static void -drisw_allocate_textures(struct dri_context *stctx, - struct dri_drawable *drawable, - const enum st_attachment_type *statts, - unsigned count) -{ - struct dri_screen *screen = dri_screen(drawable->sPriv); - struct pipe_resource templ; - unsigned width, height; - boolean resized; - unsigned i; - - width = drawable->dPriv->w; - height = drawable->dPriv->h; - - resized = (drawable->old_w != width || - drawable->old_h != height); - - /* remove outdated textures */ - if (resized) { - for (i = 0; i < ST_ATTACHMENT_COUNT; i++) - pipe_resource_reference(&drawable->textures[i], NULL); - } - - memset(&templ, 0, sizeof(templ)); - templ.target = screen->target; - templ.width0 = width; - templ.height0 = height; - templ.depth0 = 1; - templ.array_size = 1; - templ.last_level = 0; - - for (i = 0; i < count; i++) { - enum pipe_format format; - unsigned bind; - - /* the texture already exists or not requested */ - if (drawable->textures[statts[i]]) - continue; - - dri_drawable_get_format(drawable, statts[i], &format, &bind); - - /* if we don't do any present, no need for display targets */ - if (statts[i] != ST_ATTACHMENT_DEPTH_STENCIL && !swrast_no_present) - bind |= PIPE_BIND_DISPLAY_TARGET; - - if (format == PIPE_FORMAT_NONE) - continue; - - templ.format = format; - templ.bind = bind; - - drawable->textures[statts[i]] = - screen->base.screen->resource_create(screen->base.screen, &templ); - } - - drawable->old_w = width; - drawable->old_h = height; -} - -static void -drisw_update_tex_buffer(struct dri_drawable *drawable, - struct dri_context *ctx, - struct pipe_resource *res) -{ - __DRIdrawable *dPriv = drawable->dPriv; - - struct st_context *st_ctx = (struct st_context *)ctx->st; - struct pipe_context *pipe = st_ctx->pipe; - struct pipe_transfer *transfer; - char *map; - int x, y, w, h; - int ximage_stride, line; - int cpp = util_format_get_blocksize(res->format); - - get_drawable_info(dPriv, &x, &y, &w, &h); - - map = pipe_transfer_map(pipe, res, - 0, 0, // level, layer, - PIPE_TRANSFER_WRITE, - x, y, w, h, &transfer); - - /* Copy the Drawable content to the mapped texture buffer */ - get_image(dPriv, x, y, w, h, map); - - /* The pipe transfer has a pitch rounded up to the nearest 64 pixels. - get_image() has a pitch rounded up to 4 bytes. */ - ximage_stride = ((w * cpp) + 3) & -4; - for (line = h-1; line; --line) { - memmove(&map[line * transfer->stride], - &map[line * ximage_stride], - ximage_stride); - } - - pipe_transfer_unmap(pipe, transfer); -} - -/* - * Backend function for init_screen. - */ - -static const __DRIextension *drisw_screen_extensions[] = { - &driTexBufferExtension.base, - NULL -}; - -static struct drisw_loader_funcs drisw_lf = { - .put_image = drisw_put_image, - .put_image2 = drisw_put_image2 -}; - -static const __DRIconfig ** -drisw_init_screen(__DRIscreen * sPriv) -{ - const __DRIconfig **configs; - struct dri_screen *screen; - struct pipe_screen *pscreen; - - screen = CALLOC_STRUCT(dri_screen); - if (!screen) - return NULL; - - screen->sPriv = sPriv; - screen->fd = -1; - - swrast_no_present = debug_get_option_swrast_no_present(); - - sPriv->driverPrivate = (void *)screen; - sPriv->extensions = drisw_screen_extensions; - - pscreen = drisw_create_screen(&drisw_lf); - /* dri_init_screen_helper checks pscreen for us */ - - configs = dri_init_screen_helper(screen, pscreen); - if (!configs) - goto fail; - - return configs; -fail: - dri_destroy_screen_helper(screen); - FREE(screen); - return NULL; -} - -static boolean -drisw_create_buffer(__DRIscreen * sPriv, - __DRIdrawable * dPriv, - const struct gl_config * visual, boolean isPixmap) -{ - struct dri_drawable *drawable = NULL; - - if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) - return FALSE; - - drawable = dPriv->driverPrivate; - - drawable->allocate_textures = drisw_allocate_textures; - drawable->update_drawable_info = drisw_update_drawable_info; - drawable->flush_frontbuffer = drisw_flush_frontbuffer; - drawable->update_tex_buffer = drisw_update_tex_buffer; - - return TRUE; -} - -/** - * DRI driver virtual function table. - * - * DRI versions differ in their implementation of init_screen and swap_buffers. - */ -const struct __DriverAPIRec galliumsw_driver_api = { - .InitScreen = drisw_init_screen, - .DestroyScreen = dri_destroy_screen, - .CreateContext = dri_create_context, - .DestroyContext = dri_destroy_context, - .CreateBuffer = drisw_create_buffer, - .DestroyBuffer = dri_destroy_buffer, - .SwapBuffers = drisw_swap_buffers, - .MakeCurrent = dri_make_current, - .UnbindContext = dri_unbind_context, - .CopySubBuffer = drisw_copy_sub_buffer, -}; - -/* This is the table of extensions that the loader will dlsym() for. */ -const __DRIextension *galliumsw_driver_extensions[] = { - &driCoreExtension.base, - &driSWRastExtension.base, - &driCopySubBufferExtension.base, - &gallium_config_options.base, - NULL -}; - -/* vim: set sw=3 ts=8 sts=3 expandtab: */ -- cgit v1.2.3