src/gallium/state_trackers/Makefile
src/gallium/state_trackers/clover/Makefile
src/gallium/state_trackers/dri/Makefile
- src/gallium/state_trackers/dri/drm/Makefile
- src/gallium/state_trackers/dri/sw/Makefile
src/gallium/state_trackers/egl/Makefile
src/gallium/state_trackers/gbm/Makefile
src/gallium/state_trackers/glx/xlib/Makefile
GALLIUM_DRI_CFLAGS = \
-I$(top_srcdir)/include \
- -I$(top_srcdir)/src/gallium/state_trackers/dri/common \
+ -I$(top_srcdir)/src/gallium/state_trackers/dri \
-I$(top_srcdir)/src/mesa/drivers/dri/common \
-I$(top_srcdir)/src/gallium/include \
-I$(top_srcdir)/src/gallium/auxiliary \
# 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"),
# 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
--- /dev/null
+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
+#######################################################################
+# 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')
+++ /dev/null
-/**************************************************************************
- *
- * 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 <keithw@vmware.com>
- * Author: Jakob Bornecrantz <wallbraker@gmail.com>
- */
-
-#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: */
+++ /dev/null
-/**************************************************************************
- *
- * 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 <keithw@vmware.com>
- * Author: Jakob Bornecrantz <wallbraker@gmail.com>
- */
-
-#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: */
+++ /dev/null
-/**************************************************************************
- *
- * 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 <keithw@vmware.com>
- * Author: Jakob Bornecrantz <wallbraker@gmail.com>
- */
-
-#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: */
+++ /dev/null
-/**************************************************************************
- *
- * 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: */
+++ /dev/null
-/**************************************************************************
- *
- * 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 <keithw@vmware.com>
- * Author: Jakob Bornecrantz <wallbraker@gmail.com>
- */
-
-#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: */
+++ /dev/null
-/**************************************************************************
- *
- * 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 <keithw@vmware.com>
- * Author: Jakob Bornecrantz <wallbraker@gmail.com>
- */
-
-#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: */
--- /dev/null
+/*
+ * 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 <keithw@vmware.com> Jakob Bornecrantz
+ * <wallbraker@gmail.com> Chia-I Wu <olv@lunarg.com>
+ */
+
+#include <xf86drm.h>
+#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: */
--- /dev/null
+#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: */
--- /dev/null
+/**************************************************************************
+ *
+ * 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 <keithw@vmware.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ */
+
+#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: */
--- /dev/null
+/**************************************************************************
+ *
+ * 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 <keithw@vmware.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ */
+
+#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: */
--- /dev/null
+/**************************************************************************
+ *
+ * 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 <keithw@vmware.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ */
+
+#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: */
--- /dev/null
+/**************************************************************************
+ *
+ * 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: */
--- /dev/null
+/**************************************************************************
+ *
+ * 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 <keithw@vmware.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ */
+
+#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: */
--- /dev/null
+/**************************************************************************
+ *
+ * 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 <keithw@vmware.com>
+ * Author: Jakob Bornecrantz <wallbraker@gmail.com>
+ */
+
+#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: */
--- /dev/null
+/**************************************************************************
+ *
+ * Copyright 2009, VMware, Inc.
+ * All Rights Reserved.
+ * Copyright 2010 George Sapountzis <gsapountzis@gmail.com>
+ *
+ * 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: */
+++ /dev/null
-# 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)
+++ /dev/null
-C_SOURCES := \
- dri_context.c \
- dri_screen.c \
- dri_drawable.c \
- dri2.c
+++ /dev/null
-#######################################################################
-# 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')
+++ /dev/null
-/*
- * 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 <keithw@vmware.com> Jakob Bornecrantz
- * <wallbraker@gmail.com> Chia-I Wu <olv@lunarg.com>
- */
-
-#include <xf86drm.h>
-#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: */
+++ /dev/null
-#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: */
+++ /dev/null
-../common/dri_context.c
\ No newline at end of file
+++ /dev/null
-../common/dri_drawable.c
\ No newline at end of file
+++ /dev/null
-../common/dri_screen.c
\ No newline at end of file
+++ /dev/null
-# 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)
+++ /dev/null
-C_SOURCES := \
- dri_context.c \
- dri_screen.c \
- dri_drawable.c \
- drisw.c
+++ /dev/null
-#######################################################################
-# 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')
+++ /dev/null
-../common/dri_context.c
\ No newline at end of file
+++ /dev/null
-../common/dri_drawable.c
\ No newline at end of file
+++ /dev/null
-../common/dri_screen.c
\ No newline at end of file
+++ /dev/null
-/**************************************************************************
- *
- * Copyright 2009, VMware, Inc.
- * All Rights Reserved.
- * Copyright 2010 George Sapountzis <gsapountzis@gmail.com>
- *
- * 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: */
swrast_dri_la_LIBADD = \
$(top_builddir)/src/mesa/drivers/dri/common/libdricommon.la \
$(top_builddir)/src/mesa/drivers/dri/common/libmegadriver_stub.la \
- $(top_builddir)/src/gallium/state_trackers/dri/sw/libdrisw.la \
+ $(top_builddir)/src/gallium/state_trackers/dri/libdri.la \
$(top_builddir)/src/gallium/winsys/sw/dri/libswdri.la \
$(top_builddir)/src/gallium/drivers/softpipe/libsoftpipe.la \
$(top_builddir)/src/gallium/drivers/trace/libtrace.la \
'#/src/mapi',
'#/src/mesa',
'#/src/mesa/drivers/dri/common',
- '#/src/gallium/state_trackers/dri/common',
+ '#/src/gallium/state_trackers/dri',
])
env.Prepend(LIBS = [
- st_drisw,
+ st_dri,
ws_dri,
trace,
rbug,
-I$(top_srcdir)/src/mapi \
-I$(top_srcdir)/src/mesa \
-I$(top_srcdir)/src/mesa/drivers/dri/common \
- -I$(top_srcdir)/src/gallium/state_trackers/dri/common \
+ -I$(top_srcdir)/src/gallium/state_trackers/dri \
$(GALLIUM_TARGET_CFLAGS)
AM_CPPFLAGS = \
-Wl,--version-script=$(top_srcdir)/src/gallium/targets/dri/dri.sym
endif # HAVE_LD_VERSION_SCRIPT
-# XXX: Fold libdridrm/libdrisw as drivers become megadriver (__dri*DriverExtension) aware
gallium_dri_la_LIBADD = \
$(top_builddir)/src/mesa/libmesagallium.la \
$(top_builddir)/src/mesa/drivers/dri/common/libdricommon.la \
$(top_builddir)/src/mesa/drivers/dri/common/libmegadriver_stub.la \
- $(top_builddir)/src/gallium/state_trackers/dri/drm/libdridrm.la \
+ $(top_builddir)/src/gallium/state_trackers/dri/libdri.la \
$(top_builddir)/src/gallium/auxiliary/libgallium.la \
$(top_builddir)/src/gallium/drivers/galahad/libgalahad.la \
$(top_builddir)/src/gallium/drivers/noop/libnoop.la \
'#/src/mapi',
'#/src/mesa',
'#/src/mesa/drivers/dri/common',
- '#/src/gallium/state_trackers/dri/common',
+ '#/src/gallium/state_trackers/dri',
])
if env['build'] == 'release':