Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 5562 → Rev 5563

/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/Android.mk
0,0 → 1,66
# Mesa 3-D graphics library
#
# Copyright (C) 2010-2011 Chia-I Wu <olvaffe@gmail.com>
# Copyright (C) 2010-2011 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.
 
LOCAL_PATH := $(call my-dir)
 
# from Makefile
C_SOURCES = \
sp_fs_exec.c \
sp_clear.c \
sp_fence.c \
sp_flush.c \
sp_query.c \
sp_context.c \
sp_draw_arrays.c \
sp_prim_vbuf.c \
sp_quad_pipe.c \
sp_quad_stipple.c \
sp_quad_depth_test.c \
sp_quad_fs.c \
sp_quad_blend.c \
sp_screen.c \
sp_setup.c \
sp_state_blend.c \
sp_state_clip.c \
sp_state_derived.c \
sp_state_sampler.c \
sp_state_shader.c \
sp_state_so.c \
sp_state_rasterizer.c \
sp_state_surface.c \
sp_state_vertex.c \
sp_texture.c \
sp_tex_sample.c \
sp_tex_tile_cache.c \
sp_tile_cache.c \
sp_surface.c
 
include $(CLEAR_VARS)
 
LOCAL_SRC_FILES := \
$(C_SOURCES)
 
LOCAL_MODULE := libmesa_pipe_softpipe
 
include $(GALLIUM_COMMON_MK)
include $(BUILD_STATIC_LIBRARY)
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/Makefile.am
0,0 → 1,61
# 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 $(top_srcdir)/src/gallium/Automake.inc
 
AM_CPPFLAGS = \
-I$(top_srcdir)/src/gallium/drivers \
-I$(top_srcdir)/include \
$(GALLIUM_CFLAGS)
 
noinst_LTLIBRARIES = libsoftpipe.la
 
libsoftpipe_la_SOURCES = \
sp_fs_exec.c \
sp_clear.c \
sp_fence.c \
sp_flush.c \
sp_query.c \
sp_context.c \
sp_draw_arrays.c \
sp_prim_vbuf.c \
sp_quad_pipe.c \
sp_quad_stipple.c \
sp_quad_depth_test.c \
sp_quad_fs.c \
sp_quad_blend.c \
sp_screen.c \
sp_setup.c \
sp_state_blend.c \
sp_state_clip.c \
sp_state_derived.c \
sp_state_sampler.c \
sp_state_shader.c \
sp_state_so.c \
sp_state_rasterizer.c \
sp_state_surface.c \
sp_state_vertex.c \
sp_texture.c \
sp_tex_sample.c \
sp_tex_tile_cache.c \
sp_tile_cache.c \
sp_surface.c
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/Makefile.in
0,0 → 1,844
# Makefile.in generated by automake 1.14 from Makefile.am.
# @configure_input@
 
# Copyright (C) 1994-2013 Free Software Foundation, Inc.
 
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
 
@SET_MAKE@
 
# 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.
 
VPATH = @srcdir@
am__is_gnu_make = test -n '$(MAKEFILE_LIST)' && test -n '$(MAKELEVEL)'
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
DIST_COMMON = $(top_srcdir)/src/gallium/Automake.inc \
$(srcdir)/Makefile.in $(srcdir)/Makefile.am \
$(top_srcdir)/bin/depcomp
subdir = src/gallium/drivers/softpipe
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/ax_prog_bison.m4 \
$(top_srcdir)/m4/ax_prog_cc_for_build.m4 \
$(top_srcdir)/m4/ax_prog_cxx_for_build.m4 \
$(top_srcdir)/m4/ax_prog_flex.m4 \
$(top_srcdir)/m4/ax_pthread.m4 \
$(top_srcdir)/m4/ax_python_module.m4 \
$(top_srcdir)/m4/libtool.m4 $(top_srcdir)/m4/ltoptions.m4 \
$(top_srcdir)/m4/ltsugar.m4 $(top_srcdir)/m4/ltversion.m4 \
$(top_srcdir)/m4/lt~obsolete.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
mkinstalldirs = $(install_sh) -d
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libsoftpipe_la_LIBADD =
am_libsoftpipe_la_OBJECTS = sp_fs_exec.lo sp_clear.lo sp_fence.lo \
sp_flush.lo sp_query.lo sp_context.lo sp_draw_arrays.lo \
sp_prim_vbuf.lo sp_quad_pipe.lo sp_quad_stipple.lo \
sp_quad_depth_test.lo sp_quad_fs.lo sp_quad_blend.lo \
sp_screen.lo sp_setup.lo sp_state_blend.lo sp_state_clip.lo \
sp_state_derived.lo sp_state_sampler.lo sp_state_shader.lo \
sp_state_so.lo sp_state_rasterizer.lo sp_state_surface.lo \
sp_state_vertex.lo sp_texture.lo sp_tex_sample.lo \
sp_tex_tile_cache.lo sp_tile_cache.lo sp_surface.lo
libsoftpipe_la_OBJECTS = $(am_libsoftpipe_la_OBJECTS)
AM_V_lt = $(am__v_lt_@AM_V@)
am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
am__v_lt_0 = --silent
am__v_lt_1 =
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp = $(SHELL) $(top_srcdir)/bin/depcomp
am__depfiles_maybe = depfiles
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
$(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
$(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(libsoftpipe_la_SOURCES)
DIST_SOURCES = $(libsoftpipe_la_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
ETAGS = etags
CTAGS = ctags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILD_EXEEXT = @BUILD_EXEEXT@
BUILD_OBJEXT = @BUILD_OBJEXT@
CC = @CC@
CCAS = @CCAS@
CCASDEPMODE = @CCASDEPMODE@
CCASFLAGS = @CCASFLAGS@
CCDEPMODE = @CCDEPMODE@
CC_FOR_BUILD = @CC_FOR_BUILD@
CFLAGS = @CFLAGS@
CFLAGS_FOR_BUILD = @CFLAGS_FOR_BUILD@
CLANG_RESOURCE_DIR = @CLANG_RESOURCE_DIR@
CLOCK_LIB = @CLOCK_LIB@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CPPFLAGS_FOR_BUILD = @CPPFLAGS_FOR_BUILD@
CPP_FOR_BUILD = @CPP_FOR_BUILD@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXCPPFLAGS_FOR_BUILD = @CXXCPPFLAGS_FOR_BUILD@
CXXCPP_FOR_BUILD = @CXXCPP_FOR_BUILD@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CXXFLAGS_FOR_BUILD = @CXXFLAGS_FOR_BUILD@
CXX_FOR_BUILD = @CXX_FOR_BUILD@
CYGPATH_W = @CYGPATH_W@
DEFINES = @DEFINES@
DEFINES_FOR_BUILD = @DEFINES_FOR_BUILD@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
DLLTOOL = @DLLTOOL@
DLOPEN_LIBS = @DLOPEN_LIBS@
DRI2PROTO_CFLAGS = @DRI2PROTO_CFLAGS@
DRI2PROTO_LIBS = @DRI2PROTO_LIBS@
DRIGL_CFLAGS = @DRIGL_CFLAGS@
DRIGL_LIBS = @DRIGL_LIBS@
DRI_DRIVER_INSTALL_DIR = @DRI_DRIVER_INSTALL_DIR@
DRI_DRIVER_SEARCH_DIR = @DRI_DRIVER_SEARCH_DIR@
DRI_LIB_DEPS = @DRI_LIB_DEPS@
DRI_PC_REQ_PRIV = @DRI_PC_REQ_PRIV@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGL_CFLAGS = @EGL_CFLAGS@
EGL_CLIENT_APIS = @EGL_CLIENT_APIS@
EGL_DRIVER_INSTALL_DIR = @EGL_DRIVER_INSTALL_DIR@
EGL_LIB_DEPS = @EGL_LIB_DEPS@
EGL_LIB_GLOB = @EGL_LIB_GLOB@
EGL_LIB_NAME = @EGL_LIB_NAME@
EGL_NATIVE_PLATFORM = @EGL_NATIVE_PLATFORM@
EGL_PLATFORMS = @EGL_PLATFORMS@
EGREP = @EGREP@
ELF_LIB = @ELF_LIB@
EXEEXT = @EXEEXT@
EXPAT_INCLUDES = @EXPAT_INCLUDES@
FGREP = @FGREP@
FREEDRENO_CFLAGS = @FREEDRENO_CFLAGS@
FREEDRENO_LIBS = @FREEDRENO_LIBS@
GALLIUM_DRI_LIB_DEPS = @GALLIUM_DRI_LIB_DEPS@
GALLIUM_PIPE_LOADER_DEFINES = @GALLIUM_PIPE_LOADER_DEFINES@
GALLIUM_PIPE_LOADER_LIBS = @GALLIUM_PIPE_LOADER_LIBS@
GALLIUM_PIPE_LOADER_XCB_CFLAGS = @GALLIUM_PIPE_LOADER_XCB_CFLAGS@
GALLIUM_PIPE_LOADER_XCB_LIBS = @GALLIUM_PIPE_LOADER_XCB_LIBS@
GBM_PC_LIB_PRIV = @GBM_PC_LIB_PRIV@
GBM_PC_REQ_PRIV = @GBM_PC_REQ_PRIV@
GLAPI_LIB_GLOB = @GLAPI_LIB_GLOB@
GLAPI_LIB_NAME = @GLAPI_LIB_NAME@
GLESv1_CM_LIB_DEPS = @GLESv1_CM_LIB_DEPS@
GLESv1_CM_LIB_GLOB = @GLESv1_CM_LIB_GLOB@
GLESv1_CM_LIB_NAME = @GLESv1_CM_LIB_NAME@
GLESv1_CM_PC_LIB_PRIV = @GLESv1_CM_PC_LIB_PRIV@
GLESv2_LIB_DEPS = @GLESv2_LIB_DEPS@
GLESv2_LIB_GLOB = @GLESv2_LIB_GLOB@
GLESv2_LIB_NAME = @GLESv2_LIB_NAME@
GLESv2_PC_LIB_PRIV = @GLESv2_PC_LIB_PRIV@
GLPROTO_CFLAGS = @GLPROTO_CFLAGS@
GLPROTO_LIBS = @GLPROTO_LIBS@
GLX_TLS = @GLX_TLS@
GL_LIB = @GL_LIB@
GL_LIB_DEPS = @GL_LIB_DEPS@
GL_LIB_GLOB = @GL_LIB_GLOB@
GL_LIB_NAME = @GL_LIB_NAME@
GL_PC_CFLAGS = @GL_PC_CFLAGS@
GL_PC_LIB_PRIV = @GL_PC_LIB_PRIV@
GL_PC_REQ_PRIV = @GL_PC_REQ_PRIV@
GREP = @GREP@
HAVE_XF86VIDMODE = @HAVE_XF86VIDMODE@
INDENT = @INDENT@
INDENT_FLAGS = @INDENT_FLAGS@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INTEL_CFLAGS = @INTEL_CFLAGS@
INTEL_LIBS = @INTEL_LIBS@
LD = @LD@
LDFLAGS = @LDFLAGS@
LDFLAGS_FOR_BUILD = @LDFLAGS_FOR_BUILD@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBCLC_INCLUDEDIR = @LIBCLC_INCLUDEDIR@
LIBCLC_LIBEXECDIR = @LIBCLC_LIBEXECDIR@
LIBDRM_CFLAGS = @LIBDRM_CFLAGS@
LIBDRM_LIBS = @LIBDRM_LIBS@
LIBDRM_XORG_CFLAGS = @LIBDRM_XORG_CFLAGS@
LIBDRM_XORG_LIBS = @LIBDRM_XORG_LIBS@
LIBKMS_XORG_CFLAGS = @LIBKMS_XORG_CFLAGS@
LIBKMS_XORG_LIBS = @LIBKMS_XORG_LIBS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIBUDEV_CFLAGS = @LIBUDEV_CFLAGS@
LIBUDEV_LIBS = @LIBUDEV_LIBS@
LIB_DIR = @LIB_DIR@
LIPO = @LIPO@
LLVM_BINDIR = @LLVM_BINDIR@
LLVM_CFLAGS = @LLVM_CFLAGS@
LLVM_CONFIG = @LLVM_CONFIG@
LLVM_CPPFLAGS = @LLVM_CPPFLAGS@
LLVM_CXXFLAGS = @LLVM_CXXFLAGS@
LLVM_INCLUDEDIR = @LLVM_INCLUDEDIR@
LLVM_LDFLAGS = @LLVM_LDFLAGS@
LLVM_LIBDIR = @LLVM_LIBDIR@
LLVM_LIBS = @LLVM_LIBS@
LLVM_VERSION = @LLVM_VERSION@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKE = @MAKE@
MAKEINFO = @MAKEINFO@
MANIFEST_TOOL = @MANIFEST_TOOL@
MESA_LLVM = @MESA_LLVM@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
NOUVEAU_CFLAGS = @NOUVEAU_CFLAGS@
NOUVEAU_LIBS = @NOUVEAU_LIBS@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OPENCL_LIB_INSTALL_DIR = @OPENCL_LIB_INSTALL_DIR@
OSMESA_LIB = @OSMESA_LIB@
OSMESA_LIB_DEPS = @OSMESA_LIB_DEPS@
OSMESA_LIB_NAME = @OSMESA_LIB_NAME@
OSMESA_MESA_DEPS = @OSMESA_MESA_DEPS@
OSMESA_PC_LIB_PRIV = @OSMESA_PC_LIB_PRIV@
OSMESA_PC_REQ = @OSMESA_PC_REQ@
OSMESA_VERSION = @OSMESA_VERSION@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PERL = @PERL@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
POSIX_SHELL = @POSIX_SHELL@
PTHREAD_CC = @PTHREAD_CC@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
PTHREAD_LIBS = @PTHREAD_LIBS@
PYTHON2 = @PYTHON2@
RADEON_CFLAGS = @RADEON_CFLAGS@
RADEON_LIBS = @RADEON_LIBS@
RANLIB = @RANLIB@
SED = @SED@
SELINUX_LIBS = @SELINUX_LIBS@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VDPAU_CFLAGS = @VDPAU_CFLAGS@
VDPAU_LIBS = @VDPAU_LIBS@
VDPAU_LIB_INSTALL_DIR = @VDPAU_LIB_INSTALL_DIR@
VDPAU_MAJOR = @VDPAU_MAJOR@
VDPAU_MINOR = @VDPAU_MINOR@
VERSION = @VERSION@
VG_LIB_DEPS = @VG_LIB_DEPS@
VG_LIB_GLOB = @VG_LIB_GLOB@
VG_LIB_NAME = @VG_LIB_NAME@
VG_PC_LIB_PRIV = @VG_PC_LIB_PRIV@
VISIBILITY_CFLAGS = @VISIBILITY_CFLAGS@
VISIBILITY_CXXFLAGS = @VISIBILITY_CXXFLAGS@
WAYLAND_CFLAGS = @WAYLAND_CFLAGS@
WAYLAND_LIBS = @WAYLAND_LIBS@
WAYLAND_SCANNER = @WAYLAND_SCANNER@
X11_INCLUDES = @X11_INCLUDES@
XA_MAJOR = @XA_MAJOR@
XA_MINOR = @XA_MINOR@
XA_TINY = @XA_TINY@
XA_VERSION = @XA_VERSION@
XCB_DRI2_CFLAGS = @XCB_DRI2_CFLAGS@
XCB_DRI2_LIBS = @XCB_DRI2_LIBS@
XEXT_CFLAGS = @XEXT_CFLAGS@
XEXT_LIBS = @XEXT_LIBS@
XF86VIDMODE_CFLAGS = @XF86VIDMODE_CFLAGS@
XF86VIDMODE_LIBS = @XF86VIDMODE_LIBS@
XLIBGL_CFLAGS = @XLIBGL_CFLAGS@
XLIBGL_LIBS = @XLIBGL_LIBS@
XORG_CFLAGS = @XORG_CFLAGS@
XORG_DRIVER_INSTALL_DIR = @XORG_DRIVER_INSTALL_DIR@
XORG_LIBS = @XORG_LIBS@
XVMC_CFLAGS = @XVMC_CFLAGS@
XVMC_LIBS = @XVMC_LIBS@
XVMC_LIB_INSTALL_DIR = @XVMC_LIB_INSTALL_DIR@
XVMC_MAJOR = @XVMC_MAJOR@
XVMC_MINOR = @XVMC_MINOR@
YACC = @YACC@
YFLAGS = @YFLAGS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CC_FOR_BUILD = @ac_ct_CC_FOR_BUILD@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_CXX_FOR_BUILD = @ac_ct_CXX_FOR_BUILD@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__tar = @am__tar@
am__untar = @am__untar@
ax_pthread_config = @ax_pthread_config@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
GALLIUM_CFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/src/gallium/include \
-I$(top_srcdir)/src/gallium/auxiliary \
$(DEFINES)
 
AM_CPPFLAGS = \
-I$(top_srcdir)/src/gallium/drivers \
-I$(top_srcdir)/include \
$(GALLIUM_CFLAGS)
 
noinst_LTLIBRARIES = libsoftpipe.la
libsoftpipe_la_SOURCES = \
sp_fs_exec.c \
sp_clear.c \
sp_fence.c \
sp_flush.c \
sp_query.c \
sp_context.c \
sp_draw_arrays.c \
sp_prim_vbuf.c \
sp_quad_pipe.c \
sp_quad_stipple.c \
sp_quad_depth_test.c \
sp_quad_fs.c \
sp_quad_blend.c \
sp_screen.c \
sp_setup.c \
sp_state_blend.c \
sp_state_clip.c \
sp_state_derived.c \
sp_state_sampler.c \
sp_state_shader.c \
sp_state_so.c \
sp_state_rasterizer.c \
sp_state_surface.c \
sp_state_vertex.c \
sp_texture.c \
sp_tex_sample.c \
sp_tex_tile_cache.c \
sp_tile_cache.c \
sp_surface.c
 
all: all-am
 
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(top_srcdir)/src/gallium/Automake.inc $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign src/gallium/drivers/softpipe/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign src/gallium/drivers/softpipe/Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
esac;
$(top_srcdir)/src/gallium/Automake.inc:
 
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
 
$(top_srcdir)/configure: $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
 
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; \
locs=`for p in $$list; do echo $$p; done | \
sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \
sort -u`; \
test -z "$$locs" || { \
echo rm -f $${locs}; \
rm -f $${locs}; \
}
 
libsoftpipe.la: $(libsoftpipe_la_OBJECTS) $(libsoftpipe_la_DEPENDENCIES) $(EXTRA_libsoftpipe_la_DEPENDENCIES)
$(AM_V_CCLD)$(LINK) $(libsoftpipe_la_OBJECTS) $(libsoftpipe_la_LIBADD) $(LIBS)
 
mostlyclean-compile:
-rm -f *.$(OBJEXT)
 
distclean-compile:
-rm -f *.tab.c
 
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_clear.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_context.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_draw_arrays.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_fence.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_flush.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_fs_exec.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_prim_vbuf.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_quad_blend.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_quad_depth_test.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_quad_fs.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_quad_pipe.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_quad_stipple.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_query.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_screen.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_setup.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_state_blend.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_state_clip.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_state_derived.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_state_rasterizer.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_state_sampler.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_state_shader.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_state_so.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_state_surface.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_state_vertex.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_surface.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_tex_sample.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_tex_tile_cache.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_texture.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sp_tile_cache.Plo@am__quote@
 
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
 
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
 
.c.lo:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
 
mostlyclean-libtool:
-rm -f *.lo
 
clean-libtool:
-rm -rf .libs _libs
 
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
 
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
 
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
 
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
 
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
 
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
 
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
 
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
 
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
 
clean-generic:
 
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
 
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
 
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
mostlyclean-am
 
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
 
dvi: dvi-am
 
dvi-am:
 
html: html-am
 
html-am:
 
info: info-am
 
info-am:
 
install-data-am:
 
install-dvi: install-dvi-am
 
install-dvi-am:
 
install-exec-am:
 
install-html: install-html-am
 
install-html-am:
 
install-info: install-info-am
 
install-info-am:
 
install-man:
 
install-pdf: install-pdf-am
 
install-pdf-am:
 
install-ps: install-ps-am
 
install-ps-am:
 
installcheck-am:
 
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
 
mostlyclean: mostlyclean-am
 
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
 
pdf: pdf-am
 
pdf-am:
 
ps: ps-am
 
ps-am:
 
uninstall-am:
 
.MAKE: install-am install-strip
 
.PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLTLIBRARIES cscopelist-am ctags \
ctags-am distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am html \
html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-pdf install-pdf-am \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
tags tags-am uninstall uninstall-am
 
 
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/SConscript
0,0 → 1,41
Import('*')
 
env = env.Clone()
 
softpipe = env.ConvenienceLibrary(
target = 'softpipe',
source = [
'sp_fs_exec.c',
'sp_clear.c',
'sp_context.c',
'sp_draw_arrays.c',
'sp_fence.c',
'sp_flush.c',
'sp_prim_vbuf.c',
'sp_setup.c',
'sp_quad_blend.c',
'sp_quad_pipe.c',
'sp_quad_depth_test.c',
'sp_quad_fs.c',
'sp_quad_stipple.c',
'sp_query.c',
'sp_screen.c',
'sp_state_blend.c',
'sp_state_clip.c',
'sp_state_derived.c',
'sp_state_rasterizer.c',
'sp_state_sampler.c',
'sp_state_shader.c',
'sp_state_so.c',
'sp_state_surface.c',
'sp_state_vertex.c',
'sp_surface.c',
'sp_tex_sample.c',
'sp_tex_tile_cache.c',
'sp_texture.c',
'sp_tile_cache.c',
])
 
env.Alias('softpipe', softpipe)
 
Export('softpipe')
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_clear.c
0,0 → 1,90
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2009 VMware, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Author:
* Brian Paul
* Michel Dänzer
*/
 
 
#include "pipe/p_defines.h"
#include "util/u_pack_color.h"
#include "util/u_surface.h"
#include "sp_clear.h"
#include "sp_context.h"
#include "sp_query.h"
#include "sp_tile_cache.h"
 
 
/**
* Clear the given buffers to the specified values.
* No masking, no scissor (clear entire buffer).
*/
void
softpipe_clear(struct pipe_context *pipe, unsigned buffers,
const union pipe_color_union *color,
double depth, unsigned stencil)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct pipe_surface *zsbuf = softpipe->framebuffer.zsbuf;
unsigned zs_buffers = buffers & PIPE_CLEAR_DEPTHSTENCIL;
uint64_t cv;
uint i;
 
if (softpipe->no_rast)
return;
 
if (!softpipe_check_render_cond(softpipe))
return;
 
#if 0
softpipe_update_derived(softpipe, PIPE_PRIM_TRIANGLES); /* not needed?? */
#endif
 
if (buffers & PIPE_CLEAR_COLOR) {
for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {
sp_tile_cache_clear(softpipe->cbuf_cache[i], color, 0);
}
}
 
if (zs_buffers &&
util_format_is_depth_and_stencil(zsbuf->texture->format) &&
zs_buffers != PIPE_CLEAR_DEPTHSTENCIL) {
/* Clearing only depth or stencil in a combined depth-stencil buffer. */
util_clear_depth_stencil(pipe, zsbuf, zs_buffers, depth, stencil,
0, 0, zsbuf->width, zsbuf->height);
}
else if (zs_buffers) {
static const union pipe_color_union zero;
 
cv = util_pack64_z_stencil(zsbuf->format, depth, stencil);
sp_tile_cache_clear(softpipe->zsbuf_cache, &zero, cv);
}
 
softpipe->dirty_render_cache = TRUE;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_clear.h
0,0 → 1,43
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Author:
* Brian Paul
*/
 
#ifndef SP_CLEAR_H
#define SP_CLEAR_H
 
struct pipe_context;
 
extern void
softpipe_clear(struct pipe_context *pipe, unsigned buffers,
const union pipe_color_union *color,
double depth, unsigned stencil);
 
 
#endif /* SP_CLEAR_H */
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_context.c
0,0 → 1,325
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2008 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Author:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_pstipple.h"
#include "util/u_inlines.h"
#include "tgsi/tgsi_exec.h"
#include "vl/vl_decoder.h"
#include "vl/vl_video_buffer.h"
#include "sp_clear.h"
#include "sp_context.h"
#include "sp_flush.h"
#include "sp_prim_vbuf.h"
#include "sp_state.h"
#include "sp_surface.h"
#include "sp_tile_cache.h"
#include "sp_tex_tile_cache.h"
#include "sp_texture.h"
#include "sp_query.h"
#include "sp_screen.h"
#include "sp_tex_sample.h"
 
 
static void
softpipe_destroy( struct pipe_context *pipe )
{
struct softpipe_context *softpipe = softpipe_context( pipe );
uint i, sh;
 
#if DO_PSTIPPLE_IN_HELPER_MODULE
if (softpipe->pstipple.sampler)
pipe->delete_sampler_state(pipe, softpipe->pstipple.sampler);
 
pipe_resource_reference(&softpipe->pstipple.texture, NULL);
pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, NULL);
#endif
 
if (softpipe->blitter) {
util_blitter_destroy(softpipe->blitter);
}
 
if (softpipe->draw)
draw_destroy( softpipe->draw );
 
if (softpipe->quad.shade)
softpipe->quad.shade->destroy( softpipe->quad.shade );
 
if (softpipe->quad.depth_test)
softpipe->quad.depth_test->destroy( softpipe->quad.depth_test );
 
if (softpipe->quad.blend)
softpipe->quad.blend->destroy( softpipe->quad.blend );
 
if (softpipe->quad.pstipple)
softpipe->quad.pstipple->destroy( softpipe->quad.pstipple );
 
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
sp_destroy_tile_cache(softpipe->cbuf_cache[i]);
pipe_surface_reference(&softpipe->framebuffer.cbufs[i], NULL);
}
 
sp_destroy_tile_cache(softpipe->zsbuf_cache);
pipe_surface_reference(&softpipe->framebuffer.zsbuf, NULL);
 
for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
for (i = 0; i < Elements(softpipe->tex_cache[0]); i++) {
sp_destroy_tex_tile_cache(softpipe->tex_cache[sh][i]);
pipe_sampler_view_reference(&softpipe->sampler_views[sh][i], NULL);
}
}
 
for (sh = 0; sh < Elements(softpipe->constants); sh++) {
for (i = 0; i < Elements(softpipe->constants[0]); i++) {
if (softpipe->constants[sh][i]) {
pipe_resource_reference(&softpipe->constants[sh][i], NULL);
}
}
}
 
for (i = 0; i < softpipe->num_vertex_buffers; i++) {
pipe_resource_reference(&softpipe->vertex_buffer[i].buffer, NULL);
}
 
tgsi_exec_machine_destroy(softpipe->fs_machine);
 
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
FREE(softpipe->tgsi.sampler[i]);
}
 
FREE( softpipe );
}
 
 
/**
* if (the texture is being used as a framebuffer surface)
* return SP_REFERENCED_FOR_WRITE
* else if (the texture is a bound texture source)
* return SP_REFERENCED_FOR_READ
* else
* return SP_UNREFERENCED
*/
unsigned int
softpipe_is_resource_referenced( struct pipe_context *pipe,
struct pipe_resource *texture,
unsigned level, int layer)
{
struct softpipe_context *softpipe = softpipe_context( pipe );
unsigned i, sh;
 
if (texture->target == PIPE_BUFFER)
return SP_UNREFERENCED;
 
/* check if any of the bound drawing surfaces are this texture */
if (softpipe->dirty_render_cache) {
for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {
if (softpipe->framebuffer.cbufs[i] &&
softpipe->framebuffer.cbufs[i]->texture == texture) {
return SP_REFERENCED_FOR_WRITE;
}
}
if (softpipe->framebuffer.zsbuf &&
softpipe->framebuffer.zsbuf->texture == texture) {
return SP_REFERENCED_FOR_WRITE;
}
}
/* check if any of the tex_cache textures are this texture */
for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
for (i = 0; i < Elements(softpipe->tex_cache[0]); i++) {
if (softpipe->tex_cache[sh][i] &&
softpipe->tex_cache[sh][i]->texture == texture)
return SP_REFERENCED_FOR_READ;
}
}
 
return SP_UNREFERENCED;
}
 
 
 
 
static void
softpipe_render_condition( struct pipe_context *pipe,
struct pipe_query *query,
boolean condition,
uint mode )
{
struct softpipe_context *softpipe = softpipe_context( pipe );
 
softpipe->render_cond_query = query;
softpipe->render_cond_mode = mode;
softpipe->render_cond_cond = condition;
}
 
 
 
struct pipe_context *
softpipe_create_context( struct pipe_screen *screen,
void *priv )
{
struct softpipe_screen *sp_screen = softpipe_screen(screen);
struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context);
uint i, sh;
 
util_init_math();
 
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
softpipe->tgsi.sampler[i] = sp_create_tgsi_sampler();
}
 
softpipe->dump_fs = debug_get_bool_option( "SOFTPIPE_DUMP_FS", FALSE );
softpipe->dump_gs = debug_get_bool_option( "SOFTPIPE_DUMP_GS", FALSE );
 
softpipe->pipe.screen = screen;
softpipe->pipe.destroy = softpipe_destroy;
softpipe->pipe.priv = priv;
 
/* state setters */
softpipe_init_blend_funcs(&softpipe->pipe);
softpipe_init_clip_funcs(&softpipe->pipe);
softpipe_init_query_funcs( softpipe );
softpipe_init_rasterizer_funcs(&softpipe->pipe);
softpipe_init_sampler_funcs(&softpipe->pipe);
softpipe_init_shader_funcs(&softpipe->pipe);
softpipe_init_streamout_funcs(&softpipe->pipe);
softpipe_init_texture_funcs( &softpipe->pipe );
softpipe_init_vertex_funcs(&softpipe->pipe);
 
softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state;
 
softpipe->pipe.draw_vbo = softpipe_draw_vbo;
 
softpipe->pipe.clear = softpipe_clear;
softpipe->pipe.flush = softpipe_flush_wrapped;
 
softpipe->pipe.render_condition = softpipe_render_condition;
softpipe->pipe.create_video_decoder = vl_create_decoder;
softpipe->pipe.create_video_buffer = vl_video_buffer_create;
 
/*
* Alloc caches for accessing drawing surfaces and textures.
* Must be before quad stage setup!
*/
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
softpipe->cbuf_cache[i] = sp_create_tile_cache( &softpipe->pipe );
softpipe->zsbuf_cache = sp_create_tile_cache( &softpipe->pipe );
 
/* Allocate texture caches */
for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
for (i = 0; i < Elements(softpipe->tex_cache[0]); i++) {
softpipe->tex_cache[sh][i] = sp_create_tex_tile_cache(&softpipe->pipe);
if (!softpipe->tex_cache[sh][i])
goto fail;
}
}
 
softpipe->fs_machine = tgsi_exec_machine_create();
 
/* setup quad rendering stages */
softpipe->quad.shade = sp_quad_shade_stage(softpipe);
softpipe->quad.depth_test = sp_quad_depth_test_stage(softpipe);
softpipe->quad.blend = sp_quad_blend_stage(softpipe);
softpipe->quad.pstipple = sp_quad_polygon_stipple_stage(softpipe);
 
 
/*
* Create drawing context and plug our rendering stage into it.
*/
if (sp_screen->use_llvm)
softpipe->draw = draw_create(&softpipe->pipe);
else
softpipe->draw = draw_create_no_llvm(&softpipe->pipe);
if (!softpipe->draw)
goto fail;
 
draw_texture_sampler(softpipe->draw,
PIPE_SHADER_VERTEX,
(struct tgsi_sampler *)
softpipe->tgsi.sampler[PIPE_SHADER_VERTEX]);
 
draw_texture_sampler(softpipe->draw,
PIPE_SHADER_GEOMETRY,
(struct tgsi_sampler *)
softpipe->tgsi.sampler[PIPE_SHADER_GEOMETRY]);
 
if (debug_get_bool_option( "SOFTPIPE_NO_RAST", FALSE ))
softpipe->no_rast = TRUE;
 
softpipe->vbuf_backend = sp_create_vbuf_backend(softpipe);
if (!softpipe->vbuf_backend)
goto fail;
 
softpipe->vbuf = draw_vbuf_stage(softpipe->draw, softpipe->vbuf_backend);
if (!softpipe->vbuf)
goto fail;
 
draw_set_rasterize_stage(softpipe->draw, softpipe->vbuf);
draw_set_render(softpipe->draw, softpipe->vbuf_backend);
 
softpipe->blitter = util_blitter_create(&softpipe->pipe);
if (!softpipe->blitter) {
goto fail;
}
 
/* must be done before installing Draw stages */
util_blitter_cache_all_shaders(softpipe->blitter);
 
/* plug in AA line/point stages */
draw_install_aaline_stage(softpipe->draw, &softpipe->pipe);
draw_install_aapoint_stage(softpipe->draw, &softpipe->pipe);
 
/* Do polygon stipple w/ texture map + frag prog? */
#if DO_PSTIPPLE_IN_DRAW_MODULE
draw_install_pstipple_stage(softpipe->draw, &softpipe->pipe);
#endif
 
draw_wide_point_sprites(softpipe->draw, TRUE);
 
sp_init_surface_functions(softpipe);
 
#if DO_PSTIPPLE_IN_HELPER_MODULE
/* create the polgon stipple sampler */
softpipe->pstipple.sampler = util_pstipple_create_sampler(&softpipe->pipe);
#endif
 
return &softpipe->pipe;
 
fail:
softpipe_destroy(&softpipe->pipe);
return NULL;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_context.h
0,0 → 1,227
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_CONTEXT_H
#define SP_CONTEXT_H
 
#include "pipe/p_context.h"
#include "util/u_blitter.h"
 
#include "draw/draw_vertex.h"
 
#include "sp_quad_pipe.h"
 
 
/** Do polygon stipple in the draw module? */
#define DO_PSTIPPLE_IN_DRAW_MODULE 0
 
/** Do polygon stipple with the util module? */
#define DO_PSTIPPLE_IN_HELPER_MODULE 1
 
 
struct softpipe_vbuf_render;
struct draw_context;
struct draw_stage;
struct softpipe_tile_cache;
struct softpipe_tex_tile_cache;
struct sp_fragment_shader;
struct sp_vertex_shader;
struct sp_velems_state;
struct sp_so_state;
 
struct softpipe_context {
struct pipe_context pipe; /**< base class */
 
/** Constant state objects */
struct pipe_blend_state *blend;
struct pipe_sampler_state *samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
struct pipe_depth_stencil_alpha_state *depth_stencil;
struct pipe_rasterizer_state *rasterizer;
struct sp_fragment_shader *fs;
struct sp_fragment_shader_variant *fs_variant;
struct sp_vertex_shader *vs;
struct sp_geometry_shader *gs;
struct sp_velems_state *velems;
struct sp_so_state *so;
 
/** Other rendering state */
struct pipe_blend_color blend_color;
struct pipe_blend_color blend_color_clamped;
struct pipe_stencil_ref stencil_ref;
struct pipe_clip_state clip;
struct pipe_resource *constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
 
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
struct pipe_index_buffer index_buffer;
 
struct draw_so_target *so_targets[PIPE_MAX_SO_BUFFERS];
unsigned num_so_targets;
struct pipe_query_data_so_statistics so_stats;
unsigned num_primitives_generated;
 
struct pipe_query_data_pipeline_statistics pipeline_statistics;
unsigned active_statistics_queries;
 
unsigned num_samplers[PIPE_SHADER_TYPES];
unsigned num_sampler_views[PIPE_SHADER_TYPES];
 
unsigned num_vertex_buffers;
 
unsigned dirty; /**< Mask of SP_NEW_x flags */
 
/* Counter for occlusion queries. Note this supports overlapping
* queries.
*/
uint64_t occlusion_count;
unsigned active_query_count;
 
/** Mapped vertex buffers */
ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS];
 
/** Mapped constant buffers */
const void *mapped_constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
unsigned const_buffer_size[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
 
/** Vertex format */
struct vertex_info vertex_info;
struct vertex_info vertex_info_vbuf;
 
/** Which vertex shader output slot contains point size */
int psize_slot;
 
/** The reduced version of the primitive supplied by the state tracker */
unsigned reduced_api_prim;
 
/** Derived information about which winding orders to cull */
unsigned cull_mode;
 
/**
* The reduced primitive after unfilled triangles, wide-line decomposition,
* etc, are taken into account. This is the primitive type that's actually
* rasterized.
*/
unsigned reduced_prim;
 
/** Derived from scissor and surface bounds: */
struct pipe_scissor_state cliprect;
 
unsigned line_stipple_counter;
 
/** Conditional query object and mode */
struct pipe_query *render_cond_query;
uint render_cond_mode;
boolean render_cond_cond;
 
/** Polygon stipple items */
struct {
struct pipe_resource *texture;
struct pipe_sampler_state *sampler;
struct pipe_sampler_view *sampler_view;
} pstipple;
 
/** Software quad rendering pipeline */
struct {
struct quad_stage *shade;
struct quad_stage *depth_test;
struct quad_stage *blend;
struct quad_stage *pstipple;
struct quad_stage *first; /**< points to one of the above stages */
} quad;
 
/** TGSI exec things */
struct {
struct sp_tgsi_sampler *sampler[PIPE_SHADER_TYPES];
} tgsi;
 
struct tgsi_exec_machine *fs_machine;
 
/** The primitive drawing context */
struct draw_context *draw;
 
/** Draw module backend */
struct vbuf_render *vbuf_backend;
struct draw_stage *vbuf;
 
struct blitter_context *blitter;
 
boolean dirty_render_cache;
 
struct softpipe_tile_cache *cbuf_cache[PIPE_MAX_COLOR_BUFS];
struct softpipe_tile_cache *zsbuf_cache;
 
unsigned tex_timestamp;
 
/*
* Texture caches for vertex, fragment, geometry stages.
* Don't use PIPE_SHADER_TYPES here to avoid allocating unused memory
* for compute shaders.
* XXX wouldn't it make more sense for the tile cache to just be part
* of sp_sampler_view?
*/
struct softpipe_tex_tile_cache *tex_cache[PIPE_SHADER_GEOMETRY+1][PIPE_MAX_SHADER_SAMPLER_VIEWS];
 
unsigned dump_fs : 1;
unsigned dump_gs : 1;
unsigned no_rast : 1;
};
 
 
static INLINE struct softpipe_context *
softpipe_context( struct pipe_context *pipe )
{
return (struct softpipe_context *)pipe;
}
 
 
struct pipe_context *
softpipe_create_context( struct pipe_screen *, void *priv );
 
struct pipe_resource *
softpipe_user_buffer_create(struct pipe_screen *screen,
void *ptr,
unsigned bytes,
unsigned bind_flags);
 
#define SP_UNREFERENCED 0
#define SP_REFERENCED_FOR_READ (1 << 0)
#define SP_REFERENCED_FOR_WRITE (1 << 1)
 
unsigned int
softpipe_is_resource_referenced( struct pipe_context *pipe,
struct pipe_resource *texture,
unsigned level, int layer);
 
#endif /* SP_CONTEXT_H */
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_draw_arrays.c
0,0 → 1,149
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Author:
* Brian Paul
* Keith Whitwell
*/
 
 
#include "pipe/p_defines.h"
#include "pipe/p_context.h"
#include "util/u_inlines.h"
#include "util/u_prim.h"
 
#include "sp_context.h"
#include "sp_query.h"
#include "sp_state.h"
#include "sp_texture.h"
 
#include "draw/draw_context.h"
 
/**
* This function handles drawing indexed and non-indexed prims,
* instanced and non-instanced drawing, with or without min/max element
* indexes.
* All the other drawing functions are expressed in terms of this
* function.
*
* For non-indexed prims, indexBuffer should be NULL.
* For non-instanced drawing, instanceCount should be 1.
* When the min/max element indexes aren't known, minIndex should be 0
* and maxIndex should be ~0.
*/
void
softpipe_draw_vbo(struct pipe_context *pipe,
const struct pipe_draw_info *info)
{
struct softpipe_context *sp = softpipe_context(pipe);
struct draw_context *draw = sp->draw;
const void *mapped_indices = NULL;
unsigned i;
 
if (!softpipe_check_render_cond(sp))
return;
 
sp->reduced_api_prim = u_reduced_prim(info->mode);
 
if (sp->dirty) {
softpipe_update_derived(sp, sp->reduced_api_prim);
}
 
/* Map vertex buffers */
for (i = 0; i < sp->num_vertex_buffers; i++) {
const void *buf = sp->vertex_buffer[i].user_buffer;
size_t size = ~0;
if (!buf) {
if (!sp->vertex_buffer[i].buffer) {
continue;
}
buf = softpipe_resource(sp->vertex_buffer[i].buffer)->data;
size = sp->vertex_buffer[i].buffer->width0;
}
draw_set_mapped_vertex_buffer(draw, i, buf, size);
}
 
/* Map index buffer, if present */
if (info->indexed) {
unsigned available_space = ~0;
mapped_indices = sp->index_buffer.user_buffer;
if (!mapped_indices) {
mapped_indices = softpipe_resource(sp->index_buffer.buffer)->data;
if (sp->index_buffer.buffer->width0 > sp->index_buffer.offset)
available_space =
(sp->index_buffer.buffer->width0 - sp->index_buffer.offset);
else
available_space = 0;
}
 
draw_set_indexes(draw,
(ubyte *) mapped_indices + sp->index_buffer.offset,
sp->index_buffer.index_size, available_space);
}
 
 
for (i = 0; i < sp->num_so_targets; i++) {
void *buf = softpipe_resource(sp->so_targets[i]->target.buffer)->data;
sp->so_targets[i]->mapping = buf;
}
 
draw_set_mapped_so_targets(draw, sp->num_so_targets,
sp->so_targets);
 
if (sp->gs && !sp->gs->shader.tokens) {
/* we have an empty geometry shader with stream output, so
attach the stream output info to the current vertex shader */
if (sp->vs) {
draw_vs_attach_so(sp->vs->draw_data, &sp->gs->shader.stream_output);
}
}
draw_collect_pipeline_statistics(draw,
sp->active_statistics_queries > 0);
 
/* draw! */
draw_vbo(draw, info);
 
/* unmap vertex/index buffers - will cause draw module to flush */
for (i = 0; i < sp->num_vertex_buffers; i++) {
draw_set_mapped_vertex_buffer(draw, i, NULL, 0);
}
if (mapped_indices) {
draw_set_indexes(draw, NULL, 0, 0);
}
 
draw_set_mapped_so_targets(draw, 0, NULL);
 
/*
* TODO: Flush only when a user vertex/index buffer is present
* (or even better, modify draw module to do this
* internally when this condition is seen?)
*/
draw_flush(draw);
 
/* Note: leave drawing surfaces mapped */
sp->dirty_render_cache = TRUE;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_fence.c
0,0 → 1,68
/**************************************************************************
*
* Copyright 2010 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
#include "pipe/p_screen.h"
#include "util/u_debug.h"
#include "sp_fence.h"
 
 
static void
softpipe_fence_reference(struct pipe_screen *screen,
struct pipe_fence_handle **ptr,
struct pipe_fence_handle *fence)
{
*ptr = fence;
}
 
 
static boolean
softpipe_fence_signalled(struct pipe_screen *screen,
struct pipe_fence_handle *fence)
{
assert(fence);
return TRUE;
}
 
 
static boolean
softpipe_fence_finish(struct pipe_screen *screen,
struct pipe_fence_handle *fence,
uint64_t timeout)
{
assert(fence);
return TRUE;
}
 
 
void
softpipe_init_screen_fence_funcs(struct pipe_screen *screen)
{
screen->fence_reference = softpipe_fence_reference;
screen->fence_finish = softpipe_fence_finish;
screen->fence_signalled = softpipe_fence_signalled;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_fence.h
0,0 → 1,40
/**************************************************************************
*
* Copyright 2010 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
#ifndef SP_FENCE_H_
#define SP_FENCE_H_
 
 
struct pipe_screen;
 
 
void
softpipe_init_screen_fence_funcs(struct pipe_screen *screen);
 
 
#endif /* SP_FENCE_H_ */
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_flush.c
0,0 → 1,169
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Author:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "draw/draw_context.h"
#include "sp_flush.h"
#include "sp_context.h"
#include "sp_state.h"
#include "sp_tile_cache.h"
#include "sp_tex_tile_cache.h"
#include "util/u_memory.h"
#include "util/u_string.h"
 
 
void
softpipe_flush( struct pipe_context *pipe,
unsigned flags,
struct pipe_fence_handle **fence )
{
struct softpipe_context *softpipe = softpipe_context(pipe);
uint i;
 
draw_flush(softpipe->draw);
 
if (flags & SP_FLUSH_TEXTURE_CACHE) {
unsigned sh;
 
for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
for (i = 0; i < softpipe->num_sampler_views[sh]; i++) {
sp_flush_tex_tile_cache(softpipe->tex_cache[sh][i]);
}
}
}
 
/* If this is a swapbuffers, just flush color buffers.
*
* The zbuffer changes are not discarded, but held in the cache
* in the hope that a later clear will wipe them out.
*/
for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++)
if (softpipe->cbuf_cache[i])
sp_flush_tile_cache(softpipe->cbuf_cache[i]);
 
if (softpipe->zsbuf_cache)
sp_flush_tile_cache(softpipe->zsbuf_cache);
 
softpipe->dirty_render_cache = FALSE;
 
/* Enable to dump BMPs of the color/depth buffers each frame */
#if 0
if (flags & PIPE_FLUSH_END_OF_FRAME) {
static unsigned frame_no = 1;
static char filename[256];
util_snprintf(filename, sizeof(filename), "cbuf_%u.bmp", frame_no);
debug_dump_surface_bmp(pipe, filename, softpipe->framebuffer.cbufs[0]);
util_snprintf(filename, sizeof(filename), "zsbuf_%u.bmp", frame_no);
debug_dump_surface_bmp(pipe, filename, softpipe->framebuffer.zsbuf);
++frame_no;
}
#endif
 
if (fence)
*fence = (void*)(intptr_t)1;
}
 
void
softpipe_flush_wrapped(struct pipe_context *pipe,
struct pipe_fence_handle **fence,
unsigned flags)
{
softpipe_flush(pipe, SP_FLUSH_TEXTURE_CACHE, fence);
}
 
 
/**
* Flush context if necessary.
*
* Returns FALSE if it would have block, but do_not_block was set, TRUE
* otherwise.
*
* TODO: move this logic to an auxiliary library?
*/
boolean
softpipe_flush_resource(struct pipe_context *pipe,
struct pipe_resource *texture,
unsigned level,
int layer,
unsigned flush_flags,
boolean read_only,
boolean cpu_access,
boolean do_not_block)
{
unsigned referenced;
 
referenced = softpipe_is_resource_referenced(pipe, texture, level, layer);
 
if ((referenced & SP_REFERENCED_FOR_WRITE) ||
((referenced & SP_REFERENCED_FOR_READ) && !read_only)) {
 
/*
* TODO: The semantics of these flush flags are too obtuse. They should
* disappear and the pipe driver should just ensure that all visible
* side-effects happen when they need to happen.
*/
if (referenced & SP_REFERENCED_FOR_READ)
flush_flags |= SP_FLUSH_TEXTURE_CACHE;
 
if (cpu_access) {
/*
* Flush and wait.
*/
 
struct pipe_fence_handle *fence = NULL;
 
if (do_not_block)
return FALSE;
 
softpipe_flush(pipe, flush_flags, &fence);
 
if (fence) {
/*
* This is for illustrative purposes only, as softpipe does not
* have fences.
*/
pipe->screen->fence_finish(pipe->screen, fence,
PIPE_TIMEOUT_INFINITE);
pipe->screen->fence_reference(pipe->screen, &fence, NULL);
}
} else {
/*
* Just flush.
*/
 
softpipe_flush(pipe, flush_flags, NULL);
}
}
 
return TRUE;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_flush.h
0,0 → 1,58
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef SP_FLUSH_H
#define SP_FLUSH_H
 
#include "pipe/p_compiler.h"
 
struct pipe_context;
struct pipe_fence_handle;
 
#define SP_FLUSH_TEXTURE_CACHE 0x2
 
void
softpipe_flush(struct pipe_context *pipe,
unsigned flags,
struct pipe_fence_handle **fence);
 
void
softpipe_flush_wrapped(struct pipe_context *pipe,
struct pipe_fence_handle **fence,
unsigned flags);
 
boolean
softpipe_flush_resource(struct pipe_context *pipe,
struct pipe_resource *texture,
unsigned level,
int layer,
unsigned flush_flags,
boolean read_only,
boolean cpu_access,
boolean do_not_block);
 
#endif
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_fs.h
0,0 → 1,48
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_FS_H
#define SP_FS_H
 
 
struct sp_fragment_shader_variant *
softpipe_create_fs_variant_exec(struct softpipe_context *softpipe,
const struct pipe_shader_state *templ);
 
 
struct tgsi_interp_coef;
struct tgsi_exec_vector;
 
void sp_setup_pos_vector(const struct tgsi_interp_coef *coef,
float x, float y,
struct tgsi_exec_vector *quadpos);
 
 
#endif
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_fs_exec.c
0,0 → 1,206
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/**
* Execute fragment shader using the TGSI interpreter.
*/
 
#include "sp_context.h"
#include "sp_state.h"
#include "sp_fs.h"
#include "sp_quad.h"
 
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_exec.h"
#include "tgsi/tgsi_parse.h"
 
 
/**
* Subclass of sp_fragment_shader_variant
*/
struct sp_exec_fragment_shader
{
struct sp_fragment_shader_variant base;
/* No other members for now */
};
 
 
/** cast wrapper */
static INLINE struct sp_exec_fragment_shader *
sp_exec_fragment_shader(const struct sp_fragment_shader_variant *var)
{
return (struct sp_exec_fragment_shader *) var;
}
 
 
static void
exec_prepare( const struct sp_fragment_shader_variant *var,
struct tgsi_exec_machine *machine,
struct tgsi_sampler *sampler )
{
/*
* Bind tokens/shader to the interpreter's machine state.
*/
tgsi_exec_machine_bind_shader(machine,
var->tokens,
sampler);
}
 
 
 
/**
* Compute quad X,Y,Z,W for the four fragments in a quad.
*
* This should really be part of the compiled shader.
*/
static void
setup_pos_vector(const struct tgsi_interp_coef *coef,
float x, float y,
struct tgsi_exec_vector *quadpos)
{
uint chan;
/* do X */
quadpos->xyzw[0].f[0] = x;
quadpos->xyzw[0].f[1] = x + 1;
quadpos->xyzw[0].f[2] = x;
quadpos->xyzw[0].f[3] = x + 1;
 
/* do Y */
quadpos->xyzw[1].f[0] = y;
quadpos->xyzw[1].f[1] = y;
quadpos->xyzw[1].f[2] = y + 1;
quadpos->xyzw[1].f[3] = y + 1;
 
/* do Z and W for all fragments in the quad */
for (chan = 2; chan < 4; chan++) {
const float dadx = coef->dadx[chan];
const float dady = coef->dady[chan];
const float a0 = coef->a0[chan] + dadx * x + dady * y;
quadpos->xyzw[chan].f[0] = a0;
quadpos->xyzw[chan].f[1] = a0 + dadx;
quadpos->xyzw[chan].f[2] = a0 + dady;
quadpos->xyzw[chan].f[3] = a0 + dadx + dady;
}
}
 
 
/* TODO: hide the machine struct in here somewhere, remove from this
* interface:
*/
static unsigned
exec_run( const struct sp_fragment_shader_variant *var,
struct tgsi_exec_machine *machine,
struct quad_header *quad )
{
/* Compute X, Y, Z, W vals for this quad */
setup_pos_vector(quad->posCoef,
(float)quad->input.x0, (float)quad->input.y0,
&machine->QuadPos);
 
/* convert 0 to 1.0 and 1 to -1.0 */
machine->Face = (float) (quad->input.facing * -2 + 1);
 
quad->inout.mask &= tgsi_exec_machine_run( machine );
if (quad->inout.mask == 0)
return FALSE;
 
/* store outputs */
{
const ubyte *sem_name = var->info.output_semantic_name;
const ubyte *sem_index = var->info.output_semantic_index;
const uint n = var->info.num_outputs;
uint i;
for (i = 0; i < n; i++) {
switch (sem_name[i]) {
case TGSI_SEMANTIC_COLOR:
{
uint cbuf = sem_index[i];
 
assert(sizeof(quad->output.color[cbuf]) ==
sizeof(machine->Outputs[i]));
 
/* copy float[4][4] result */
memcpy(quad->output.color[cbuf],
&machine->Outputs[i],
sizeof(quad->output.color[0]) );
}
break;
case TGSI_SEMANTIC_POSITION:
{
uint j;
 
for (j = 0; j < 4; j++)
quad->output.depth[j] = machine->Outputs[i].xyzw[2].f[j];
}
break;
case TGSI_SEMANTIC_STENCIL:
{
uint j;
 
for (j = 0; j < 4; j++)
quad->output.stencil[j] = (unsigned)machine->Outputs[i].xyzw[1].f[j];
}
break;
}
}
}
 
return TRUE;
}
 
 
static void
exec_delete(struct sp_fragment_shader_variant *var,
struct tgsi_exec_machine *machine)
{
if (machine->Tokens == var->tokens) {
tgsi_exec_machine_bind_shader(machine, NULL, NULL);
}
 
FREE( (void *) var->tokens );
FREE(var);
}
 
 
struct sp_fragment_shader_variant *
softpipe_create_fs_variant_exec(struct softpipe_context *softpipe,
const struct pipe_shader_state *templ)
{
struct sp_exec_fragment_shader *shader;
 
shader = CALLOC_STRUCT(sp_exec_fragment_shader);
if (!shader)
return NULL;
 
shader->base.prepare = exec_prepare;
shader->base.run = exec_run;
shader->base.delete = exec_delete;
 
return &shader->base;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_limits.h
0,0 → 1,43
/**************************************************************************
*
* Copyright 2010 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 THE AUTHORS 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 SP_LIMITS_H
#define SP_LIMITS_H
 
 
#define SP_MAX_TEXTURE_SIZE (1 * 1024 * 1024 * 1024ULL) /* 1GB for now */
#define SP_MAX_TEXTURE_2D_LEVELS 15 /* 16K x 16K */
#define SP_MAX_TEXTURE_3D_LEVELS 9 /* 256 x 256 x 256 */
#define SP_MAX_TEXTURE_CUBE_LEVELS 13 /* 4K x 4K */
 
 
/** Max surface size */
#define MAX_WIDTH (1 << (SP_MAX_TEXTURE_2D_LEVELS - 1))
#define MAX_HEIGHT (1 << (SP_MAX_TEXTURE_2D_LEVELS - 1))
 
 
#endif /* SP_LIMITS_H */
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_prim_vbuf.c
0,0 → 1,667
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/**
* Interface between 'draw' module's output and the softpipe rasterizer/setup
* code. When the 'draw' module has finished filling a vertex buffer, the
* draw_arrays() functions below will be called. Loop over the vertices and
* call the point/line/tri setup functions.
*
* Authors
* Brian Paul
*/
 
 
#include "sp_context.h"
#include "sp_setup.h"
#include "sp_state.h"
#include "sp_prim_vbuf.h"
#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
 
 
#define SP_MAX_VBUF_INDEXES 1024
#define SP_MAX_VBUF_SIZE 4096
 
typedef const float (*cptrf4)[4];
 
/**
* Subclass of vbuf_render.
*/
struct softpipe_vbuf_render
{
struct vbuf_render base;
struct softpipe_context *softpipe;
struct setup_context *setup;
 
uint prim;
uint vertex_size;
uint nr_vertices;
uint vertex_buffer_size;
void *vertex_buffer;
};
 
 
/** cast wrapper */
static struct softpipe_vbuf_render *
softpipe_vbuf_render(struct vbuf_render *vbr)
{
return (struct softpipe_vbuf_render *) vbr;
}
 
 
/** This tells the draw module about our desired vertex layout */
static const struct vertex_info *
sp_vbuf_get_vertex_info(struct vbuf_render *vbr)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
return softpipe_get_vbuf_vertex_info(cvbr->softpipe);
}
 
 
static boolean
sp_vbuf_allocate_vertices(struct vbuf_render *vbr,
ushort vertex_size, ushort nr_vertices)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
unsigned size = vertex_size * nr_vertices;
 
if (cvbr->vertex_buffer_size < size) {
align_free(cvbr->vertex_buffer);
cvbr->vertex_buffer = align_malloc(size, 16);
cvbr->vertex_buffer_size = size;
}
 
cvbr->vertex_size = vertex_size;
cvbr->nr_vertices = nr_vertices;
return cvbr->vertex_buffer != NULL;
}
 
 
static void
sp_vbuf_release_vertices(struct vbuf_render *vbr)
{
/* keep the old allocation for next time */
}
 
 
static void *
sp_vbuf_map_vertices(struct vbuf_render *vbr)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
return cvbr->vertex_buffer;
}
 
 
static void
sp_vbuf_unmap_vertices(struct vbuf_render *vbr,
ushort min_index,
ushort max_index )
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
assert( cvbr->vertex_buffer_size >= (max_index+1) * cvbr->vertex_size );
(void) cvbr;
/* do nothing */
}
 
 
static void
sp_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
struct setup_context *setup_ctx = cvbr->setup;
sp_setup_prepare( setup_ctx );
 
cvbr->softpipe->reduced_prim = u_reduced_prim(prim);
cvbr->prim = prim;
}
 
 
static INLINE cptrf4 get_vert( const void *vertex_buffer,
int index,
int stride )
{
return (cptrf4)((char *)vertex_buffer + index * stride);
}
 
 
/**
* draw elements / indexed primitives
*/
static void
sp_vbuf_draw_elements(struct vbuf_render *vbr, const ushort *indices, uint nr)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
struct softpipe_context *softpipe = cvbr->softpipe;
const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float);
const void *vertex_buffer = cvbr->vertex_buffer;
struct setup_context *setup = cvbr->setup;
const boolean flatshade_first = softpipe->rasterizer->flatshade_first;
unsigned i;
 
switch (cvbr->prim) {
case PIPE_PRIM_POINTS:
for (i = 0; i < nr; i++) {
sp_setup_point( setup,
get_vert(vertex_buffer, indices[i-0], stride) );
}
break;
 
case PIPE_PRIM_LINES:
for (i = 1; i < nr; i += 2) {
sp_setup_line( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
break;
 
case PIPE_PRIM_LINE_STRIP:
for (i = 1; i < nr; i ++) {
sp_setup_line( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
break;
 
case PIPE_PRIM_LINE_LOOP:
for (i = 1; i < nr; i ++) {
sp_setup_line( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
if (nr) {
sp_setup_line( setup,
get_vert(vertex_buffer, indices[nr-1], stride),
get_vert(vertex_buffer, indices[0], stride) );
}
break;
 
case PIPE_PRIM_TRIANGLES:
for (i = 2; i < nr; i += 3) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
break;
 
case PIPE_PRIM_TRIANGLE_STRIP:
if (flatshade_first) {
for (i = 2; i < nr; i += 1) {
/* emit first triangle vertex as first triangle vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i+(i&1)-1], stride),
get_vert(vertex_buffer, indices[i-(i&1)], stride) );
 
}
}
else {
for (i = 2; i < nr; i += 1) {
/* emit last triangle vertex as last triangle vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i+(i&1)-2], stride),
get_vert(vertex_buffer, indices[i-(i&1)-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
break;
 
case PIPE_PRIM_TRIANGLE_FAN:
if (flatshade_first) {
for (i = 2; i < nr; i += 1) {
/* emit first non-spoke vertex as first vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[0], stride) );
}
}
else {
for (i = 2; i < nr; i += 1) {
/* emit last non-spoke vertex as last vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[0], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
break;
 
case PIPE_PRIM_QUADS:
/* GL quads don't follow provoking vertex convention */
if (flatshade_first) {
/* emit last quad vertex as first triangle vertex */
for (i = 3; i < nr; i += 4) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[i-3], stride),
get_vert(vertex_buffer, indices[i-2], stride) );
 
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-1], stride) );
}
}
else {
/* emit last quad vertex as last triangle vertex */
for (i = 3; i < nr; i += 4) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-3], stride),
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
 
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
break;
 
case PIPE_PRIM_QUAD_STRIP:
/* GL quad strips don't follow provoking vertex convention */
if (flatshade_first) {
/* emit last quad vertex as first triangle vertex */
for (i = 3; i < nr; i += 2) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[i-3], stride),
get_vert(vertex_buffer, indices[i-2], stride) );
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-3], stride) );
}
}
else {
/* emit last quad vertex as last triangle vertex */
for (i = 3; i < nr; i += 2) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-3], stride),
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-3], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
break;
 
case PIPE_PRIM_POLYGON:
/* Almost same as tri fan but the _first_ vertex specifies the flat
* shading color.
*/
if (flatshade_first) {
/* emit first polygon vertex as first triangle vertex */
for (i = 2; i < nr; i += 1) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[0], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
else {
/* emit first polygon vertex as last triangle vertex */
for (i = 2; i < nr; i += 1) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[0], stride) );
}
}
break;
 
default:
assert(0);
}
}
 
 
/**
* This function is hit when the draw module is working in pass-through mode.
* It's up to us to convert the vertex array into point/line/tri prims.
*/
static void
sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
struct softpipe_context *softpipe = cvbr->softpipe;
struct setup_context *setup = cvbr->setup;
const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float);
const void *vertex_buffer =
(void *) get_vert(cvbr->vertex_buffer, start, stride);
const boolean flatshade_first = softpipe->rasterizer->flatshade_first;
unsigned i;
 
switch (cvbr->prim) {
case PIPE_PRIM_POINTS:
for (i = 0; i < nr; i++) {
sp_setup_point( setup,
get_vert(vertex_buffer, i-0, stride) );
}
break;
 
case PIPE_PRIM_LINES:
for (i = 1; i < nr; i += 2) {
sp_setup_line( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
break;
 
case PIPE_PRIM_LINES_ADJACENCY:
for (i = 3; i < nr; i += 4) {
sp_setup_line( setup,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-1, stride) );
}
break;
 
case PIPE_PRIM_LINE_STRIP:
for (i = 1; i < nr; i ++) {
sp_setup_line( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
break;
 
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
for (i = 3; i < nr; i++) {
sp_setup_line( setup,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-1, stride) );
}
break;
 
case PIPE_PRIM_LINE_LOOP:
for (i = 1; i < nr; i ++) {
sp_setup_line( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
if (nr) {
sp_setup_line( setup,
get_vert(vertex_buffer, nr-1, stride),
get_vert(vertex_buffer, 0, stride) );
}
break;
 
case PIPE_PRIM_TRIANGLES:
for (i = 2; i < nr; i += 3) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
break;
 
case PIPE_PRIM_TRIANGLES_ADJACENCY:
for (i = 5; i < nr; i += 6) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-5, stride),
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-1, stride) );
}
break;
 
case PIPE_PRIM_TRIANGLE_STRIP:
if (flatshade_first) {
for (i = 2; i < nr; i++) {
/* emit first triangle vertex as first triangle vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i+(i&1)-1, stride),
get_vert(vertex_buffer, i-(i&1), stride) );
}
}
else {
for (i = 2; i < nr; i++) {
/* emit last triangle vertex as last triangle vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, i+(i&1)-2, stride),
get_vert(vertex_buffer, i-(i&1)-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
break;
 
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
if (flatshade_first) {
for (i = 5; i < nr; i += 2) {
/* emit first triangle vertex as first triangle vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, i-5, stride),
get_vert(vertex_buffer, i+(i&1)*2-3, stride),
get_vert(vertex_buffer, i-(i&1)*2-1, stride) );
}
}
else {
for (i = 5; i < nr; i += 2) {
/* emit last triangle vertex as last triangle vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, i+(i&1)*2-5, stride),
get_vert(vertex_buffer, i-(i&1)*2-3, stride),
get_vert(vertex_buffer, i-1, stride) );
}
}
break;
 
case PIPE_PRIM_TRIANGLE_FAN:
if (flatshade_first) {
for (i = 2; i < nr; i += 1) {
/* emit first non-spoke vertex as first vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, 0, stride) );
}
}
else {
for (i = 2; i < nr; i += 1) {
/* emit last non-spoke vertex as last vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, 0, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
break;
 
case PIPE_PRIM_QUADS:
/* GL quads don't follow provoking vertex convention */
if (flatshade_first) {
/* emit last quad vertex as first triangle vertex */
for (i = 3; i < nr; i += 4) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-2, stride) );
sp_setup_tri( setup,
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-1, stride) );
}
}
else {
/* emit last quad vertex as last triangle vertex */
for (i = 3; i < nr; i += 4) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-0, stride) );
sp_setup_tri( setup,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
break;
 
case PIPE_PRIM_QUAD_STRIP:
/* GL quad strips don't follow provoking vertex convention */
if (flatshade_first) {
/* emit last quad vertex as first triangle vertex */
for (i = 3; i < nr; i += 2) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-2, stride) );
sp_setup_tri( setup,
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-3, stride) );
}
}
else {
/* emit last quad vertex as last triangle vertex */
for (i = 3; i < nr; i += 2) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-0, stride) );
sp_setup_tri( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
break;
 
case PIPE_PRIM_POLYGON:
/* Almost same as tri fan but the _first_ vertex specifies the flat
* shading color.
*/
if (flatshade_first) {
/* emit first polygon vertex as first triangle vertex */
for (i = 2; i < nr; i += 1) {
sp_setup_tri( setup,
get_vert(vertex_buffer, 0, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
else {
/* emit first polygon vertex as last triangle vertex */
for (i = 2; i < nr; i += 1) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, 0, stride) );
}
}
break;
 
default:
assert(0);
}
}
 
static void
sp_vbuf_so_info(struct vbuf_render *vbr, uint primitives, uint vertices,
uint prim_generated)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
struct softpipe_context *softpipe = cvbr->softpipe;
 
softpipe->so_stats.num_primitives_written += primitives;
softpipe->so_stats.primitives_storage_needed =
vertices * 4 /*sizeof(float|int32)*/ * 4 /*x,y,z,w*/;
softpipe->num_primitives_generated += prim_generated;
}
 
static void
sp_vbuf_pipeline_statistics(
struct vbuf_render *vbr,
const struct pipe_query_data_pipeline_statistics *stats)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
struct softpipe_context *softpipe = cvbr->softpipe;
 
softpipe->pipeline_statistics.ia_vertices +=
stats->ia_vertices;
softpipe->pipeline_statistics.ia_primitives +=
stats->ia_primitives;
softpipe->pipeline_statistics.vs_invocations +=
stats->vs_invocations;
softpipe->pipeline_statistics.gs_invocations +=
stats->gs_invocations;
softpipe->pipeline_statistics.gs_primitives +=
stats->gs_primitives;
softpipe->pipeline_statistics.c_invocations +=
stats->c_invocations;
}
 
 
static void
sp_vbuf_destroy(struct vbuf_render *vbr)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
if (cvbr->vertex_buffer)
align_free(cvbr->vertex_buffer);
sp_setup_destroy_context(cvbr->setup);
FREE(cvbr);
}
 
 
/**
* Create the post-transform vertex handler for the given context.
*/
struct vbuf_render *
sp_create_vbuf_backend(struct softpipe_context *sp)
{
struct softpipe_vbuf_render *cvbr = CALLOC_STRUCT(softpipe_vbuf_render);
 
assert(sp->draw);
 
cvbr->base.max_indices = SP_MAX_VBUF_INDEXES;
cvbr->base.max_vertex_buffer_bytes = SP_MAX_VBUF_SIZE;
 
cvbr->base.get_vertex_info = sp_vbuf_get_vertex_info;
cvbr->base.allocate_vertices = sp_vbuf_allocate_vertices;
cvbr->base.map_vertices = sp_vbuf_map_vertices;
cvbr->base.unmap_vertices = sp_vbuf_unmap_vertices;
cvbr->base.set_primitive = sp_vbuf_set_primitive;
cvbr->base.draw_elements = sp_vbuf_draw_elements;
cvbr->base.draw_arrays = sp_vbuf_draw_arrays;
cvbr->base.release_vertices = sp_vbuf_release_vertices;
cvbr->base.set_stream_output_info = sp_vbuf_so_info;
cvbr->base.pipeline_statistics = sp_vbuf_pipeline_statistics;
cvbr->base.destroy = sp_vbuf_destroy;
 
cvbr->softpipe = sp;
 
cvbr->setup = sp_setup_create_context(cvbr->softpipe);
 
return &cvbr->base;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_prim_vbuf.h
0,0 → 1,38
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef SP_VBUF_H
#define SP_VBUF_H
 
 
struct softpipe_context;
 
extern struct vbuf_render *
sp_create_vbuf_backend(struct softpipe_context *softpipe);
 
 
#endif /* SP_VBUF_H */
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_public.h
0,0 → 1,10
#ifndef SP_PUBLIC_H
#define SP_PUBLIC_H
 
struct pipe_screen;
struct sw_winsys;
 
struct pipe_screen *
softpipe_create_screen(struct sw_winsys *winsys);
 
#endif
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_quad.h
0,0 → 1,107
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_QUAD_H
#define SP_QUAD_H
 
#include "pipe/p_state.h"
#include "tgsi/tgsi_exec.h"
 
 
#define QUAD_PRIM_POINT 1
#define QUAD_PRIM_LINE 2
#define QUAD_PRIM_TRI 3
 
 
/* The rasterizer generates 2x2 quads of fragment and feeds them to
* the current fp_machine (see below).
* Remember that Y=0=top with Y increasing down the window.
*/
#define QUAD_TOP_LEFT 0
#define QUAD_TOP_RIGHT 1
#define QUAD_BOTTOM_LEFT 2
#define QUAD_BOTTOM_RIGHT 3
 
#define MASK_TOP_LEFT (1 << QUAD_TOP_LEFT)
#define MASK_TOP_RIGHT (1 << QUAD_TOP_RIGHT)
#define MASK_BOTTOM_LEFT (1 << QUAD_BOTTOM_LEFT)
#define MASK_BOTTOM_RIGHT (1 << QUAD_BOTTOM_RIGHT)
#define MASK_ALL 0xf
 
 
/**
* Quad stage inputs (pos, coverage, front/back face, etc)
*/
struct quad_header_input
{
int x0, y0; /**< quad window pos, always even */
float coverage[TGSI_QUAD_SIZE]; /**< fragment coverage for antialiasing */
unsigned facing:1; /**< Front (0) or back (1) facing? */
unsigned prim:2; /**< QUAD_PRIM_POINT, LINE, TRI */
};
 
 
/**
* Quad stage inputs/outputs.
*/
struct quad_header_inout
{
unsigned mask:4;
};
 
 
/**
* Quad stage outputs (color & depth).
*/
struct quad_header_output
{
/** colors in SOA format (rrrr, gggg, bbbb, aaaa) */
float color[PIPE_MAX_COLOR_BUFS][TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
float depth[TGSI_QUAD_SIZE];
uint8_t stencil[TGSI_QUAD_SIZE];
};
 
 
/**
* Encodes everything we need to know about a 2x2 pixel block. Uses
* "Channel-Serial" or "SoA" layout.
*/
struct quad_header {
struct quad_header_input input;
struct quad_header_inout inout;
struct quad_header_output output;
 
/* Redundant/duplicated:
*/
const struct tgsi_interp_coef *posCoef;
const struct tgsi_interp_coef *coef;
};
 
#endif /* SP_QUAD_H */
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_quad_blend.c
0,0 → 1,1306
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/**
* quad blending
* \author Brian Paul
*/
 
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_format.h"
#include "util/u_dual_blend.h"
#include "sp_context.h"
#include "sp_state.h"
#include "sp_quad.h"
#include "sp_tile_cache.h"
#include "sp_quad_pipe.h"
 
 
enum format
{
RGBA,
RGB,
LUMINANCE,
LUMINANCE_ALPHA,
INTENSITY
};
 
 
/** Subclass of quad_stage */
struct blend_quad_stage
{
struct quad_stage base;
boolean clamp[PIPE_MAX_COLOR_BUFS]; /**< clamp colors to [0,1]? */
enum format base_format[PIPE_MAX_COLOR_BUFS];
enum util_format_type format_type[PIPE_MAX_COLOR_BUFS];
};
 
 
/** cast wrapper */
static INLINE struct blend_quad_stage *
blend_quad_stage(struct quad_stage *stage)
{
return (struct blend_quad_stage *) stage;
}
 
 
#define VEC4_COPY(DST, SRC) \
do { \
DST[0] = SRC[0]; \
DST[1] = SRC[1]; \
DST[2] = SRC[2]; \
DST[3] = SRC[3]; \
} while(0)
 
#define VEC4_SCALAR(DST, SRC) \
do { \
DST[0] = SRC; \
DST[1] = SRC; \
DST[2] = SRC; \
DST[3] = SRC; \
} while(0)
 
#define VEC4_ADD(R, A, B) \
do { \
R[0] = A[0] + B[0]; \
R[1] = A[1] + B[1]; \
R[2] = A[2] + B[2]; \
R[3] = A[3] + B[3]; \
} while (0)
 
#define VEC4_SUB(R, A, B) \
do { \
R[0] = A[0] - B[0]; \
R[1] = A[1] - B[1]; \
R[2] = A[2] - B[2]; \
R[3] = A[3] - B[3]; \
} while (0)
 
/** Add and limit result to ceiling of 1.0 */
#define VEC4_ADD_SAT(R, A, B) \
do { \
R[0] = A[0] + B[0]; if (R[0] > 1.0f) R[0] = 1.0f; \
R[1] = A[1] + B[1]; if (R[1] > 1.0f) R[1] = 1.0f; \
R[2] = A[2] + B[2]; if (R[2] > 1.0f) R[2] = 1.0f; \
R[3] = A[3] + B[3]; if (R[3] > 1.0f) R[3] = 1.0f; \
} while (0)
 
/** Subtract and limit result to floor of 0.0 */
#define VEC4_SUB_SAT(R, A, B) \
do { \
R[0] = A[0] - B[0]; if (R[0] < 0.0f) R[0] = 0.0f; \
R[1] = A[1] - B[1]; if (R[1] < 0.0f) R[1] = 0.0f; \
R[2] = A[2] - B[2]; if (R[2] < 0.0f) R[2] = 0.0f; \
R[3] = A[3] - B[3]; if (R[3] < 0.0f) R[3] = 0.0f; \
} while (0)
 
#define VEC4_MUL(R, A, B) \
do { \
R[0] = A[0] * B[0]; \
R[1] = A[1] * B[1]; \
R[2] = A[2] * B[2]; \
R[3] = A[3] * B[3]; \
} while (0)
 
#define VEC4_MIN(R, A, B) \
do { \
R[0] = (A[0] < B[0]) ? A[0] : B[0]; \
R[1] = (A[1] < B[1]) ? A[1] : B[1]; \
R[2] = (A[2] < B[2]) ? A[2] : B[2]; \
R[3] = (A[3] < B[3]) ? A[3] : B[3]; \
} while (0)
 
#define VEC4_MAX(R, A, B) \
do { \
R[0] = (A[0] > B[0]) ? A[0] : B[0]; \
R[1] = (A[1] > B[1]) ? A[1] : B[1]; \
R[2] = (A[2] > B[2]) ? A[2] : B[2]; \
R[3] = (A[3] > B[3]) ? A[3] : B[3]; \
} while (0)
 
 
 
static void
logicop_quad(struct quad_stage *qs,
float (*quadColor)[4],
float (*dest)[4])
{
struct softpipe_context *softpipe = qs->softpipe;
ubyte src[4][4], dst[4][4], res[4][4];
uint *src4 = (uint *) src;
uint *dst4 = (uint *) dst;
uint *res4 = (uint *) res;
uint j;
 
 
/* convert to ubyte */
for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */
dst[j][0] = float_to_ubyte(dest[j][0]); /* P0 */
dst[j][1] = float_to_ubyte(dest[j][1]); /* P1 */
dst[j][2] = float_to_ubyte(dest[j][2]); /* P2 */
dst[j][3] = float_to_ubyte(dest[j][3]); /* P3 */
 
src[j][0] = float_to_ubyte(quadColor[j][0]); /* P0 */
src[j][1] = float_to_ubyte(quadColor[j][1]); /* P1 */
src[j][2] = float_to_ubyte(quadColor[j][2]); /* P2 */
src[j][3] = float_to_ubyte(quadColor[j][3]); /* P3 */
}
 
switch (softpipe->blend->logicop_func) {
case PIPE_LOGICOP_CLEAR:
for (j = 0; j < 4; j++)
res4[j] = 0;
break;
case PIPE_LOGICOP_NOR:
for (j = 0; j < 4; j++)
res4[j] = ~(src4[j] | dst4[j]);
break;
case PIPE_LOGICOP_AND_INVERTED:
for (j = 0; j < 4; j++)
res4[j] = ~src4[j] & dst4[j];
break;
case PIPE_LOGICOP_COPY_INVERTED:
for (j = 0; j < 4; j++)
res4[j] = ~src4[j];
break;
case PIPE_LOGICOP_AND_REVERSE:
for (j = 0; j < 4; j++)
res4[j] = src4[j] & ~dst4[j];
break;
case PIPE_LOGICOP_INVERT:
for (j = 0; j < 4; j++)
res4[j] = ~dst4[j];
break;
case PIPE_LOGICOP_XOR:
for (j = 0; j < 4; j++)
res4[j] = dst4[j] ^ src4[j];
break;
case PIPE_LOGICOP_NAND:
for (j = 0; j < 4; j++)
res4[j] = ~(src4[j] & dst4[j]);
break;
case PIPE_LOGICOP_AND:
for (j = 0; j < 4; j++)
res4[j] = src4[j] & dst4[j];
break;
case PIPE_LOGICOP_EQUIV:
for (j = 0; j < 4; j++)
res4[j] = ~(src4[j] ^ dst4[j]);
break;
case PIPE_LOGICOP_NOOP:
for (j = 0; j < 4; j++)
res4[j] = dst4[j];
break;
case PIPE_LOGICOP_OR_INVERTED:
for (j = 0; j < 4; j++)
res4[j] = ~src4[j] | dst4[j];
break;
case PIPE_LOGICOP_COPY:
for (j = 0; j < 4; j++)
res4[j] = src4[j];
break;
case PIPE_LOGICOP_OR_REVERSE:
for (j = 0; j < 4; j++)
res4[j] = src4[j] | ~dst4[j];
break;
case PIPE_LOGICOP_OR:
for (j = 0; j < 4; j++)
res4[j] = src4[j] | dst4[j];
break;
case PIPE_LOGICOP_SET:
for (j = 0; j < 4; j++)
res4[j] = ~0;
break;
default:
assert(0 && "invalid logicop mode");
}
 
for (j = 0; j < 4; j++) {
quadColor[j][0] = ubyte_to_float(res[j][0]);
quadColor[j][1] = ubyte_to_float(res[j][1]);
quadColor[j][2] = ubyte_to_float(res[j][2]);
quadColor[j][3] = ubyte_to_float(res[j][3]);
}
}
 
 
 
/**
* Do blending for a 2x2 quad for one color buffer.
* \param quadColor the incoming quad colors
* \param dest the destination/framebuffer quad colors
* \param const_blend_color the constant blend color
* \param blend_index which set of blending terms to use
*/
static void
blend_quad(struct quad_stage *qs,
float (*quadColor)[4],
float (*quadColor2)[4],
float (*dest)[4],
const float const_blend_color[4],
unsigned blend_index)
{
static const float zero[4] = { 0, 0, 0, 0 };
static const float one[4] = { 1, 1, 1, 1 };
struct softpipe_context *softpipe = qs->softpipe;
float source[4][TGSI_QUAD_SIZE] = { { 0 } };
float blend_dest[4][TGSI_QUAD_SIZE];
 
/*
* Compute src/first term RGB
*/
switch (softpipe->blend->rt[blend_index].rgb_src_factor) {
case PIPE_BLENDFACTOR_ONE:
VEC4_COPY(source[0], quadColor[0]); /* R */
VEC4_COPY(source[1], quadColor[1]); /* G */
VEC4_COPY(source[2], quadColor[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
VEC4_MUL(source[0], quadColor[0], quadColor[0]); /* R */
VEC4_MUL(source[1], quadColor[1], quadColor[1]); /* G */
VEC4_MUL(source[2], quadColor[2], quadColor[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
{
const float *alpha = quadColor[3];
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_DST_COLOR:
VEC4_MUL(source[0], quadColor[0], dest[0]); /* R */
VEC4_MUL(source[1], quadColor[1], dest[1]); /* G */
VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */
break;
case PIPE_BLENDFACTOR_DST_ALPHA:
{
const float *alpha = dest[3];
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
{
const float *alpha = quadColor[3];
float diff[4], temp[4];
VEC4_SUB(diff, one, dest[3]);
VEC4_MIN(temp, alpha, diff);
VEC4_MUL(source[0], quadColor[0], temp); /* R */
VEC4_MUL(source[1], quadColor[1], temp); /* G */
VEC4_MUL(source[2], quadColor[2], temp); /* B */
}
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
{
float comp[4];
VEC4_SCALAR(comp, const_blend_color[0]); /* R */
VEC4_MUL(source[0], quadColor[0], comp); /* R */
VEC4_SCALAR(comp, const_blend_color[1]); /* G */
VEC4_MUL(source[1], quadColor[1], comp); /* G */
VEC4_SCALAR(comp, const_blend_color[2]); /* B */
VEC4_MUL(source[2], quadColor[2], comp); /* B */
}
break;
case PIPE_BLENDFACTOR_CONST_ALPHA:
{
float alpha[4];
VEC4_SCALAR(alpha, const_blend_color[3]);
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_SRC1_COLOR:
VEC4_MUL(source[0], quadColor[0], quadColor2[0]); /* R */
VEC4_MUL(source[1], quadColor[1], quadColor2[1]); /* G */
VEC4_MUL(source[2], quadColor[2], quadColor2[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC1_ALPHA:
{
const float *alpha = quadColor2[3];
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_ZERO:
VEC4_COPY(source[0], zero); /* R */
VEC4_COPY(source[1], zero); /* G */
VEC4_COPY(source[2], zero); /* B */
break;
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, quadColor[3]);
VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, dest[3]);
VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, dest[0]); /* R */
VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
VEC4_SUB(inv_comp, one, dest[1]); /* G */
VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
VEC4_SUB(inv_comp, one, dest[2]); /* B */
VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
{
float inv_comp[4];
/* R */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[0]);
VEC4_MUL(source[0], quadColor[0], inv_comp);
/* G */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[1]);
VEC4_MUL(source[1], quadColor[1], inv_comp);
/* B */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[2]);
VEC4_MUL(source[2], quadColor[2], inv_comp);
}
break;
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
{
float inv_alpha[4];
VEC4_SCALAR(inv_alpha, 1.0f - const_blend_color[3]);
VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, quadColor2[0]); /* R */
VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
VEC4_SUB(inv_comp, one, quadColor2[1]); /* G */
VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
VEC4_SUB(inv_comp, one, quadColor2[2]); /* B */
VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, quadColor2[3]);
VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
}
break;
default:
assert(0 && "invalid rgb src factor");
}
 
/*
* Compute src/first term A
*/
switch (softpipe->blend->rt[blend_index].alpha_src_factor) {
case PIPE_BLENDFACTOR_ONE:
VEC4_COPY(source[3], quadColor[3]); /* A */
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_SRC_ALPHA:
{
const float *alpha = quadColor[3];
VEC4_MUL(source[3], quadColor[3], alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_DST_ALPHA:
VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
/* multiply alpha by 1.0 */
VEC4_COPY(source[3], quadColor[3]); /* A */
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_CONST_ALPHA:
{
float comp[4];
VEC4_SCALAR(comp, const_blend_color[3]); /* A */
VEC4_MUL(source[3], quadColor[3], comp); /* A */
}
break;
case PIPE_BLENDFACTOR_ZERO:
VEC4_COPY(source[3], zero); /* A */
break;
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, quadColor[3]);
VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, dest[3]);
VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
{
float inv_comp[4];
/* A */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]);
VEC4_MUL(source[3], quadColor[3], inv_comp);
}
break;
case PIPE_BLENDFACTOR_SRC1_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_SRC1_ALPHA:
{
const float *alpha = quadColor2[3];
VEC4_MUL(source[3], quadColor[3], alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, quadColor2[3]);
VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
}
break;
default:
assert(0 && "invalid alpha src factor");
}
 
/* Save the original dest for use in masking */
VEC4_COPY(blend_dest[0], dest[0]);
VEC4_COPY(blend_dest[1], dest[1]);
VEC4_COPY(blend_dest[2], dest[2]);
VEC4_COPY(blend_dest[3], dest[3]);
 
 
/*
* Compute blend_dest/second term RGB
*/
switch (softpipe->blend->rt[blend_index].rgb_dst_factor) {
case PIPE_BLENDFACTOR_ONE:
/* blend_dest = blend_dest * 1 NO-OP, leave blend_dest as-is */
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
VEC4_MUL(blend_dest[0], blend_dest[0], quadColor[0]); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], quadColor[1]); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], quadColor[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
VEC4_MUL(blend_dest[0], blend_dest[0], quadColor[3]); /* R * A */
VEC4_MUL(blend_dest[1], blend_dest[1], quadColor[3]); /* G * A */
VEC4_MUL(blend_dest[2], blend_dest[2], quadColor[3]); /* B * A */
break;
case PIPE_BLENDFACTOR_DST_ALPHA:
VEC4_MUL(blend_dest[0], blend_dest[0], blend_dest[3]); /* R * A */
VEC4_MUL(blend_dest[1], blend_dest[1], blend_dest[3]); /* G * A */
VEC4_MUL(blend_dest[2], blend_dest[2], blend_dest[3]); /* B * A */
break;
case PIPE_BLENDFACTOR_DST_COLOR:
VEC4_MUL(blend_dest[0], blend_dest[0], blend_dest[0]); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], blend_dest[1]); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], blend_dest[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
{
const float *alpha = quadColor[3];
float diff[4], temp[4];
VEC4_SUB(diff, one, blend_dest[3]);
VEC4_MIN(temp, alpha, diff);
VEC4_MUL(blend_dest[0], blend_dest[0], temp); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], temp); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], temp); /* B */
}
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
{
float comp[4];
VEC4_SCALAR(comp, const_blend_color[0]); /* R */
VEC4_MUL(blend_dest[0], blend_dest[0], comp); /* R */
VEC4_SCALAR(comp, const_blend_color[1]); /* G */
VEC4_MUL(blend_dest[1], blend_dest[1], comp); /* G */
VEC4_SCALAR(comp, const_blend_color[2]); /* B */
VEC4_MUL(blend_dest[2], blend_dest[2], comp); /* B */
}
break;
case PIPE_BLENDFACTOR_CONST_ALPHA:
{
float comp[4];
VEC4_SCALAR(comp, const_blend_color[3]); /* A */
VEC4_MUL(blend_dest[0], blend_dest[0], comp); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], comp); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], comp); /* B */
}
break;
case PIPE_BLENDFACTOR_ZERO:
VEC4_COPY(blend_dest[0], zero); /* R */
VEC4_COPY(blend_dest[1], zero); /* G */
VEC4_COPY(blend_dest[2], zero); /* B */
break;
case PIPE_BLENDFACTOR_SRC1_COLOR:
VEC4_MUL(blend_dest[0], blend_dest[0], quadColor2[0]); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], quadColor2[1]); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], quadColor2[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC1_ALPHA:
VEC4_MUL(blend_dest[0], blend_dest[0], quadColor2[3]); /* R * A */
VEC4_MUL(blend_dest[1], blend_dest[1], quadColor2[3]); /* G * A */
VEC4_MUL(blend_dest[2], blend_dest[2], quadColor2[3]); /* B * A */
break;
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
VEC4_MUL(blend_dest[0], inv_comp, blend_dest[0]); /* R */
VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
VEC4_MUL(blend_dest[1], inv_comp, blend_dest[1]); /* G */
VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
VEC4_MUL(blend_dest[2], inv_comp, blend_dest[2]); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
{
float one_minus_alpha[TGSI_QUAD_SIZE];
VEC4_SUB(one_minus_alpha, one, quadColor[3]);
VEC4_MUL(blend_dest[0], blend_dest[0], one_minus_alpha); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], one_minus_alpha); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], one_minus_alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, blend_dest[3]); /* A */
VEC4_MUL(blend_dest[0], inv_comp, blend_dest[0]); /* R */
VEC4_MUL(blend_dest[1], inv_comp, blend_dest[1]); /* G */
VEC4_MUL(blend_dest[2], inv_comp, blend_dest[2]); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, blend_dest[0]); /* R */
VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp); /* R */
VEC4_SUB(inv_comp, one, blend_dest[1]); /* G */
VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp); /* G */
VEC4_SUB(inv_comp, one, blend_dest[2]); /* B */
VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
{
float inv_comp[4];
/* R */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[0]);
VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp);
/* G */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[1]);
VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp);
/* B */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[2]);
VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp);
}
break;
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
{
float inv_comp[4];
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]);
VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp);
VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp);
VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp);
}
break;
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, quadColor2[0]); /* R */
VEC4_MUL(blend_dest[0], inv_comp, blend_dest[0]); /* R */
VEC4_SUB(inv_comp, one, quadColor2[1]); /* G */
VEC4_MUL(blend_dest[1], inv_comp, blend_dest[1]); /* G */
VEC4_SUB(inv_comp, one, quadColor2[2]); /* B */
VEC4_MUL(blend_dest[2], inv_comp, blend_dest[2]); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
{
float one_minus_alpha[TGSI_QUAD_SIZE];
VEC4_SUB(one_minus_alpha, one, quadColor2[3]);
VEC4_MUL(blend_dest[0], blend_dest[0], one_minus_alpha); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], one_minus_alpha); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], one_minus_alpha); /* B */
}
break;
default:
assert(0 && "invalid rgb dst factor");
}
 
/*
* Compute blend_dest/second term A
*/
switch (softpipe->blend->rt[blend_index].alpha_dst_factor) {
case PIPE_BLENDFACTOR_ONE:
/* blend_dest = blend_dest * 1 NO-OP, leave blend_dest as-is */
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_SRC_ALPHA:
VEC4_MUL(blend_dest[3], blend_dest[3], quadColor[3]); /* A * A */
break;
case PIPE_BLENDFACTOR_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_DST_ALPHA:
VEC4_MUL(blend_dest[3], blend_dest[3], blend_dest[3]); /* A */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
/* blend_dest = blend_dest * 1 NO-OP, leave blend_dest as-is */
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_CONST_ALPHA:
{
float comp[4];
VEC4_SCALAR(comp, const_blend_color[3]); /* A */
VEC4_MUL(blend_dest[3], blend_dest[3], comp); /* A */
}
break;
case PIPE_BLENDFACTOR_ZERO:
VEC4_COPY(blend_dest[3], zero); /* A */
break;
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
{
float one_minus_alpha[TGSI_QUAD_SIZE];
VEC4_SUB(one_minus_alpha, one, quadColor[3]);
VEC4_MUL(blend_dest[3], blend_dest[3], one_minus_alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, blend_dest[3]); /* A */
VEC4_MUL(blend_dest[3], inv_comp, blend_dest[3]); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
{
float inv_comp[4];
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]);
VEC4_MUL(blend_dest[3], blend_dest[3], inv_comp);
}
break;
case PIPE_BLENDFACTOR_SRC1_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_SRC1_ALPHA:
VEC4_MUL(blend_dest[3], blend_dest[3], quadColor2[3]); /* A * A */
break;
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
{
float one_minus_alpha[TGSI_QUAD_SIZE];
VEC4_SUB(one_minus_alpha, one, quadColor2[3]);
VEC4_MUL(blend_dest[3], blend_dest[3], one_minus_alpha); /* A */
}
break;
default:
assert(0 && "invalid alpha dst factor");
}
 
/*
* Combine RGB terms
*/
switch (softpipe->blend->rt[blend_index].rgb_func) {
case PIPE_BLEND_ADD:
VEC4_ADD(quadColor[0], source[0], blend_dest[0]); /* R */
VEC4_ADD(quadColor[1], source[1], blend_dest[1]); /* G */
VEC4_ADD(quadColor[2], source[2], blend_dest[2]); /* B */
break;
case PIPE_BLEND_SUBTRACT:
VEC4_SUB(quadColor[0], source[0], blend_dest[0]); /* R */
VEC4_SUB(quadColor[1], source[1], blend_dest[1]); /* G */
VEC4_SUB(quadColor[2], source[2], blend_dest[2]); /* B */
break;
case PIPE_BLEND_REVERSE_SUBTRACT:
VEC4_SUB(quadColor[0], blend_dest[0], source[0]); /* R */
VEC4_SUB(quadColor[1], blend_dest[1], source[1]); /* G */
VEC4_SUB(quadColor[2], blend_dest[2], source[2]); /* B */
break;
case PIPE_BLEND_MIN:
VEC4_MIN(quadColor[0], source[0], blend_dest[0]); /* R */
VEC4_MIN(quadColor[1], source[1], blend_dest[1]); /* G */
VEC4_MIN(quadColor[2], source[2], blend_dest[2]); /* B */
break;
case PIPE_BLEND_MAX:
VEC4_MAX(quadColor[0], source[0], blend_dest[0]); /* R */
VEC4_MAX(quadColor[1], source[1], blend_dest[1]); /* G */
VEC4_MAX(quadColor[2], source[2], blend_dest[2]); /* B */
break;
default:
assert(0 && "invalid rgb blend func");
}
 
/*
* Combine A terms
*/
switch (softpipe->blend->rt[blend_index].alpha_func) {
case PIPE_BLEND_ADD:
VEC4_ADD(quadColor[3], source[3], blend_dest[3]); /* A */
break;
case PIPE_BLEND_SUBTRACT:
VEC4_SUB(quadColor[3], source[3], blend_dest[3]); /* A */
break;
case PIPE_BLEND_REVERSE_SUBTRACT:
VEC4_SUB(quadColor[3], blend_dest[3], source[3]); /* A */
break;
case PIPE_BLEND_MIN:
VEC4_MIN(quadColor[3], source[3], blend_dest[3]); /* A */
break;
case PIPE_BLEND_MAX:
VEC4_MAX(quadColor[3], source[3], blend_dest[3]); /* A */
break;
default:
assert(0 && "invalid alpha blend func");
}
}
 
static void
colormask_quad(unsigned colormask,
float (*quadColor)[4],
float (*dest)[4])
{
/* R */
if (!(colormask & PIPE_MASK_R))
COPY_4V(quadColor[0], dest[0]);
 
/* G */
if (!(colormask & PIPE_MASK_G))
COPY_4V(quadColor[1], dest[1]);
 
/* B */
if (!(colormask & PIPE_MASK_B))
COPY_4V(quadColor[2], dest[2]);
 
/* A */
if (!(colormask & PIPE_MASK_A))
COPY_4V(quadColor[3], dest[3]);
}
 
 
/**
* Clamp all colors in a quad to [0, 1]
*/
static void
clamp_colors(float (*quadColor)[4])
{
unsigned i, j;
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
for (i = 0; i < 4; i++) {
quadColor[i][j] = CLAMP(quadColor[i][j], 0.0F, 1.0F);
}
}
}
 
 
/**
* If we're drawing to a luminance, luminance/alpha or intensity surface
* we have to adjust (rebase) the fragment/quad colors before writing them
* to the tile cache. The tile cache always stores RGBA colors but if
* we're caching a L/A surface (for example) we need to be sure that R=G=B
* so that subsequent reads from the surface cache appear to return L/A
* values.
* The piglit fbo-blending-formats test will exercise this.
*/
static void
rebase_colors(enum format base_format, float (*quadColor)[4])
{
unsigned i;
 
switch (base_format) {
case RGB:
for (i = 0; i < 4; i++) {
/* A = 1 */
quadColor[3][i] = 1.0F;
}
break;
case LUMINANCE:
for (i = 0; i < 4; i++) {
/* B = G = R */
quadColor[2][i] = quadColor[1][i] = quadColor[0][i];
/* A = 1 */
quadColor[3][i] = 1.0F;
}
break;
case LUMINANCE_ALPHA:
for (i = 0; i < 4; i++) {
/* B = G = R */
quadColor[2][i] = quadColor[1][i] = quadColor[0][i];
}
break;
case INTENSITY:
for (i = 0; i < 4; i++) {
/* A = B = G = R */
quadColor[3][i] = quadColor[2][i] = quadColor[1][i] = quadColor[0][i];
}
break;
default:
; /* nothing */
}
}
 
static void
blend_fallback(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
const struct blend_quad_stage *bqs = blend_quad_stage(qs);
struct softpipe_context *softpipe = qs->softpipe;
const struct pipe_blend_state *blend = softpipe->blend;
unsigned cbuf;
boolean write_all;
 
write_all = softpipe->fs_variant->info.color0_writes_all_cbufs;
 
for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++)
{
/* which blend/mask state index to use: */
const uint blend_buf = blend->independent_blend_enable ? cbuf : 0;
float dest[4][TGSI_QUAD_SIZE];
struct softpipe_cached_tile *tile
= sp_get_cached_tile(softpipe->cbuf_cache[cbuf],
quads[0]->input.x0,
quads[0]->input.y0);
const boolean clamp = bqs->clamp[cbuf];
const float *blend_color;
const boolean dual_source_blend = util_blend_state_is_dual(blend, cbuf);
uint q, i, j;
 
if (clamp)
blend_color = softpipe->blend_color_clamped.color;
else
blend_color = softpipe->blend_color.color;
 
for (q = 0; q < nr; q++) {
struct quad_header *quad = quads[q];
float (*quadColor)[4];
float (*quadColor2)[4] = NULL;
float temp_quad_color[TGSI_QUAD_SIZE][4];
const int itx = (quad->input.x0 & (TILE_SIZE-1));
const int ity = (quad->input.y0 & (TILE_SIZE-1));
 
if (write_all) {
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
for (i = 0; i < 4; i++) {
temp_quad_color[i][j] = quad->output.color[0][i][j];
}
}
quadColor = temp_quad_color;
} else {
quadColor = quad->output.color[cbuf];
if (dual_source_blend)
quadColor2 = quad->output.color[cbuf + 1];
}
 
/* If fixed-point dest color buffer, need to clamp the incoming
* fragment colors now.
*/
if (clamp || softpipe->rasterizer->clamp_fragment_color) {
clamp_colors(quadColor);
}
 
/* get/swizzle dest colors
*/
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) {
dest[i][j] = tile->data.color[y][x][i];
}
}
 
 
if (blend->logicop_enable) {
if (bqs->format_type[cbuf] != UTIL_FORMAT_TYPE_FLOAT) {
logicop_quad( qs, quadColor, dest );
}
}
else if (blend->rt[blend_buf].blend_enable) {
blend_quad(qs, quadColor, quadColor2, dest, blend_color, blend_buf);
 
/* If fixed-point dest color buffer, need to clamp the outgoing
* fragment colors now.
*/
if (clamp) {
clamp_colors(quadColor);
}
}
 
rebase_colors(bqs->base_format[cbuf], quadColor);
 
if (blend->rt[blend_buf].colormask != 0xf)
colormask_quad( blend->rt[cbuf].colormask, quadColor, dest);
/* Output color values
*/
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (quad->inout.mask & (1 << j)) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) { /* loop over color chans */
tile->data.color[y][x][i] = quadColor[i][j];
}
}
}
}
}
}
 
 
static void
blend_single_add_src_alpha_inv_src_alpha(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
const struct blend_quad_stage *bqs = blend_quad_stage(qs);
static const float one[4] = { 1, 1, 1, 1 };
float one_minus_alpha[TGSI_QUAD_SIZE];
float dest[4][TGSI_QUAD_SIZE];
float source[4][TGSI_QUAD_SIZE];
uint i, j, q;
 
struct softpipe_cached_tile *tile
= sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
quads[0]->input.x0,
quads[0]->input.y0);
 
for (q = 0; q < nr; q++) {
struct quad_header *quad = quads[q];
float (*quadColor)[4] = quad->output.color[0];
const float *alpha = quadColor[3];
const int itx = (quad->input.x0 & (TILE_SIZE-1));
const int ity = (quad->input.y0 & (TILE_SIZE-1));
/* get/swizzle dest colors */
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) {
dest[i][j] = tile->data.color[y][x][i];
}
}
 
/* If fixed-point dest color buffer, need to clamp the incoming
* fragment colors now.
*/
if (bqs->clamp[0] || qs->softpipe->rasterizer->clamp_fragment_color) {
clamp_colors(quadColor);
}
 
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
VEC4_MUL(source[3], quadColor[3], alpha); /* A */
 
VEC4_SUB(one_minus_alpha, one, alpha);
VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */
VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */
VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */
VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */
 
VEC4_ADD(quadColor[0], source[0], dest[0]); /* R */
VEC4_ADD(quadColor[1], source[1], dest[1]); /* G */
VEC4_ADD(quadColor[2], source[2], dest[2]); /* B */
VEC4_ADD(quadColor[3], source[3], dest[3]); /* A */
 
/* If fixed-point dest color buffer, need to clamp the outgoing
* fragment colors now.
*/
if (bqs->clamp[0]) {
clamp_colors(quadColor);
}
 
rebase_colors(bqs->base_format[0], quadColor);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (quad->inout.mask & (1 << j)) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) { /* loop over color chans */
tile->data.color[y][x][i] = quadColor[i][j];
}
}
}
}
}
 
static void
blend_single_add_one_one(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
const struct blend_quad_stage *bqs = blend_quad_stage(qs);
float dest[4][TGSI_QUAD_SIZE];
uint i, j, q;
 
struct softpipe_cached_tile *tile
= sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
quads[0]->input.x0,
quads[0]->input.y0);
 
for (q = 0; q < nr; q++) {
struct quad_header *quad = quads[q];
float (*quadColor)[4] = quad->output.color[0];
const int itx = (quad->input.x0 & (TILE_SIZE-1));
const int ity = (quad->input.y0 & (TILE_SIZE-1));
/* get/swizzle dest colors */
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) {
dest[i][j] = tile->data.color[y][x][i];
}
}
/* If fixed-point dest color buffer, need to clamp the incoming
* fragment colors now.
*/
if (bqs->clamp[0] || qs->softpipe->rasterizer->clamp_fragment_color) {
clamp_colors(quadColor);
}
 
VEC4_ADD(quadColor[0], quadColor[0], dest[0]); /* R */
VEC4_ADD(quadColor[1], quadColor[1], dest[1]); /* G */
VEC4_ADD(quadColor[2], quadColor[2], dest[2]); /* B */
VEC4_ADD(quadColor[3], quadColor[3], dest[3]); /* A */
 
/* If fixed-point dest color buffer, need to clamp the outgoing
* fragment colors now.
*/
if (bqs->clamp[0]) {
clamp_colors(quadColor);
}
 
rebase_colors(bqs->base_format[0], quadColor);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (quad->inout.mask & (1 << j)) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) { /* loop over color chans */
tile->data.color[y][x][i] = quadColor[i][j];
}
}
}
}
}
 
 
/**
* Just copy the quad color to the framebuffer tile (respecting the writemask),
* for one color buffer.
* Clamping will be done, if needed (depending on the color buffer's
* datatype) when we write/pack the colors later.
*/
static void
single_output_color(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
const struct blend_quad_stage *bqs = blend_quad_stage(qs);
uint i, j, q;
 
struct softpipe_cached_tile *tile
= sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
quads[0]->input.x0,
quads[0]->input.y0);
 
for (q = 0; q < nr; q++) {
struct quad_header *quad = quads[q];
float (*quadColor)[4] = quad->output.color[0];
const int itx = (quad->input.x0 & (TILE_SIZE-1));
const int ity = (quad->input.y0 & (TILE_SIZE-1));
 
if (qs->softpipe->rasterizer->clamp_fragment_color)
clamp_colors(quadColor);
 
rebase_colors(bqs->base_format[0], quadColor);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (quad->inout.mask & (1 << j)) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) { /* loop over color chans */
tile->data.color[y][x][i] = quadColor[i][j];
}
}
}
}
}
 
static void
blend_noop(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
}
 
 
static void
choose_blend_quad(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
struct blend_quad_stage *bqs = blend_quad_stage(qs);
struct softpipe_context *softpipe = qs->softpipe;
const struct pipe_blend_state *blend = softpipe->blend;
unsigned i;
 
qs->run = blend_fallback;
if (softpipe->framebuffer.nr_cbufs == 0) {
qs->run = blend_noop;
}
else if (!softpipe->blend->logicop_enable &&
softpipe->blend->rt[0].colormask == 0xf &&
softpipe->framebuffer.nr_cbufs == 1)
{
if (!blend->rt[0].blend_enable) {
qs->run = single_output_color;
}
else if (blend->rt[0].rgb_src_factor == blend->rt[0].alpha_src_factor &&
blend->rt[0].rgb_dst_factor == blend->rt[0].alpha_dst_factor &&
blend->rt[0].rgb_func == blend->rt[0].alpha_func)
{
if (blend->rt[0].alpha_func == PIPE_BLEND_ADD) {
if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_ONE &&
blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_ONE) {
qs->run = blend_single_add_one_one;
}
else if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA &&
blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_INV_SRC_ALPHA)
qs->run = blend_single_add_src_alpha_inv_src_alpha;
 
}
}
}
 
/* For each color buffer, determine if the buffer has destination alpha and
* whether color clamping is needed.
*/
for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {
const enum pipe_format format = softpipe->framebuffer.cbufs[i]->format;
const struct util_format_description *desc =
util_format_description(format);
/* assuming all or no color channels are normalized: */
bqs->clamp[i] = desc->channel[0].normalized;
bqs->format_type[i] = desc->channel[0].type;
 
if (util_format_is_intensity(format))
bqs->base_format[i] = INTENSITY;
else if (util_format_is_luminance(format))
bqs->base_format[i] = LUMINANCE;
else if (util_format_is_luminance_alpha(format))
bqs->base_format[i] = LUMINANCE_ALPHA;
else if (!util_format_has_alpha(format))
bqs->base_format[i] = RGB;
else
bqs->base_format[i] = RGBA;
}
 
qs->run(qs, quads, nr);
}
 
 
static void blend_begin(struct quad_stage *qs)
{
qs->run = choose_blend_quad;
}
 
 
static void blend_destroy(struct quad_stage *qs)
{
FREE( qs );
}
 
 
struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe )
{
struct blend_quad_stage *stage = CALLOC_STRUCT(blend_quad_stage);
 
if (!stage)
return NULL;
 
stage->base.softpipe = softpipe;
stage->base.begin = blend_begin;
stage->base.run = choose_blend_quad;
stage->base.destroy = blend_destroy;
 
return &stage->base;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_quad_depth_test.c
0,0 → 1,983
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2010 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 THE AUTHORS 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.
*
**************************************************************************/
 
/**
* \brief Quad depth / stencil testing
*/
 
#include "pipe/p_defines.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_scan.h"
#include "sp_context.h"
#include "sp_quad.h"
#include "sp_quad_pipe.h"
#include "sp_tile_cache.h"
#include "sp_state.h" /* for sp_fragment_shader */
 
 
struct depth_data {
struct pipe_surface *ps;
enum pipe_format format;
unsigned bzzzz[TGSI_QUAD_SIZE]; /**< Z values fetched from depth buffer */
unsigned qzzzz[TGSI_QUAD_SIZE]; /**< Z values from the quad */
ubyte stencilVals[TGSI_QUAD_SIZE];
boolean use_shader_stencil_refs;
ubyte shader_stencil_refs[TGSI_QUAD_SIZE];
struct softpipe_cached_tile *tile;
};
 
 
 
static void
get_depth_stencil_values( struct depth_data *data,
const struct quad_header *quad )
{
unsigned j;
const struct softpipe_cached_tile *tile = data->tile;
 
switch (data->format) {
case PIPE_FORMAT_Z16_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = tile->data.depth16[y][x];
}
break;
case PIPE_FORMAT_Z32_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = tile->data.depth32[y][x];
}
break;
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = tile->data.depth32[y][x] & 0xffffff;
data->stencilVals[j] = tile->data.depth32[y][x] >> 24;
}
break;
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = tile->data.depth32[y][x] >> 8;
data->stencilVals[j] = tile->data.depth32[y][x] & 0xff;
}
break;
case PIPE_FORMAT_S8_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = 0;
data->stencilVals[j] = tile->data.stencil8[y][x];
}
break;
case PIPE_FORMAT_Z32_FLOAT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = tile->data.depth32[y][x];
}
break;
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = tile->data.depth64[y][x] & 0xffffffff;
data->stencilVals[j] = (tile->data.depth64[y][x] >> 32) & 0xff;
}
break;
default:
assert(0);
}
}
 
 
/**
* If the shader has not been run, interpolate the depth values
* ourselves.
*/
static void
interpolate_quad_depth( struct quad_header *quad )
{
const float fx = (float) quad->input.x0;
const float fy = (float) quad->input.y0;
const float dzdx = quad->posCoef->dadx[2];
const float dzdy = quad->posCoef->dady[2];
const float z0 = quad->posCoef->a0[2] + dzdx * fx + dzdy * fy;
 
quad->output.depth[0] = z0;
quad->output.depth[1] = z0 + dzdx;
quad->output.depth[2] = z0 + dzdy;
quad->output.depth[3] = z0 + dzdx + dzdy;
}
 
 
/**
* Compute the depth_data::qzzzz[] values from the float fragment Z values.
*/
static void
convert_quad_depth( struct depth_data *data,
const struct quad_header *quad )
{
unsigned j;
 
/* Convert quad's float depth values to int depth values (qzzzz).
* If the Z buffer stores integer values, we _have_ to do the depth
* compares with integers (not floats). Otherwise, the float->int->float
* conversion of Z values (which isn't an identity function) will cause
* Z-fighting errors.
*/
switch (data->format) {
case PIPE_FORMAT_Z16_UNORM:
{
float scale = 65535.0;
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
}
}
break;
case PIPE_FORMAT_Z32_UNORM:
{
double scale = (double) (uint) ~0UL;
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
}
}
break;
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
{
float scale = (float) ((1 << 24) - 1);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
}
}
break;
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
{
float scale = (float) ((1 << 24) - 1);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
}
}
break;
case PIPE_FORMAT_Z32_FLOAT:
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
{
union fi fui;
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
fui.f = quad->output.depth[j];
data->qzzzz[j] = fui.ui;
}
}
break;
default:
assert(0);
}
}
 
 
/**
* Compute the depth_data::shader_stencil_refs[] values from the float
* fragment stencil values.
*/
static void
convert_quad_stencil( struct depth_data *data,
const struct quad_header *quad )
{
unsigned j;
 
data->use_shader_stencil_refs = TRUE;
/* Copy quads stencil values
*/
switch (data->format) {
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
case PIPE_FORMAT_S8_UINT:
case PIPE_FORMAT_Z32_FLOAT:
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->shader_stencil_refs[j] = ((unsigned)(quad->output.stencil[j]));
}
break;
default:
assert(0);
}
}
 
 
/**
* Write data->bzzzz[] values and data->stencilVals into the Z/stencil buffer.
*/
static void
write_depth_stencil_values( struct depth_data *data,
struct quad_header *quad )
{
struct softpipe_cached_tile *tile = data->tile;
unsigned j;
 
/* put updated Z values back into cached tile */
switch (data->format) {
case PIPE_FORMAT_Z16_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth16[y][x] = (ushort) data->bzzzz[j];
}
break;
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z32_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth32[y][x] = data->bzzzz[j];
}
break;
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth32[y][x] = (data->stencilVals[j] << 24) | data->bzzzz[j];
}
break;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth32[y][x] = (data->bzzzz[j] << 8) | data->stencilVals[j];
}
break;
case PIPE_FORMAT_X8Z24_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth32[y][x] = data->bzzzz[j] << 8;
}
break;
case PIPE_FORMAT_S8_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.stencil8[y][x] = data->stencilVals[j];
}
break;
case PIPE_FORMAT_Z32_FLOAT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth32[y][x] = data->bzzzz[j];
}
break;
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth64[y][x] = (uint64_t)data->bzzzz[j] | ((uint64_t)data->stencilVals[j] << 32);
}
break;
default:
assert(0);
}
}
 
 
 
/** Only 8-bit stencil supported */
#define STENCIL_MAX 0xff
 
 
/**
* Do the basic stencil test (compare stencil buffer values against the
* reference value.
*
* \param data->stencilVals the stencil values from the stencil buffer
* \param func the stencil func (PIPE_FUNC_x)
* \param ref the stencil reference value
* \param valMask the stencil value mask indicating which bits of the stencil
* values and ref value are to be used.
* \return mask indicating which pixels passed the stencil test
*/
static unsigned
do_stencil_test(struct depth_data *data,
unsigned func,
unsigned ref, unsigned valMask)
{
unsigned passMask = 0x0;
unsigned j;
ubyte refs[TGSI_QUAD_SIZE];
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->use_shader_stencil_refs)
refs[j] = data->shader_stencil_refs[j] & valMask;
else
refs[j] = ref & valMask;
}
 
switch (func) {
case PIPE_FUNC_NEVER:
/* passMask = 0x0 */
break;
case PIPE_FUNC_LESS:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (refs[j] < (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_EQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (refs[j] == (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_LEQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (refs[j] <= (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_GREATER:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (refs[j] > (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_NOTEQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (refs[j] != (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_GEQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (refs[j] >= (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_ALWAYS:
passMask = MASK_ALL;
break;
default:
assert(0);
}
 
return passMask;
}
 
 
/**
* Apply the stencil operator to stencil values.
*
* \param data->stencilVals the stencil buffer values (read and written)
* \param mask indicates which pixels to update
* \param op the stencil operator (PIPE_STENCIL_OP_x)
* \param ref the stencil reference value
* \param wrtMask writemask controlling which bits are changed in the
* stencil values
*/
static void
apply_stencil_op(struct depth_data *data,
unsigned mask, unsigned op, ubyte ref, ubyte wrtMask)
{
unsigned j;
ubyte newstencil[TGSI_QUAD_SIZE];
ubyte refs[TGSI_QUAD_SIZE];
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
newstencil[j] = data->stencilVals[j];
if (data->use_shader_stencil_refs)
refs[j] = data->shader_stencil_refs[j];
else
refs[j] = ref;
}
 
switch (op) {
case PIPE_STENCIL_OP_KEEP:
/* no-op */
break;
case PIPE_STENCIL_OP_ZERO:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = 0;
}
}
break;
case PIPE_STENCIL_OP_REPLACE:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = refs[j];
}
}
break;
case PIPE_STENCIL_OP_INCR:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
if (data->stencilVals[j] < STENCIL_MAX) {
newstencil[j] = data->stencilVals[j] + 1;
}
}
}
break;
case PIPE_STENCIL_OP_DECR:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
if (data->stencilVals[j] > 0) {
newstencil[j] = data->stencilVals[j] - 1;
}
}
}
break;
case PIPE_STENCIL_OP_INCR_WRAP:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = data->stencilVals[j] + 1;
}
}
break;
case PIPE_STENCIL_OP_DECR_WRAP:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = data->stencilVals[j] - 1;
}
}
break;
case PIPE_STENCIL_OP_INVERT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = ~data->stencilVals[j];
}
}
break;
default:
assert(0);
}
 
/*
* update the stencil values
*/
if (wrtMask != STENCIL_MAX) {
/* apply bit-wise stencil buffer writemask */
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->stencilVals[j] = (wrtMask & newstencil[j]) | (~wrtMask & data->stencilVals[j]);
}
}
else {
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->stencilVals[j] = newstencil[j];
}
}
}
 
 
/**
* To increase efficiency, we should probably have multiple versions
* of this function that are specifically for Z16, Z32 and FP Z buffers.
* Try to effectively do that with codegen...
*/
static boolean
depth_test_quad(struct quad_stage *qs,
struct depth_data *data,
struct quad_header *quad)
{
struct softpipe_context *softpipe = qs->softpipe;
unsigned zmask = 0;
unsigned j;
 
switch (softpipe->depth_stencil->depth.func) {
case PIPE_FUNC_NEVER:
/* zmask = 0 */
break;
case PIPE_FUNC_LESS:
/* Note this is pretty much a single sse or cell instruction.
* Like this: quad->mask &= (quad->outputs.depth < zzzz);
*/
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->qzzzz[j] < data->bzzzz[j])
zmask |= 1 << j;
}
break;
case PIPE_FUNC_EQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->qzzzz[j] == data->bzzzz[j])
zmask |= 1 << j;
}
break;
case PIPE_FUNC_LEQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->qzzzz[j] <= data->bzzzz[j])
zmask |= (1 << j);
}
break;
case PIPE_FUNC_GREATER:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->qzzzz[j] > data->bzzzz[j])
zmask |= (1 << j);
}
break;
case PIPE_FUNC_NOTEQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->qzzzz[j] != data->bzzzz[j])
zmask |= (1 << j);
}
break;
case PIPE_FUNC_GEQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->qzzzz[j] >= data->bzzzz[j])
zmask |= (1 << j);
}
break;
case PIPE_FUNC_ALWAYS:
zmask = MASK_ALL;
break;
default:
assert(0);
}
 
quad->inout.mask &= zmask;
if (quad->inout.mask == 0)
return FALSE;
 
/* Update our internal copy only if writemask set. Even if
* depth.writemask is FALSE, may still need to write out buffer
* data due to stencil changes.
*/
if (softpipe->depth_stencil->depth.writemask) {
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (quad->inout.mask & (1 << j)) {
data->bzzzz[j] = data->qzzzz[j];
}
}
}
 
return TRUE;
}
 
 
 
/**
* Do stencil (and depth) testing. Stenciling depends on the outcome of
* depth testing.
*/
static void
depth_stencil_test_quad(struct quad_stage *qs,
struct depth_data *data,
struct quad_header *quad)
{
struct softpipe_context *softpipe = qs->softpipe;
unsigned func, zFailOp, zPassOp, failOp;
ubyte ref, wrtMask, valMask;
uint face = quad->input.facing;
 
if (!softpipe->depth_stencil->stencil[1].enabled) {
/* single-sided stencil test, use front (face=0) state */
face = 0;
}
 
/* 0 = front-face, 1 = back-face */
assert(face == 0 || face == 1);
 
/* choose front or back face function, operator, etc */
/* XXX we could do these initializations once per primitive */
func = softpipe->depth_stencil->stencil[face].func;
failOp = softpipe->depth_stencil->stencil[face].fail_op;
zFailOp = softpipe->depth_stencil->stencil[face].zfail_op;
zPassOp = softpipe->depth_stencil->stencil[face].zpass_op;
ref = softpipe->stencil_ref.ref_value[face];
wrtMask = softpipe->depth_stencil->stencil[face].writemask;
valMask = softpipe->depth_stencil->stencil[face].valuemask;
 
/* do the stencil test first */
{
unsigned passMask, failMask;
passMask = do_stencil_test(data, func, ref, valMask);
failMask = quad->inout.mask & ~passMask;
quad->inout.mask &= passMask;
 
if (failOp != PIPE_STENCIL_OP_KEEP) {
apply_stencil_op(data, failMask, failOp, ref, wrtMask);
}
}
 
if (quad->inout.mask) {
/* now the pixels that passed the stencil test are depth tested */
if (softpipe->depth_stencil->depth.enabled) {
const unsigned origMask = quad->inout.mask;
 
depth_test_quad(qs, data, quad); /* quad->mask is updated */
 
/* update stencil buffer values according to z pass/fail result */
if (zFailOp != PIPE_STENCIL_OP_KEEP) {
const unsigned zFailMask = origMask & ~quad->inout.mask;
apply_stencil_op(data, zFailMask, zFailOp, ref, wrtMask);
}
 
if (zPassOp != PIPE_STENCIL_OP_KEEP) {
const unsigned zPassMask = origMask & quad->inout.mask;
apply_stencil_op(data, zPassMask, zPassOp, ref, wrtMask);
}
}
else {
/* no depth test, apply Zpass operator to stencil buffer values */
apply_stencil_op(data, quad->inout.mask, zPassOp, ref, wrtMask);
}
}
}
 
 
#define ALPHATEST( FUNC, COMP ) \
static unsigned \
alpha_test_quads_##FUNC( struct quad_stage *qs, \
struct quad_header *quads[], \
unsigned nr ) \
{ \
const float ref = qs->softpipe->depth_stencil->alpha.ref_value; \
const uint cbuf = 0; /* only output[0].alpha is tested */ \
unsigned pass_nr = 0; \
unsigned i; \
\
for (i = 0; i < nr; i++) { \
const float *aaaa = quads[i]->output.color[cbuf][3]; \
unsigned passMask = 0; \
\
if (aaaa[0] COMP ref) passMask |= (1 << 0); \
if (aaaa[1] COMP ref) passMask |= (1 << 1); \
if (aaaa[2] COMP ref) passMask |= (1 << 2); \
if (aaaa[3] COMP ref) passMask |= (1 << 3); \
\
quads[i]->inout.mask &= passMask; \
\
if (quads[i]->inout.mask) \
quads[pass_nr++] = quads[i]; \
} \
\
return pass_nr; \
}
 
 
ALPHATEST( LESS, < )
ALPHATEST( EQUAL, == )
ALPHATEST( LEQUAL, <= )
ALPHATEST( GREATER, > )
ALPHATEST( NOTEQUAL, != )
ALPHATEST( GEQUAL, >= )
 
 
/* XXX: Incorporate into shader using KILL_IF.
*/
static unsigned
alpha_test_quads(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
switch (qs->softpipe->depth_stencil->alpha.func) {
case PIPE_FUNC_LESS:
return alpha_test_quads_LESS( qs, quads, nr );
case PIPE_FUNC_EQUAL:
return alpha_test_quads_EQUAL( qs, quads, nr );
case PIPE_FUNC_LEQUAL:
return alpha_test_quads_LEQUAL( qs, quads, nr );
case PIPE_FUNC_GREATER:
return alpha_test_quads_GREATER( qs, quads, nr );
case PIPE_FUNC_NOTEQUAL:
return alpha_test_quads_NOTEQUAL( qs, quads, nr );
case PIPE_FUNC_GEQUAL:
return alpha_test_quads_GEQUAL( qs, quads, nr );
case PIPE_FUNC_ALWAYS:
return nr;
case PIPE_FUNC_NEVER:
default:
return 0;
}
}
 
 
static unsigned mask_count[16] =
{
0, /* 0x0 */
1, /* 0x1 */
1, /* 0x2 */
2, /* 0x3 */
1, /* 0x4 */
2, /* 0x5 */
2, /* 0x6 */
3, /* 0x7 */
1, /* 0x8 */
2, /* 0x9 */
2, /* 0xa */
3, /* 0xb */
2, /* 0xc */
3, /* 0xd */
3, /* 0xe */
4, /* 0xf */
};
 
 
 
/**
* General depth/stencil test function. Used when there's no fast-path.
*/
static void
depth_test_quads_fallback(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
unsigned i, pass = 0;
const struct tgsi_shader_info *fsInfo = &qs->softpipe->fs_variant->info;
boolean interp_depth = !fsInfo->writes_z;
boolean shader_stencil_ref = fsInfo->writes_stencil;
struct depth_data data;
 
data.use_shader_stencil_refs = FALSE;
 
if (qs->softpipe->depth_stencil->alpha.enabled) {
nr = alpha_test_quads(qs, quads, nr);
}
 
if (qs->softpipe->framebuffer.zsbuf &&
(qs->softpipe->depth_stencil->depth.enabled ||
qs->softpipe->depth_stencil->stencil[0].enabled)) {
 
data.ps = qs->softpipe->framebuffer.zsbuf;
data.format = data.ps->format;
data.tile = sp_get_cached_tile(qs->softpipe->zsbuf_cache,
quads[0]->input.x0,
quads[0]->input.y0);
 
for (i = 0; i < nr; i++) {
get_depth_stencil_values(&data, quads[i]);
 
if (qs->softpipe->depth_stencil->depth.enabled) {
if (interp_depth)
interpolate_quad_depth(quads[i]);
 
convert_quad_depth(&data, quads[i]);
}
 
if (qs->softpipe->depth_stencil->stencil[0].enabled) {
if (shader_stencil_ref)
convert_quad_stencil(&data, quads[i]);
depth_stencil_test_quad(qs, &data, quads[i]);
write_depth_stencil_values(&data, quads[i]);
}
else {
if (!depth_test_quad(qs, &data, quads[i]))
continue;
 
if (qs->softpipe->depth_stencil->depth.writemask)
write_depth_stencil_values(&data, quads[i]);
}
 
quads[pass++] = quads[i];
}
 
nr = pass;
}
 
if (qs->softpipe->active_query_count) {
for (i = 0; i < nr; i++)
qs->softpipe->occlusion_count += mask_count[quads[i]->inout.mask];
}
 
if (nr)
qs->next->run(qs->next, quads, nr);
}
 
 
/**
* Special-case Z testing for 16-bit Zbuffer and Z buffer writes enabled.
*/
 
#define NAME depth_interp_z16_less_write
#define OPERATOR <
#include "sp_quad_depth_test_tmp.h"
 
#define NAME depth_interp_z16_equal_write
#define OPERATOR ==
#include "sp_quad_depth_test_tmp.h"
 
#define NAME depth_interp_z16_lequal_write
#define OPERATOR <=
#include "sp_quad_depth_test_tmp.h"
 
#define NAME depth_interp_z16_greater_write
#define OPERATOR >
#include "sp_quad_depth_test_tmp.h"
 
#define NAME depth_interp_z16_notequal_write
#define OPERATOR !=
#include "sp_quad_depth_test_tmp.h"
 
#define NAME depth_interp_z16_gequal_write
#define OPERATOR >=
#include "sp_quad_depth_test_tmp.h"
 
#define NAME depth_interp_z16_always_write
#define ALWAYS 1
#include "sp_quad_depth_test_tmp.h"
 
 
 
static void
depth_noop(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
qs->next->run(qs->next, quads, nr);
}
 
 
 
static void
choose_depth_test(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
const struct tgsi_shader_info *fsInfo = &qs->softpipe->fs_variant->info;
 
boolean interp_depth = !fsInfo->writes_z;
 
boolean alpha = qs->softpipe->depth_stencil->alpha.enabled;
 
boolean depth = qs->softpipe->depth_stencil->depth.enabled;
 
unsigned depthfunc = qs->softpipe->depth_stencil->depth.func;
 
boolean stencil = qs->softpipe->depth_stencil->stencil[0].enabled;
 
boolean depthwrite = qs->softpipe->depth_stencil->depth.writemask;
 
boolean occlusion = qs->softpipe->active_query_count;
 
if(!qs->softpipe->framebuffer.zsbuf)
depth = depthwrite = stencil = FALSE;
 
/* default */
qs->run = depth_test_quads_fallback;
 
/* look for special cases */
if (!alpha &&
!depth &&
!occlusion &&
!stencil) {
qs->run = depth_noop;
}
else if (!alpha &&
interp_depth &&
depth &&
depthwrite &&
!occlusion &&
!stencil)
{
if (qs->softpipe->framebuffer.zsbuf->format == PIPE_FORMAT_Z16_UNORM) {
switch (depthfunc) {
case PIPE_FUNC_NEVER:
qs->run = depth_test_quads_fallback;
break;
case PIPE_FUNC_LESS:
qs->run = depth_interp_z16_less_write;
break;
case PIPE_FUNC_EQUAL:
qs->run = depth_interp_z16_equal_write;
break;
case PIPE_FUNC_LEQUAL:
qs->run = depth_interp_z16_lequal_write;
break;
case PIPE_FUNC_GREATER:
qs->run = depth_interp_z16_greater_write;
break;
case PIPE_FUNC_NOTEQUAL:
qs->run = depth_interp_z16_notequal_write;
break;
case PIPE_FUNC_GEQUAL:
qs->run = depth_interp_z16_gequal_write;
break;
case PIPE_FUNC_ALWAYS:
qs->run = depth_interp_z16_always_write;
break;
default:
qs->run = depth_test_quads_fallback;
break;
}
}
}
 
/* next quad/fragment stage */
qs->run( qs, quads, nr );
}
 
 
 
static void
depth_test_begin(struct quad_stage *qs)
{
qs->run = choose_depth_test;
qs->next->begin(qs->next);
}
 
 
static void
depth_test_destroy(struct quad_stage *qs)
{
FREE( qs );
}
 
 
struct quad_stage *
sp_quad_depth_test_stage(struct softpipe_context *softpipe)
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
 
stage->softpipe = softpipe;
stage->begin = depth_test_begin;
stage->run = choose_depth_test;
stage->destroy = depth_test_destroy;
 
return stage;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_quad_depth_test_tmp.h
0,0 → 1,147
/**************************************************************************
*
* Copyright 2010 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 THE AUTHORS 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.
*
**************************************************************************/
 
 
/*
* Template for generating Z test functions
* Only PIPE_FORMAT_Z16_UNORM supported at this time.
*/
 
 
#ifndef NAME
#error "NAME is not defined!"
#endif
 
#if !defined(OPERATOR) && !defined(ALWAYS)
#error "neither OPERATOR nor ALWAYS is defined!"
#endif
 
 
/*
* NOTE: there's no guarantee that the quads are sequentially side by
* side. The fragment shader may have culled some quads, etc. Sliver
* triangles may generate non-sequential quads.
*/
static void
NAME(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
unsigned i, pass = 0;
const unsigned ix = quads[0]->input.x0;
const unsigned iy = quads[0]->input.y0;
const float fx = (float) ix;
const float fy = (float) iy;
const float dzdx = quads[0]->posCoef->dadx[2];
const float dzdy = quads[0]->posCoef->dady[2];
const float z0 = quads[0]->posCoef->a0[2] + dzdx * fx + dzdy * fy;
struct softpipe_cached_tile *tile;
ushort (*depth16)[TILE_SIZE];
ushort init_idepth[4], idepth[4], depth_step;
const float scale = 65535.0;
 
/* compute scaled depth of the four pixels in first quad */
init_idepth[0] = (ushort)((z0) * scale);
init_idepth[1] = (ushort)((z0 + dzdx) * scale);
init_idepth[2] = (ushort)((z0 + dzdy) * scale);
init_idepth[3] = (ushort)((z0 + dzdx + dzdy) * scale);
 
depth_step = (ushort)(dzdx * scale);
 
tile = sp_get_cached_tile(qs->softpipe->zsbuf_cache, ix, iy);
 
for (i = 0; i < nr; i++) {
const unsigned outmask = quads[i]->inout.mask;
const int dx = quads[i]->input.x0 - ix;
unsigned mask = 0;
/* compute depth for this quad */
idepth[0] = init_idepth[0] + dx * depth_step;
idepth[1] = init_idepth[1] + dx * depth_step;
idepth[2] = init_idepth[2] + dx * depth_step;
idepth[3] = init_idepth[3] + dx * depth_step;
 
depth16 = (ushort (*)[TILE_SIZE])
&tile->data.depth16[iy % TILE_SIZE][(ix + dx)% TILE_SIZE];
 
#ifdef ALWAYS
if (outmask & 1) {
depth16[0][0] = idepth[0];
mask |= (1 << 0);
}
 
if (outmask & 2) {
depth16[0][1] = idepth[1];
mask |= (1 << 1);
}
 
if (outmask & 4) {
depth16[1][0] = idepth[2];
mask |= (1 << 2);
}
 
if (outmask & 8) {
depth16[1][1] = idepth[3];
mask |= (1 << 3);
}
#else
/* Note: OPERATOR appears here: */
if ((outmask & 1) && (idepth[0] OPERATOR depth16[0][0])) {
depth16[0][0] = idepth[0];
mask |= (1 << 0);
}
 
if ((outmask & 2) && (idepth[1] OPERATOR depth16[0][1])) {
depth16[0][1] = idepth[1];
mask |= (1 << 1);
}
 
if ((outmask & 4) && (idepth[2] OPERATOR depth16[1][0])) {
depth16[1][0] = idepth[2];
mask |= (1 << 2);
}
 
if ((outmask & 8) && (idepth[3] OPERATOR depth16[1][1])) {
depth16[1][1] = idepth[3];
mask |= (1 << 3);
}
#endif
 
depth16 = (ushort (*)[TILE_SIZE]) &depth16[0][2];
 
quads[i]->inout.mask = mask;
if (quads[i]->inout.mask)
quads[pass++] = quads[i];
}
 
if (pass)
qs->next->run(qs->next, quads, pass);
}
 
 
#undef NAME
#undef OPERATOR
#undef ALWAYS
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_quad_fs.c
0,0 → 1,184
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2008 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Vertices are just an array of floats, with all the attributes
* packed. We currently assume a layout like:
*
* attr[0][0..3] - window position
* attr[1..n][0..3] - remaining attributes.
*
* Attributes are assumed to be 4 floats wide but are packed so that
* all the enabled attributes run contiguously.
*/
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
 
#include "sp_context.h"
#include "sp_state.h"
#include "sp_quad.h"
#include "sp_quad_pipe.h"
 
 
struct quad_shade_stage
{
struct quad_stage stage; /**< base class */
 
/* no other fields at this time */
};
 
 
/** cast wrapper */
static INLINE struct quad_shade_stage *
quad_shade_stage(struct quad_stage *qs)
{
return (struct quad_shade_stage *) qs;
}
 
 
/**
* Execute fragment shader for the four fragments in the quad.
* \return TRUE if quad is alive, FALSE if all four pixels are killed
*/
static INLINE boolean
shade_quad(struct quad_stage *qs, struct quad_header *quad)
{
struct softpipe_context *softpipe = qs->softpipe;
struct tgsi_exec_machine *machine = softpipe->fs_machine;
 
if (softpipe->active_statistics_queries) {
softpipe->pipeline_statistics.ps_invocations +=
util_bitcount(quad->inout.mask);
}
 
/* run shader */
machine->flatshade_color = softpipe->rasterizer->flatshade ? TRUE : FALSE;
return softpipe->fs_variant->run( softpipe->fs_variant, machine, quad );
}
 
 
 
static void
coverage_quad(struct quad_stage *qs, struct quad_header *quad)
{
struct softpipe_context *softpipe = qs->softpipe;
uint cbuf;
 
/* loop over colorbuffer outputs */
for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) {
float (*quadColor)[4] = quad->output.color[cbuf];
unsigned j;
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
assert(quad->input.coverage[j] >= 0.0);
assert(quad->input.coverage[j] <= 1.0);
quadColor[3][j] *= quad->input.coverage[j];
}
}
}
 
 
/**
* Shade/write an array of quads
* Called via quad_stage::run()
*/
static void
shade_quads(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
struct softpipe_context *softpipe = qs->softpipe;
struct tgsi_exec_machine *machine = softpipe->fs_machine;
unsigned i, nr_quads = 0;
 
tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
softpipe->mapped_constants[PIPE_SHADER_FRAGMENT],
softpipe->const_buffer_size[PIPE_SHADER_FRAGMENT]);
 
machine->InterpCoefs = quads[0]->coef;
 
for (i = 0; i < nr; i++) {
/* Only omit this quad from the output list if all the fragments
* are killed _AND_ it's not the first quad in the list.
* The first quad is special in the (optimized) depth-testing code:
* the quads' Z coordinates are step-wise interpolated with respect
* to the first quad in the list.
* For multi-pass algorithms we need to produce exactly the same
* Z values in each pass. If interpolation starts with different quads
* we can get different Z values for the same (x,y).
*/
if (!shade_quad(qs, quads[i]) && i > 0)
continue; /* quad totally culled/killed */
 
if (/*do_coverage*/ 0)
coverage_quad( qs, quads[i] );
 
quads[nr_quads++] = quads[i];
}
if (nr_quads)
qs->next->run(qs->next, quads, nr_quads);
}
 
/**
* Per-primitive (or per-begin?) setup
*/
static void
shade_begin(struct quad_stage *qs)
{
qs->next->begin(qs->next);
}
 
 
static void
shade_destroy(struct quad_stage *qs)
{
FREE( qs );
}
 
 
struct quad_stage *
sp_quad_shade_stage( struct softpipe_context *softpipe )
{
struct quad_shade_stage *qss = CALLOC_STRUCT(quad_shade_stage);
if (!qss)
goto fail;
 
qss->stage.softpipe = softpipe;
qss->stage.begin = shade_begin;
qss->stage.run = shade_quads;
qss->stage.destroy = shade_destroy;
 
return &qss->stage;
 
fail:
FREE(qss);
return NULL;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_quad_pipe.c
0,0 → 1,69
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
 
#include "sp_context.h"
#include "sp_state.h"
#include "pipe/p_shader_tokens.h"
 
 
static void
insert_stage_at_head(struct softpipe_context *sp, struct quad_stage *quad)
{
quad->next = sp->quad.first;
sp->quad.first = quad;
}
 
 
void
sp_build_quad_pipeline(struct softpipe_context *sp)
{
boolean early_depth_test =
sp->depth_stencil->depth.enabled &&
sp->framebuffer.zsbuf &&
!sp->depth_stencil->alpha.enabled &&
!sp->fs_variant->info.uses_kill &&
!sp->fs_variant->info.writes_z &&
!sp->fs_variant->info.writes_stencil;
 
sp->quad.first = sp->quad.blend;
 
if (early_depth_test) {
insert_stage_at_head( sp, sp->quad.shade );
insert_stage_at_head( sp, sp->quad.depth_test );
}
else {
insert_stage_at_head( sp, sp->quad.depth_test );
insert_stage_at_head( sp, sp->quad.shade );
}
 
#if !DO_PSTIPPLE_IN_DRAW_MODULE && !DO_PSTIPPLE_IN_HELPER_MODULE
if (sp->rasterizer->poly_stipple_enable)
insert_stage_at_head( sp, sp->quad.pstipple );
#endif
}
 
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_quad_pipe.h
0,0 → 1,72
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_QUAD_PIPE_H
#define SP_QUAD_PIPE_H
 
 
struct softpipe_context;
struct quad_header;
 
 
/**
* Fragment processing is performed on 2x2 blocks of pixels called "quads".
* Quad processing is performed with a pipeline of stages represented by
* this type.
*/
struct quad_stage {
struct softpipe_context *softpipe;
 
struct quad_stage *next;
 
void (*begin)(struct quad_stage *qs);
 
/** the stage action */
void (*run)(struct quad_stage *qs, struct quad_header *quad[], unsigned nr);
 
void (*destroy)(struct quad_stage *qs);
};
 
 
struct quad_stage *sp_quad_polygon_stipple_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_earlyz_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_alpha_test_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_occlusion_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_coverage_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_colormask_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_output_stage( struct softpipe_context *softpipe );
 
void sp_build_quad_pipeline(struct softpipe_context *sp);
 
#endif /* SP_QUAD_PIPE_H */
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_quad_stipple.c
0,0 → 1,81
 
/**
* quad polygon stipple stage
*/
 
#include "sp_context.h"
#include "sp_quad.h"
#include "sp_quad_pipe.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
 
 
/**
* Apply polygon stipple to quads produced by triangle rasterization
*/
static void
stipple_quad(struct quad_stage *qs, struct quad_header *quads[], unsigned nr)
{
static const uint bit31 = 1 << 31;
static const uint bit30 = 1 << 30;
unsigned pass = nr;
 
struct softpipe_context *softpipe = qs->softpipe;
unsigned q;
 
pass = 0;
 
for (q = 0; q < nr; q++) {
struct quad_header *quad = quads[q];
 
const int col0 = quad->input.x0 % 32;
const int y0 = quad->input.y0;
const int y1 = y0 + 1;
const uint stipple0 = softpipe->poly_stipple.stipple[y0 % 32];
const uint stipple1 = softpipe->poly_stipple.stipple[y1 % 32];
 
/* turn off quad mask bits that fail the stipple test */
if ((stipple0 & (bit31 >> col0)) == 0)
quad->inout.mask &= ~MASK_TOP_LEFT;
 
if ((stipple0 & (bit30 >> col0)) == 0)
quad->inout.mask &= ~MASK_TOP_RIGHT;
 
if ((stipple1 & (bit31 >> col0)) == 0)
quad->inout.mask &= ~MASK_BOTTOM_LEFT;
 
if ((stipple1 & (bit30 >> col0)) == 0)
quad->inout.mask &= ~MASK_BOTTOM_RIGHT;
 
if (quad->inout.mask)
quads[pass++] = quad;
}
 
qs->next->run(qs->next, quads, pass);
}
 
 
static void stipple_begin(struct quad_stage *qs)
{
qs->next->begin(qs->next);
}
 
 
static void stipple_destroy(struct quad_stage *qs)
{
FREE( qs );
}
 
 
struct quad_stage *
sp_quad_polygon_stipple_stage( struct softpipe_context *softpipe )
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
 
stage->softpipe = softpipe;
stage->begin = stipple_begin;
stage->run = stipple_quad;
stage->destroy = stipple_destroy;
 
return stage;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_query.c
0,0 → 1,296
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Author:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "draw/draw_context.h"
#include "os/os_time.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "sp_context.h"
#include "sp_query.h"
#include "sp_state.h"
 
struct softpipe_query {
unsigned type;
uint64_t start;
uint64_t end;
struct pipe_query_data_so_statistics so;
unsigned num_primitives_generated;
 
struct pipe_query_data_pipeline_statistics stats;
};
 
 
static struct softpipe_query *softpipe_query( struct pipe_query *p )
{
return (struct softpipe_query *)p;
}
 
static struct pipe_query *
softpipe_create_query(struct pipe_context *pipe,
unsigned type)
{
struct softpipe_query* sq;
 
assert(type == PIPE_QUERY_OCCLUSION_COUNTER ||
type == PIPE_QUERY_OCCLUSION_PREDICATE ||
type == PIPE_QUERY_TIME_ELAPSED ||
type == PIPE_QUERY_SO_STATISTICS ||
type == PIPE_QUERY_SO_OVERFLOW_PREDICATE ||
type == PIPE_QUERY_PRIMITIVES_EMITTED ||
type == PIPE_QUERY_PRIMITIVES_GENERATED ||
type == PIPE_QUERY_PIPELINE_STATISTICS ||
type == PIPE_QUERY_GPU_FINISHED ||
type == PIPE_QUERY_TIMESTAMP ||
type == PIPE_QUERY_TIMESTAMP_DISJOINT);
sq = CALLOC_STRUCT( softpipe_query );
sq->type = type;
 
return (struct pipe_query *)sq;
}
 
 
static void
softpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
{
FREE(q);
}
 
 
static void
softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
{
struct softpipe_context *softpipe = softpipe_context( pipe );
struct softpipe_query *sq = softpipe_query(q);
 
switch (sq->type) {
case PIPE_QUERY_OCCLUSION_COUNTER:
case PIPE_QUERY_OCCLUSION_PREDICATE:
sq->start = softpipe->occlusion_count;
break;
case PIPE_QUERY_TIME_ELAPSED:
sq->start = os_time_get_nano();
break;
case PIPE_QUERY_SO_STATISTICS:
sq->so.primitives_storage_needed = 0;
sq->num_primitives_generated = 0;
softpipe->num_primitives_generated = 0;
sq->so.num_primitives_written = 0;
softpipe->so_stats.num_primitives_written = 0;
break;
case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
sq->end = FALSE;
break;
case PIPE_QUERY_PRIMITIVES_EMITTED:
sq->so.num_primitives_written = 0;
softpipe->so_stats.num_primitives_written = 0;
break;
case PIPE_QUERY_PRIMITIVES_GENERATED:
sq->num_primitives_generated = 0;
softpipe->num_primitives_generated = 0;
break;
case PIPE_QUERY_TIMESTAMP:
case PIPE_QUERY_GPU_FINISHED:
case PIPE_QUERY_TIMESTAMP_DISJOINT:
break;
case PIPE_QUERY_PIPELINE_STATISTICS:
/* reset our cache */
if (softpipe->active_statistics_queries == 0) {
memset(&softpipe->pipeline_statistics, 0,
sizeof(softpipe->pipeline_statistics));
}
memcpy(&sq->stats, &softpipe->pipeline_statistics,
sizeof(sq->stats));
softpipe->active_statistics_queries++;
break;
default:
assert(0);
break;
}
softpipe->active_query_count++;
softpipe->dirty |= SP_NEW_QUERY;
}
 
 
static void
softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
{
struct softpipe_context *softpipe = softpipe_context( pipe );
struct softpipe_query *sq = softpipe_query(q);
 
softpipe->active_query_count--;
switch (sq->type) {
case PIPE_QUERY_OCCLUSION_COUNTER:
case PIPE_QUERY_OCCLUSION_PREDICATE:
sq->end = softpipe->occlusion_count;
break;
case PIPE_QUERY_TIMESTAMP:
sq->start = 0;
/* fall through */
case PIPE_QUERY_TIME_ELAPSED:
sq->end = os_time_get_nano();
break;
case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
sq->end = (softpipe->num_primitives_generated >
softpipe->so_stats.num_primitives_written);
break;
case PIPE_QUERY_SO_STATISTICS:
sq->num_primitives_generated =
softpipe->num_primitives_generated;
sq->so.num_primitives_written =
softpipe->so_stats.num_primitives_written;
break;
case PIPE_QUERY_PRIMITIVES_EMITTED:
sq->so.num_primitives_written =
softpipe->so_stats.num_primitives_written;
break;
case PIPE_QUERY_PRIMITIVES_GENERATED:
sq->num_primitives_generated = softpipe->num_primitives_generated;
break;
case PIPE_QUERY_GPU_FINISHED:
case PIPE_QUERY_TIMESTAMP_DISJOINT:
break;
case PIPE_QUERY_PIPELINE_STATISTICS:
sq->stats.ia_vertices =
softpipe->pipeline_statistics.ia_vertices - sq->stats.ia_vertices;
sq->stats.ia_primitives =
softpipe->pipeline_statistics.ia_primitives - sq->stats.ia_primitives;
sq->stats.vs_invocations =
softpipe->pipeline_statistics.vs_invocations - sq->stats.vs_invocations;
sq->stats.gs_invocations =
softpipe->pipeline_statistics.gs_invocations - sq->stats.gs_invocations;
sq->stats.gs_primitives =
softpipe->pipeline_statistics.gs_primitives - sq->stats.gs_primitives;
sq->stats.c_invocations =
softpipe->pipeline_statistics.c_invocations - sq->stats.c_invocations;
sq->stats.c_primitives =
softpipe->pipeline_statistics.c_primitives - sq->stats.c_primitives;
sq->stats.ps_invocations =
softpipe->pipeline_statistics.ps_invocations - sq->stats.ps_invocations;
 
softpipe->active_statistics_queries--;
break;
default:
assert(0);
break;
}
softpipe->dirty |= SP_NEW_QUERY;
}
 
 
static boolean
softpipe_get_query_result(struct pipe_context *pipe,
struct pipe_query *q,
boolean wait,
union pipe_query_result *vresult)
{
struct softpipe_query *sq = softpipe_query(q);
uint64_t *result = (uint64_t*)vresult;
 
switch (sq->type) {
case PIPE_QUERY_SO_STATISTICS: {
struct pipe_query_data_so_statistics *stats =
(struct pipe_query_data_so_statistics *)vresult;
stats->num_primitives_written = sq->so.num_primitives_written;
stats->primitives_storage_needed = sq->num_primitives_generated;
}
break;
case PIPE_QUERY_PIPELINE_STATISTICS:
memcpy(vresult, &sq->stats,
sizeof(struct pipe_query_data_pipeline_statistics));;
break;
case PIPE_QUERY_GPU_FINISHED:
vresult->b = TRUE;
break;
case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
vresult->b = sq->end != 0;
break;
case PIPE_QUERY_TIMESTAMP_DISJOINT: {
struct pipe_query_data_timestamp_disjoint *td =
(struct pipe_query_data_timestamp_disjoint *)vresult;
/* os_get_time_nano return nanoseconds */
td->frequency = UINT64_C(1000000000);
td->disjoint = FALSE;
}
break;
case PIPE_QUERY_PRIMITIVES_EMITTED:
*result = sq->so.num_primitives_written;
break;
case PIPE_QUERY_PRIMITIVES_GENERATED:
*result = sq->num_primitives_generated;
break;
case PIPE_QUERY_OCCLUSION_PREDICATE:
vresult->b = sq->end - sq->start != 0;
break;
default:
*result = sq->end - sq->start;
break;
}
return TRUE;
}
 
 
/**
* Called by rendering function to check rendering is conditional.
* \return TRUE if we should render, FALSE if we should skip rendering
*/
boolean
softpipe_check_render_cond(struct softpipe_context *sp)
{
struct pipe_context *pipe = &sp->pipe;
boolean b, wait;
uint64_t result;
 
if (!sp->render_cond_query) {
return TRUE; /* no query predicate, draw normally */
}
 
wait = (sp->render_cond_mode == PIPE_RENDER_COND_WAIT ||
sp->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT);
 
b = pipe->get_query_result(pipe, sp->render_cond_query, wait,
(void*)&result);
if (b)
return (!result == sp->render_cond_cond);
else
return TRUE;
}
 
 
void softpipe_init_query_funcs(struct softpipe_context *softpipe )
{
softpipe->pipe.create_query = softpipe_create_query;
softpipe->pipe.destroy_query = softpipe_destroy_query;
softpipe->pipe.begin_query = softpipe_begin_query;
softpipe->pipe.end_query = softpipe_end_query;
softpipe->pipe.get_query_result = softpipe_get_query_result;
}
 
 
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_query.h
0,0 → 1,43
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Author:
* Keith Whitwell
*/
 
#ifndef SP_QUERY_H
#define SP_QUERY_H
 
extern boolean
softpipe_check_render_cond(struct softpipe_context *sp);
 
 
struct softpipe_context;
extern void softpipe_init_query_funcs(struct softpipe_context * );
 
 
#endif /* SP_QUERY_H */
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_screen.c
0,0 → 1,420
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
 
#include "util/u_memory.h"
#include "util/u_format.h"
#include "util/u_format_s3tc.h"
#include "util/u_video.h"
#include "os/os_time.h"
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "draw/draw_context.h"
#include "vl/vl_decoder.h"
#include "vl/vl_video_buffer.h"
 
#include "state_tracker/sw_winsys.h"
#include "tgsi/tgsi_exec.h"
 
#include "sp_texture.h"
#include "sp_screen.h"
#include "sp_context.h"
#include "sp_fence.h"
#include "sp_public.h"
 
DEBUG_GET_ONCE_BOOL_OPTION(use_llvm, "SOFTPIPE_USE_LLVM", FALSE)
 
static const char *
softpipe_get_vendor(struct pipe_screen *screen)
{
return "VMware, Inc.";
}
 
 
static const char *
softpipe_get_name(struct pipe_screen *screen)
{
return "softpipe";
}
 
 
static int
softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
{
switch (param) {
case PIPE_CAP_MAX_COMBINED_SAMPLERS:
return 2 * PIPE_MAX_SAMPLERS; /* VS + FS */
case PIPE_CAP_NPOT_TEXTURES:
return 1;
case PIPE_CAP_TWO_SIDED_STENCIL:
return 1;
case PIPE_CAP_SM3:
return 1;
case PIPE_CAP_ANISOTROPIC_FILTER:
return 1;
case PIPE_CAP_POINT_SPRITE:
return 1;
case PIPE_CAP_MAX_RENDER_TARGETS:
return PIPE_MAX_COLOR_BUFS;
case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
return 1;
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
case PIPE_CAP_QUERY_TIME_ELAPSED:
return 1;
case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
return 1;
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
return 1;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 1;
case PIPE_CAP_TEXTURE_SWIZZLE:
return 1;
case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
return 0;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
return SP_MAX_TEXTURE_2D_LEVELS;
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
return SP_MAX_TEXTURE_3D_LEVELS;
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
return SP_MAX_TEXTURE_CUBE_LEVELS;
case PIPE_CAP_BLEND_EQUATION_SEPARATE:
return 1;
case PIPE_CAP_INDEP_BLEND_ENABLE:
return 1;
case PIPE_CAP_INDEP_BLEND_FUNC:
return 1;
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
return 1;
case PIPE_CAP_DEPTH_CLIP_DISABLE:
return 0;
case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
return PIPE_MAX_SO_BUFFERS;
case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
return 16*4;
case PIPE_CAP_PRIMITIVE_RESTART:
return 1;
case PIPE_CAP_SHADER_STENCIL_EXPORT:
return 1;
case PIPE_CAP_TGSI_INSTANCEID:
case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
return 1;
case PIPE_CAP_SEAMLESS_CUBE_MAP:
case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
return 1;
case PIPE_CAP_SCALED_RESOLVE:
return 0;
case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
return 256; /* for GL3 */
case PIPE_CAP_MIN_TEXEL_OFFSET:
return -8;
case PIPE_CAP_MAX_TEXEL_OFFSET:
return 7;
case PIPE_CAP_CONDITIONAL_RENDER:
return 1;
case PIPE_CAP_TEXTURE_BARRIER:
return 0;
case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: /* draw module */
case PIPE_CAP_VERTEX_COLOR_CLAMPED: /* draw module */
return 1;
case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
return 0;
case PIPE_CAP_GLSL_FEATURE_LEVEL:
return 140;
case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
return 0;
case PIPE_CAP_COMPUTE:
return 0;
case PIPE_CAP_USER_VERTEX_BUFFERS:
case PIPE_CAP_USER_INDEX_BUFFERS:
case PIPE_CAP_USER_CONSTANT_BUFFERS:
case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
return 1;
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
return 16;
case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_START_INSTANCE:
case PIPE_CAP_TEXTURE_MULTISAMPLE:
case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
return 0;
case PIPE_CAP_QUERY_TIMESTAMP:
case PIPE_CAP_CUBE_MAP_ARRAY:
return 1;
case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
return 1;
case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
return 65536;
case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
return 0;
case PIPE_CAP_TGSI_TEXCOORD:
case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
return 0;
case PIPE_CAP_MAX_VIEWPORTS:
return 1;
case PIPE_CAP_ENDIANNESS:
return PIPE_ENDIAN_NATIVE;
}
/* should only get here on unhandled cases */
debug_printf("Unexpected PIPE_CAP %d query\n", param);
return 0;
}
 
static int
softpipe_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap param)
{
struct softpipe_screen *sp_screen = softpipe_screen(screen);
switch(shader)
{
case PIPE_SHADER_FRAGMENT:
return tgsi_exec_get_shader_param(param);
case PIPE_SHADER_VERTEX:
case PIPE_SHADER_GEOMETRY:
switch (param) {
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
if (sp_screen->use_llvm)
/* Softpipe doesn't yet know how to tell draw/llvm about textures */
return 0;
else
return PIPE_MAX_SAMPLERS;
default:
if (sp_screen->use_llvm)
return draw_get_shader_param(shader, param);
else
return draw_get_shader_param_no_llvm(shader, param);
}
default:
return 0;
}
}
 
static float
softpipe_get_paramf(struct pipe_screen *screen, enum pipe_capf param)
{
switch (param) {
case PIPE_CAPF_MAX_LINE_WIDTH:
/* fall-through */
case PIPE_CAPF_MAX_LINE_WIDTH_AA:
return 255.0; /* arbitrary */
case PIPE_CAPF_MAX_POINT_WIDTH:
/* fall-through */
case PIPE_CAPF_MAX_POINT_WIDTH_AA:
return 255.0; /* arbitrary */
case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
return 16.0;
case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
return 16.0; /* arbitrary */
case PIPE_CAPF_GUARD_BAND_LEFT:
case PIPE_CAPF_GUARD_BAND_TOP:
case PIPE_CAPF_GUARD_BAND_RIGHT:
case PIPE_CAPF_GUARD_BAND_BOTTOM:
return 0.0;
}
/* should only get here on unhandled cases */
debug_printf("Unexpected PIPE_CAPF %d query\n", param);
return 0.0;
}
 
static int
softpipe_get_video_param(struct pipe_screen *screen,
enum pipe_video_profile profile,
enum pipe_video_cap param)
{
switch (param) {
case PIPE_VIDEO_CAP_SUPPORTED:
return vl_profile_supported(screen, profile);
case PIPE_VIDEO_CAP_NPOT_TEXTURES:
return 0;
case PIPE_VIDEO_CAP_MAX_WIDTH:
case PIPE_VIDEO_CAP_MAX_HEIGHT:
return vl_video_buffer_max_size(screen);
case PIPE_VIDEO_CAP_PREFERED_FORMAT:
return PIPE_FORMAT_NV12;
case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
return false;
case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
return false;
case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
return true;
default:
return 0;
}
}
 
/**
* Query format support for creating a texture, drawing surface, etc.
* \param format the format to test
* \param type one of PIPE_TEXTURE, PIPE_SURFACE
*/
static boolean
softpipe_is_format_supported( struct pipe_screen *screen,
enum pipe_format format,
enum pipe_texture_target target,
unsigned sample_count,
unsigned bind)
{
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
const struct util_format_description *format_desc;
 
assert(target == PIPE_BUFFER ||
target == PIPE_TEXTURE_1D ||
target == PIPE_TEXTURE_1D_ARRAY ||
target == PIPE_TEXTURE_2D ||
target == PIPE_TEXTURE_2D_ARRAY ||
target == PIPE_TEXTURE_RECT ||
target == PIPE_TEXTURE_3D ||
target == PIPE_TEXTURE_CUBE ||
target == PIPE_TEXTURE_CUBE_ARRAY);
 
format_desc = util_format_description(format);
if (!format_desc)
return FALSE;
 
if (sample_count > 1)
return FALSE;
 
if (bind & (PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT |
PIPE_BIND_SHARED)) {
if(!winsys->is_displaytarget_format_supported(winsys, bind, format))
return FALSE;
}
 
if (bind & PIPE_BIND_RENDER_TARGET) {
if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
return FALSE;
 
/*
* Although possible, it is unnatural to render into compressed or YUV
* surfaces. So disable these here to avoid going into weird paths
* inside the state trackers.
*/
if (format_desc->block.width != 1 ||
format_desc->block.height != 1)
return FALSE;
}
 
if (bind & PIPE_BIND_DEPTH_STENCIL) {
if (format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
return FALSE;
}
 
/*
* All other operations (sampling, transfer, etc).
*/
 
if (format_desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
return util_format_s3tc_enabled;
}
 
/*
* Everything else should be supported by u_format.
*/
return TRUE;
}
 
 
static void
softpipe_destroy_screen( struct pipe_screen *screen )
{
struct softpipe_screen *sp_screen = softpipe_screen(screen);
struct sw_winsys *winsys = sp_screen->winsys;
 
if(winsys->destroy)
winsys->destroy(winsys);
 
FREE(screen);
}
 
 
/* This is often overriden by the co-state tracker.
*/
static void
softpipe_flush_frontbuffer(struct pipe_screen *_screen,
struct pipe_resource *resource,
unsigned level, unsigned layer,
void *context_private)
{
struct softpipe_screen *screen = softpipe_screen(_screen);
struct sw_winsys *winsys = screen->winsys;
struct softpipe_resource *texture = softpipe_resource(resource);
 
assert(texture->dt);
if (texture->dt)
winsys->displaytarget_display(winsys, texture->dt, context_private);
}
 
static uint64_t
softpipe_get_timestamp(struct pipe_screen *_screen)
{
return os_time_get_nano();
}
 
/**
* Create a new pipe_screen object
* Note: we're not presently subclassing pipe_screen (no softpipe_screen).
*/
struct pipe_screen *
softpipe_create_screen(struct sw_winsys *winsys)
{
struct softpipe_screen *screen = CALLOC_STRUCT(softpipe_screen);
 
if (!screen)
return NULL;
 
screen->winsys = winsys;
 
screen->base.destroy = softpipe_destroy_screen;
 
screen->base.get_name = softpipe_get_name;
screen->base.get_vendor = softpipe_get_vendor;
screen->base.get_param = softpipe_get_param;
screen->base.get_shader_param = softpipe_get_shader_param;
screen->base.get_paramf = softpipe_get_paramf;
screen->base.get_video_param = softpipe_get_video_param;
screen->base.get_timestamp = softpipe_get_timestamp;
screen->base.is_format_supported = softpipe_is_format_supported;
screen->base.is_video_format_supported = vl_video_buffer_is_format_supported;
screen->base.context_create = softpipe_create_context;
screen->base.flush_frontbuffer = softpipe_flush_frontbuffer;
 
screen->use_llvm = debug_get_option_use_llvm();
 
util_format_s3tc_init();
 
softpipe_init_screen_texture_funcs(&screen->base);
softpipe_init_screen_fence_funcs(&screen->base);
 
return &screen->base;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_screen.h
0,0 → 1,60
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_SCREEN_H
#define SP_SCREEN_H
 
#include "pipe/p_screen.h"
#include "pipe/p_defines.h"
 
 
struct sw_winsys;
 
struct softpipe_screen {
struct pipe_screen base;
 
struct sw_winsys *winsys;
 
/* Increments whenever textures are modified. Contexts can track
* this.
*/
unsigned timestamp;
boolean use_llvm;
};
 
static INLINE struct softpipe_screen *
softpipe_screen( struct pipe_screen *pipe )
{
return (struct softpipe_screen *)pipe;
}
 
 
 
#endif /* SP_SCREEN_H */
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_setup.c
0,0 → 1,1459
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/**
* \brief Primitive rasterization/rendering (points, lines, triangles)
*
* \author Keith Whitwell <keith@tungstengraphics.com>
* \author Brian Paul
*/
 
#include "sp_context.h"
#include "sp_quad.h"
#include "sp_quad_pipe.h"
#include "sp_setup.h"
#include "sp_state.h"
#include "draw/draw_context.h"
#include "draw/draw_vertex.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_math.h"
#include "util/u_memory.h"
 
 
#define DEBUG_VERTS 0
#define DEBUG_FRAGS 0
 
 
/**
* Triangle edge info
*/
struct edge {
float dx; /**< X(v1) - X(v0), used only during setup */
float dy; /**< Y(v1) - Y(v0), used only during setup */
float dxdy; /**< dx/dy */
float sx, sy; /**< first sample point coord */
int lines; /**< number of lines on this edge */
};
 
 
/**
* Max number of quads (2x2 pixel blocks) to process per batch.
* This can't be arbitrarily increased since we depend on some 32-bit
* bitmasks (two bits per quad).
*/
#define MAX_QUADS 16
 
 
/**
* Triangle setup info.
* Also used for line drawing (taking some liberties).
*/
struct setup_context {
struct softpipe_context *softpipe;
 
/* Vertices are just an array of floats making up each attribute in
* turn. Currently fixed at 4 floats, but should change in time.
* Codegen will help cope with this.
*/
const float (*vmax)[4];
const float (*vmid)[4];
const float (*vmin)[4];
const float (*vprovoke)[4];
 
struct edge ebot;
struct edge etop;
struct edge emaj;
 
float oneoverarea;
int facing;
 
float pixel_offset;
 
struct quad_header quad[MAX_QUADS];
struct quad_header *quad_ptrs[MAX_QUADS];
unsigned count;
 
struct tgsi_interp_coef coef[PIPE_MAX_SHADER_INPUTS];
struct tgsi_interp_coef posCoef; /* For Z, W */
 
struct {
int left[2]; /**< [0] = row0, [1] = row1 */
int right[2];
int y;
} span;
 
#if DEBUG_FRAGS
uint numFragsEmitted; /**< per primitive */
uint numFragsWritten; /**< per primitive */
#endif
 
unsigned cull_face; /* which faces cull */
unsigned nr_vertex_attrs;
};
 
 
 
 
 
 
 
/**
* Clip setup->quad against the scissor/surface bounds.
*/
static INLINE void
quad_clip(struct setup_context *setup, struct quad_header *quad)
{
const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
const int minx = (int) cliprect->minx;
const int maxx = (int) cliprect->maxx;
const int miny = (int) cliprect->miny;
const int maxy = (int) cliprect->maxy;
 
if (quad->input.x0 >= maxx ||
quad->input.y0 >= maxy ||
quad->input.x0 + 1 < minx ||
quad->input.y0 + 1 < miny) {
/* totally clipped */
quad->inout.mask = 0x0;
return;
}
if (quad->input.x0 < minx)
quad->inout.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
if (quad->input.y0 < miny)
quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
if (quad->input.x0 == maxx - 1)
quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
if (quad->input.y0 == maxy - 1)
quad->inout.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
}
 
 
/**
* Emit a quad (pass to next stage) with clipping.
*/
static INLINE void
clip_emit_quad(struct setup_context *setup, struct quad_header *quad)
{
quad_clip( setup, quad );
 
if (quad->inout.mask) {
struct softpipe_context *sp = setup->softpipe;
 
#if DEBUG_FRAGS
setup->numFragsEmitted += util_bitcount(quad->inout.mask);
#endif
 
sp->quad.first->run( sp->quad.first, &quad, 1 );
}
}
 
 
 
/**
* Given an X or Y coordinate, return the block/quad coordinate that it
* belongs to.
*/
static INLINE int
block(int x)
{
return x & ~(2-1);
}
 
 
static INLINE int
block_x(int x)
{
return x & ~(16-1);
}
 
 
/**
* Render a horizontal span of quads
*/
static void
flush_spans(struct setup_context *setup)
{
const int step = MAX_QUADS;
const int xleft0 = setup->span.left[0];
const int xleft1 = setup->span.left[1];
const int xright0 = setup->span.right[0];
const int xright1 = setup->span.right[1];
struct quad_stage *pipe = setup->softpipe->quad.first;
 
const int minleft = block_x(MIN2(xleft0, xleft1));
const int maxright = MAX2(xright0, xright1);
int x;
 
/* process quads in horizontal chunks of 16 */
for (x = minleft; x < maxright; x += step) {
unsigned skip_left0 = CLAMP(xleft0 - x, 0, step);
unsigned skip_left1 = CLAMP(xleft1 - x, 0, step);
unsigned skip_right0 = CLAMP(x + step - xright0, 0, step);
unsigned skip_right1 = CLAMP(x + step - xright1, 0, step);
unsigned lx = x;
unsigned q = 0;
 
unsigned skipmask_left0 = (1U << skip_left0) - 1U;
unsigned skipmask_left1 = (1U << skip_left1) - 1U;
 
/* These calculations fail when step == 32 and skip_right == 0.
*/
unsigned skipmask_right0 = ~0U << (unsigned)(step - skip_right0);
unsigned skipmask_right1 = ~0U << (unsigned)(step - skip_right1);
 
unsigned mask0 = ~skipmask_left0 & ~skipmask_right0;
unsigned mask1 = ~skipmask_left1 & ~skipmask_right1;
 
if (mask0 | mask1) {
do {
unsigned quadmask = (mask0 & 3) | ((mask1 & 3) << 2);
if (quadmask) {
setup->quad[q].input.x0 = lx;
setup->quad[q].input.y0 = setup->span.y;
setup->quad[q].input.facing = setup->facing;
setup->quad[q].inout.mask = quadmask;
setup->quad_ptrs[q] = &setup->quad[q];
q++;
#if DEBUG_FRAGS
setup->numFragsEmitted += util_bitcount(quadmask);
#endif
}
mask0 >>= 2;
mask1 >>= 2;
lx += 2;
} while (mask0 | mask1);
 
pipe->run( pipe, setup->quad_ptrs, q );
}
}
 
 
setup->span.y = 0;
setup->span.right[0] = 0;
setup->span.right[1] = 0;
setup->span.left[0] = 1000000; /* greater than right[0] */
setup->span.left[1] = 1000000; /* greater than right[1] */
}
 
 
#if DEBUG_VERTS
static void
print_vertex(const struct setup_context *setup,
const float (*v)[4])
{
int i;
debug_printf(" Vertex: (%p)\n", (void *) v);
for (i = 0; i < setup->nr_vertex_attrs; i++) {
debug_printf(" %d: %f %f %f %f\n", i,
v[i][0], v[i][1], v[i][2], v[i][3]);
if (util_is_inf_or_nan(v[i][0])) {
debug_printf(" NaN!\n");
}
}
}
#endif
 
 
/**
* Sort the vertices from top to bottom order, setting up the triangle
* edge fields (ebot, emaj, etop).
* \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise
*/
static boolean
setup_sort_vertices(struct setup_context *setup,
float det,
const float (*v0)[4],
const float (*v1)[4],
const float (*v2)[4])
{
if (setup->softpipe->rasterizer->flatshade_first)
setup->vprovoke = v0;
else
setup->vprovoke = v2;
 
/* determine bottom to top order of vertices */
{
float y0 = v0[0][1];
float y1 = v1[0][1];
float y2 = v2[0][1];
if (y0 <= y1) {
if (y1 <= y2) {
/* y0<=y1<=y2 */
setup->vmin = v0;
setup->vmid = v1;
setup->vmax = v2;
}
else if (y2 <= y0) {
/* y2<=y0<=y1 */
setup->vmin = v2;
setup->vmid = v0;
setup->vmax = v1;
}
else {
/* y0<=y2<=y1 */
setup->vmin = v0;
setup->vmid = v2;
setup->vmax = v1;
}
}
else {
if (y0 <= y2) {
/* y1<=y0<=y2 */
setup->vmin = v1;
setup->vmid = v0;
setup->vmax = v2;
}
else if (y2 <= y1) {
/* y2<=y1<=y0 */
setup->vmin = v2;
setup->vmid = v1;
setup->vmax = v0;
}
else {
/* y1<=y2<=y0 */
setup->vmin = v1;
setup->vmid = v2;
setup->vmax = v0;
}
}
}
 
setup->ebot.dx = setup->vmid[0][0] - setup->vmin[0][0];
setup->ebot.dy = setup->vmid[0][1] - setup->vmin[0][1];
setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
setup->etop.dx = setup->vmax[0][0] - setup->vmid[0][0];
setup->etop.dy = setup->vmax[0][1] - setup->vmid[0][1];
 
/*
* Compute triangle's area. Use 1/area to compute partial
* derivatives of attributes later.
*
* The area will be the same as prim->det, but the sign may be
* different depending on how the vertices get sorted above.
*
* To determine whether the primitive is front or back facing we
* use the prim->det value because its sign is correct.
*/
{
const float area = (setup->emaj.dx * setup->ebot.dy -
setup->ebot.dx * setup->emaj.dy);
 
setup->oneoverarea = 1.0f / area;
 
/*
debug_printf("%s one-over-area %f area %f det %f\n",
__FUNCTION__, setup->oneoverarea, area, det );
*/
if (util_is_inf_or_nan(setup->oneoverarea))
return FALSE;
}
 
/* We need to know if this is a front or back-facing triangle for:
* - the GLSL gl_FrontFacing fragment attribute (bool)
* - two-sided stencil test
* 0 = front-facing, 1 = back-facing
*/
setup->facing =
((det < 0.0) ^
(setup->softpipe->rasterizer->front_ccw));
 
{
unsigned face = setup->facing == 0 ? PIPE_FACE_FRONT : PIPE_FACE_BACK;
 
if (face & setup->cull_face)
return FALSE;
}
 
 
/* Prepare pixel offset for rasterisation:
* - pixel center (0.5, 0.5) for GL, or
* - assume (0.0, 0.0) for other APIs.
*/
if (setup->softpipe->rasterizer->half_pixel_center) {
setup->pixel_offset = 0.5f;
} else {
setup->pixel_offset = 0.0f;
}
 
return TRUE;
}
 
 
/* Apply cylindrical wrapping to v0, v1, v2 coordinates, if enabled.
* Input coordinates must be in [0, 1] range, otherwise results are undefined.
* Some combinations of coordinates produce invalid results,
* but this behaviour is acceptable.
*/
static void
tri_apply_cylindrical_wrap(float v0,
float v1,
float v2,
uint cylindrical_wrap,
float output[3])
{
if (cylindrical_wrap) {
float delta;
 
delta = v1 - v0;
if (delta > 0.5f) {
v0 += 1.0f;
}
else if (delta < -0.5f) {
v1 += 1.0f;
}
 
delta = v2 - v1;
if (delta > 0.5f) {
v1 += 1.0f;
}
else if (delta < -0.5f) {
v2 += 1.0f;
}
 
delta = v0 - v2;
if (delta > 0.5f) {
v2 += 1.0f;
}
else if (delta < -0.5f) {
v0 += 1.0f;
}
}
 
output[0] = v0;
output[1] = v1;
output[2] = v2;
}
 
 
/**
* Compute a0 for a constant-valued coefficient (GL_FLAT shading).
* The value value comes from vertex[slot][i].
* The result will be put into setup->coef[slot].a0[i].
* \param slot which attribute slot
* \param i which component of the slot (0..3)
*/
static void
const_coeff(struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint vertSlot, uint i)
{
assert(i <= 3);
 
coef->dadx[i] = 0;
coef->dady[i] = 0;
 
/* need provoking vertex info!
*/
coef->a0[i] = setup->vprovoke[vertSlot][i];
}
 
 
/**
* Compute a0, dadx and dady for a linearly interpolated coefficient,
* for a triangle.
* v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
*/
static void
tri_linear_coeff(struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint i,
const float v[3])
{
float botda = v[1] - v[0];
float majda = v[2] - v[0];
float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
float dadx = a * setup->oneoverarea;
float dady = b * setup->oneoverarea;
 
assert(i <= 3);
 
coef->dadx[i] = dadx;
coef->dady[i] = dady;
 
/* calculate a0 as the value which would be sampled for the
* fragment at (0,0), taking into account that we want to sample at
* pixel centers, in other words (pixel_offset, pixel_offset).
*
* this is neat but unfortunately not a good way to do things for
* triangles with very large values of dadx or dady as it will
* result in the subtraction and re-addition from a0 of a very
* large number, which means we'll end up loosing a lot of the
* fractional bits and precision from a0. the way to fix this is
* to define a0 as the sample at a pixel center somewhere near vmin
* instead - i'll switch to this later.
*/
coef->a0[i] = (v[0] -
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
 
/*
debug_printf("attr[%d].%c: %f dx:%f dy:%f\n",
slot, "xyzw"[i],
setup->coef[slot].a0[i],
setup->coef[slot].dadx[i],
setup->coef[slot].dady[i]);
*/
}
 
 
/**
* Compute a0, dadx and dady for a perspective-corrected interpolant,
* for a triangle.
* We basically multiply the vertex value by 1/w before computing
* the plane coefficients (a0, dadx, dady).
* Later, when we compute the value at a particular fragment position we'll
* divide the interpolated value by the interpolated W at that fragment.
* v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
*/
static void
tri_persp_coeff(struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint i,
const float v[3])
{
/* premultiply by 1/w (v[0][3] is always W):
*/
float mina = v[0] * setup->vmin[0][3];
float mida = v[1] * setup->vmid[0][3];
float maxa = v[2] * setup->vmax[0][3];
float botda = mida - mina;
float majda = maxa - mina;
float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
float dadx = a * setup->oneoverarea;
float dady = b * setup->oneoverarea;
 
/*
debug_printf("tri persp %d,%d: %f %f %f\n", vertSlot, i,
setup->vmin[vertSlot][i],
setup->vmid[vertSlot][i],
setup->vmax[vertSlot][i]
);
*/
assert(i <= 3);
 
coef->dadx[i] = dadx;
coef->dady[i] = dady;
coef->a0[i] = (mina -
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
}
 
 
/**
* Special coefficient setup for gl_FragCoord.
* X and Y are trivial, though Y may have to be inverted for OpenGL.
* Z and W are copied from posCoef which should have already been computed.
* We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
*/
static void
setup_fragcoord_coeff(struct setup_context *setup, uint slot)
{
const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
 
/*X*/
setup->coef[slot].a0[0] = fsInfo->pixel_center_integer ? 0.0f : 0.5f;
setup->coef[slot].dadx[0] = 1.0f;
setup->coef[slot].dady[0] = 0.0f;
/*Y*/
setup->coef[slot].a0[1] =
(fsInfo->origin_lower_left ? setup->softpipe->framebuffer.height-1 : 0)
+ (fsInfo->pixel_center_integer ? 0.0f : 0.5f);
setup->coef[slot].dadx[1] = 0.0f;
setup->coef[slot].dady[1] = fsInfo->origin_lower_left ? -1.0f : 1.0f;
/*Z*/
setup->coef[slot].a0[2] = setup->posCoef.a0[2];
setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];
setup->coef[slot].dady[2] = setup->posCoef.dady[2];
/*W*/
setup->coef[slot].a0[3] = setup->posCoef.a0[3];
setup->coef[slot].dadx[3] = setup->posCoef.dadx[3];
setup->coef[slot].dady[3] = setup->posCoef.dady[3];
}
 
 
 
/**
* Compute the setup->coef[] array dadx, dady, a0 values.
* Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
*/
static void
setup_tri_coefficients(struct setup_context *setup)
{
struct softpipe_context *softpipe = setup->softpipe;
const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot;
float v[3];
 
/* z and w are done by linear interpolation:
*/
v[0] = setup->vmin[0][2];
v[1] = setup->vmid[0][2];
v[2] = setup->vmax[0][2];
tri_linear_coeff(setup, &setup->posCoef, 2, v);
 
v[0] = setup->vmin[0][3];
v[1] = setup->vmid[0][3];
v[2] = setup->vmax[0][3];
tri_linear_coeff(setup, &setup->posCoef, 3, v);
 
/* setup interpolation for all the remaining attributes:
*/
for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
const uint vertSlot = vinfo->attrib[fragSlot].src_index;
uint j;
 
switch (vinfo->attrib[fragSlot].interp_mode) {
case INTERP_CONSTANT:
for (j = 0; j < TGSI_NUM_CHANNELS; j++)
const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
break;
case INTERP_LINEAR:
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmid[vertSlot][j],
setup->vmax[vertSlot][j],
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v);
tri_linear_coeff(setup, &setup->coef[fragSlot], j, v);
}
break;
case INTERP_PERSPECTIVE:
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmid[vertSlot][j],
setup->vmax[vertSlot][j],
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v);
tri_persp_coeff(setup, &setup->coef[fragSlot], j, v);
}
break;
case INTERP_POS:
setup_fragcoord_coeff(setup, fragSlot);
break;
default:
assert(0);
}
 
if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
/* convert 0 to 1.0 and 1 to -1.0 */
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0;
setup->coef[fragSlot].dady[0] = 0.0;
}
}
}
 
 
static void
setup_tri_edges(struct setup_context *setup)
{
float vmin_x = setup->vmin[0][0] + setup->pixel_offset;
float vmid_x = setup->vmid[0][0] + setup->pixel_offset;
 
float vmin_y = setup->vmin[0][1] - setup->pixel_offset;
float vmid_y = setup->vmid[0][1] - setup->pixel_offset;
float vmax_y = setup->vmax[0][1] - setup->pixel_offset;
 
setup->emaj.sy = ceilf(vmin_y);
setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy);
setup->emaj.dxdy = setup->emaj.dy ? setup->emaj.dx / setup->emaj.dy : .0f;
setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy;
 
setup->etop.sy = ceilf(vmid_y);
setup->etop.lines = (int) ceilf(vmax_y - setup->etop.sy);
setup->etop.dxdy = setup->etop.dy ? setup->etop.dx / setup->etop.dy : .0f;
setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy;
 
setup->ebot.sy = ceilf(vmin_y);
setup->ebot.lines = (int) ceilf(vmid_y - setup->ebot.sy);
setup->ebot.dxdy = setup->ebot.dy ? setup->ebot.dx / setup->ebot.dy : .0f;
setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy;
}
 
 
/**
* Render the upper or lower half of a triangle.
* Scissoring/cliprect is applied here too.
*/
static void
subtriangle(struct setup_context *setup,
struct edge *eleft,
struct edge *eright,
int lines)
{
const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
const int minx = (int) cliprect->minx;
const int maxx = (int) cliprect->maxx;
const int miny = (int) cliprect->miny;
const int maxy = (int) cliprect->maxy;
int y, start_y, finish_y;
int sy = (int)eleft->sy;
 
assert((int)eleft->sy == (int) eright->sy);
assert(lines >= 0);
 
/* clip top/bottom */
start_y = sy;
if (start_y < miny)
start_y = miny;
 
finish_y = sy + lines;
if (finish_y > maxy)
finish_y = maxy;
 
start_y -= sy;
finish_y -= sy;
 
/*
debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
*/
 
for (y = start_y; y < finish_y; y++) {
 
/* avoid accumulating adds as floats don't have the precision to
* accurately iterate large triangle edges that way. luckily we
* can just multiply these days.
*
* this is all drowned out by the attribute interpolation anyway.
*/
int left = (int)(eleft->sx + y * eleft->dxdy);
int right = (int)(eright->sx + y * eright->dxdy);
 
/* clip left/right */
if (left < minx)
left = minx;
if (right > maxx)
right = maxx;
 
if (left < right) {
int _y = sy + y;
if (block(_y) != setup->span.y) {
flush_spans(setup);
setup->span.y = block(_y);
}
 
setup->span.left[_y&1] = left;
setup->span.right[_y&1] = right;
}
}
 
 
/* save the values so that emaj can be restarted:
*/
eleft->sx += lines * eleft->dxdy;
eright->sx += lines * eright->dxdy;
eleft->sy += lines;
eright->sy += lines;
}
 
 
/**
* Recalculate prim's determinant. This is needed as we don't have
* get this information through the vbuf_render interface & we must
* calculate it here.
*/
static float
calc_det(const float (*v0)[4],
const float (*v1)[4],
const float (*v2)[4])
{
/* edge vectors e = v0 - v2, f = v1 - v2 */
const float ex = v0[0][0] - v2[0][0];
const float ey = v0[0][1] - v2[0][1];
const float fx = v1[0][0] - v2[0][0];
const float fy = v1[0][1] - v2[0][1];
 
/* det = cross(e,f).z */
return ex * fy - ey * fx;
}
 
 
/**
* Do setup for triangle rasterization, then render the triangle.
*/
void
sp_setup_tri(struct setup_context *setup,
const float (*v0)[4],
const float (*v1)[4],
const float (*v2)[4])
{
float det;
 
#if DEBUG_VERTS
debug_printf("Setup triangle:\n");
print_vertex(setup, v0);
print_vertex(setup, v1);
print_vertex(setup, v2);
#endif
 
if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
return;
det = calc_det(v0, v1, v2);
/*
debug_printf("%s\n", __FUNCTION__ );
*/
 
#if DEBUG_FRAGS
setup->numFragsEmitted = 0;
setup->numFragsWritten = 0;
#endif
 
if (!setup_sort_vertices( setup, det, v0, v1, v2 ))
return;
 
setup_tri_coefficients( setup );
setup_tri_edges( setup );
 
assert(setup->softpipe->reduced_prim == PIPE_PRIM_TRIANGLES);
 
setup->span.y = 0;
setup->span.right[0] = 0;
setup->span.right[1] = 0;
/* setup->span.z_mode = tri_z_mode( setup->ctx ); */
 
/* init_constant_attribs( setup ); */
 
if (setup->oneoverarea < 0.0) {
/* emaj on left:
*/
subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines );
subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines );
}
else {
/* emaj on right:
*/
subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines );
subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines );
}
 
flush_spans( setup );
 
if (setup->softpipe->active_statistics_queries) {
setup->softpipe->pipeline_statistics.c_primitives++;
}
 
#if DEBUG_FRAGS
printf("Tri: %u frags emitted, %u written\n",
setup->numFragsEmitted,
setup->numFragsWritten);
#endif
}
 
 
/* Apply cylindrical wrapping to v0, v1 coordinates, if enabled.
* Input coordinates must be in [0, 1] range, otherwise results are undefined.
*/
static void
line_apply_cylindrical_wrap(float v0,
float v1,
uint cylindrical_wrap,
float output[2])
{
if (cylindrical_wrap) {
float delta;
 
delta = v1 - v0;
if (delta > 0.5f) {
v0 += 1.0f;
}
else if (delta < -0.5f) {
v1 += 1.0f;
}
}
 
output[0] = v0;
output[1] = v1;
}
 
 
/**
* Compute a0, dadx and dady for a linearly interpolated coefficient,
* for a line.
* v[0] and v[1] are vmin and vmax, respectively.
*/
static void
line_linear_coeff(const struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint i,
const float v[2])
{
const float da = v[1] - v[0];
const float dadx = da * setup->emaj.dx * setup->oneoverarea;
const float dady = da * setup->emaj.dy * setup->oneoverarea;
coef->dadx[i] = dadx;
coef->dady[i] = dady;
coef->a0[i] = (v[0] -
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
}
 
 
/**
* Compute a0, dadx and dady for a perspective-corrected interpolant,
* for a line.
* v[0] and v[1] are vmin and vmax, respectively.
*/
static void
line_persp_coeff(const struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint i,
const float v[2])
{
const float a0 = v[0] * setup->vmin[0][3];
const float a1 = v[1] * setup->vmax[0][3];
const float da = a1 - a0;
const float dadx = da * setup->emaj.dx * setup->oneoverarea;
const float dady = da * setup->emaj.dy * setup->oneoverarea;
coef->dadx[i] = dadx;
coef->dady[i] = dady;
coef->a0[i] = (a0 -
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
}
 
 
/**
* Compute the setup->coef[] array dadx, dady, a0 values.
* Must be called after setup->vmin,vmax are initialized.
*/
static boolean
setup_line_coefficients(struct setup_context *setup,
const float (*v0)[4],
const float (*v1)[4])
{
struct softpipe_context *softpipe = setup->softpipe;
const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot;
float area;
float v[2];
 
/* use setup->vmin, vmax to point to vertices */
if (softpipe->rasterizer->flatshade_first)
setup->vprovoke = v0;
else
setup->vprovoke = v1;
setup->vmin = v0;
setup->vmax = v1;
 
setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
 
/* NOTE: this is not really area but something proportional to it */
area = setup->emaj.dx * setup->emaj.dx + setup->emaj.dy * setup->emaj.dy;
if (area == 0.0f || util_is_inf_or_nan(area))
return FALSE;
setup->oneoverarea = 1.0f / area;
 
/* z and w are done by linear interpolation:
*/
v[0] = setup->vmin[0][2];
v[1] = setup->vmax[0][2];
line_linear_coeff(setup, &setup->posCoef, 2, v);
 
v[0] = setup->vmin[0][3];
v[1] = setup->vmax[0][3];
line_linear_coeff(setup, &setup->posCoef, 3, v);
 
/* setup interpolation for all the remaining attributes:
*/
for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
const uint vertSlot = vinfo->attrib[fragSlot].src_index;
uint j;
 
switch (vinfo->attrib[fragSlot].interp_mode) {
case INTERP_CONSTANT:
for (j = 0; j < TGSI_NUM_CHANNELS; j++)
const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
break;
case INTERP_LINEAR:
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmax[vertSlot][j],
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v);
line_linear_coeff(setup, &setup->coef[fragSlot], j, v);
}
break;
case INTERP_PERSPECTIVE:
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmax[vertSlot][j],
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v);
line_persp_coeff(setup, &setup->coef[fragSlot], j, v);
}
break;
case INTERP_POS:
setup_fragcoord_coeff(setup, fragSlot);
break;
default:
assert(0);
}
 
if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
/* convert 0 to 1.0 and 1 to -1.0 */
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0;
setup->coef[fragSlot].dady[0] = 0.0;
}
}
return TRUE;
}
 
 
/**
* Plot a pixel in a line segment.
*/
static INLINE void
plot(struct setup_context *setup, int x, int y)
{
const int iy = y & 1;
const int ix = x & 1;
const int quadX = x - ix;
const int quadY = y - iy;
const int mask = (1 << ix) << (2 * iy);
 
if (quadX != setup->quad[0].input.x0 ||
quadY != setup->quad[0].input.y0)
{
/* flush prev quad, start new quad */
 
if (setup->quad[0].input.x0 != -1)
clip_emit_quad( setup, &setup->quad[0] );
 
setup->quad[0].input.x0 = quadX;
setup->quad[0].input.y0 = quadY;
setup->quad[0].inout.mask = 0x0;
}
 
setup->quad[0].inout.mask |= mask;
}
 
 
/**
* Do setup for line rasterization, then render the line.
* Single-pixel width, no stipple, etc. We rely on the 'draw' module
* to handle stippling and wide lines.
*/
void
sp_setup_line(struct setup_context *setup,
const float (*v0)[4],
const float (*v1)[4])
{
int x0 = (int) v0[0][0];
int x1 = (int) v1[0][0];
int y0 = (int) v0[0][1];
int y1 = (int) v1[0][1];
int dx = x1 - x0;
int dy = y1 - y0;
int xstep, ystep;
 
#if DEBUG_VERTS
debug_printf("Setup line:\n");
print_vertex(setup, v0);
print_vertex(setup, v1);
#endif
 
if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
return;
 
if (dx == 0 && dy == 0)
return;
 
if (!setup_line_coefficients(setup, v0, v1))
return;
 
assert(v0[0][0] < 1.0e9);
assert(v0[0][1] < 1.0e9);
assert(v1[0][0] < 1.0e9);
assert(v1[0][1] < 1.0e9);
 
if (dx < 0) {
dx = -dx; /* make positive */
xstep = -1;
}
else {
xstep = 1;
}
 
if (dy < 0) {
dy = -dy; /* make positive */
ystep = -1;
}
else {
ystep = 1;
}
 
assert(dx >= 0);
assert(dy >= 0);
assert(setup->softpipe->reduced_prim == PIPE_PRIM_LINES);
 
setup->quad[0].input.x0 = setup->quad[0].input.y0 = -1;
setup->quad[0].inout.mask = 0x0;
 
/* XXX temporary: set coverage to 1.0 so the line appears
* if AA mode happens to be enabled.
*/
setup->quad[0].input.coverage[0] =
setup->quad[0].input.coverage[1] =
setup->quad[0].input.coverage[2] =
setup->quad[0].input.coverage[3] = 1.0;
 
if (dx > dy) {
/*** X-major line ***/
int i;
const int errorInc = dy + dy;
int error = errorInc - dx;
const int errorDec = error - dx;
 
for (i = 0; i < dx; i++) {
plot(setup, x0, y0);
 
x0 += xstep;
if (error < 0) {
error += errorInc;
}
else {
error += errorDec;
y0 += ystep;
}
}
}
else {
/*** Y-major line ***/
int i;
const int errorInc = dx + dx;
int error = errorInc - dy;
const int errorDec = error - dy;
 
for (i = 0; i < dy; i++) {
plot(setup, x0, y0);
 
y0 += ystep;
if (error < 0) {
error += errorInc;
}
else {
error += errorDec;
x0 += xstep;
}
}
}
 
/* draw final quad */
if (setup->quad[0].inout.mask) {
clip_emit_quad( setup, &setup->quad[0] );
}
}
 
 
static void
point_persp_coeff(const struct setup_context *setup,
const float (*vert)[4],
struct tgsi_interp_coef *coef,
uint vertSlot, uint i)
{
assert(i <= 3);
coef->dadx[i] = 0.0F;
coef->dady[i] = 0.0F;
coef->a0[i] = vert[vertSlot][i] * vert[0][3];
}
 
 
/**
* Do setup for point rasterization, then render the point.
* Round or square points...
* XXX could optimize a lot for 1-pixel points.
*/
void
sp_setup_point(struct setup_context *setup,
const float (*v0)[4])
{
struct softpipe_context *softpipe = setup->softpipe;
const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
const int sizeAttr = setup->softpipe->psize_slot;
const float size
= sizeAttr > 0 ? v0[sizeAttr][0]
: setup->softpipe->rasterizer->point_size;
const float halfSize = 0.5F * size;
const boolean round = (boolean) setup->softpipe->rasterizer->point_smooth;
const float x = v0[0][0]; /* Note: data[0] is always position */
const float y = v0[0][1];
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot;
 
#if DEBUG_VERTS
debug_printf("Setup point:\n");
print_vertex(setup, v0);
#endif
 
if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
return;
 
assert(setup->softpipe->reduced_prim == PIPE_PRIM_POINTS);
 
/* For points, all interpolants are constant-valued.
* However, for point sprites, we'll need to setup texcoords appropriately.
* XXX: which coefficients are the texcoords???
* We may do point sprites as textured quads...
*
* KW: We don't know which coefficients are texcoords - ultimately
* the choice of what interpolation mode to use for each attribute
* should be determined by the fragment program, using
* per-attribute declaration statements that include interpolation
* mode as a parameter. So either the fragment program will have
* to be adjusted for pointsprite vs normal point behaviour, or
* otherwise a special interpolation mode will have to be defined
* which matches the required behaviour for point sprites. But -
* the latter is not a feature of normal hardware, and as such
* probably should be ruled out on that basis.
*/
setup->vprovoke = v0;
 
/* setup Z, W */
const_coeff(setup, &setup->posCoef, 0, 2);
const_coeff(setup, &setup->posCoef, 0, 3);
 
for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
const uint vertSlot = vinfo->attrib[fragSlot].src_index;
uint j;
 
switch (vinfo->attrib[fragSlot].interp_mode) {
case INTERP_CONSTANT:
/* fall-through */
case INTERP_LINEAR:
for (j = 0; j < TGSI_NUM_CHANNELS; j++)
const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
break;
case INTERP_PERSPECTIVE:
for (j = 0; j < TGSI_NUM_CHANNELS; j++)
point_persp_coeff(setup, setup->vprovoke,
&setup->coef[fragSlot], vertSlot, j);
break;
case INTERP_POS:
setup_fragcoord_coeff(setup, fragSlot);
break;
default:
assert(0);
}
 
if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
/* convert 0 to 1.0 and 1 to -1.0 */
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0;
setup->coef[fragSlot].dady[0] = 0.0;
}
}
 
 
if (halfSize <= 0.5 && !round) {
/* special case for 1-pixel points */
const int ix = ((int) x) & 1;
const int iy = ((int) y) & 1;
setup->quad[0].input.x0 = (int) x - ix;
setup->quad[0].input.y0 = (int) y - iy;
setup->quad[0].inout.mask = (1 << ix) << (2 * iy);
clip_emit_quad( setup, &setup->quad[0] );
}
else {
if (round) {
/* rounded points */
const int ixmin = block((int) (x - halfSize));
const int ixmax = block((int) (x + halfSize));
const int iymin = block((int) (y - halfSize));
const int iymax = block((int) (y + halfSize));
const float rmin = halfSize - 0.7071F; /* 0.7071 = sqrt(2)/2 */
const float rmax = halfSize + 0.7071F;
const float rmin2 = MAX2(0.0F, rmin * rmin);
const float rmax2 = rmax * rmax;
const float cscale = 1.0F / (rmax2 - rmin2);
int ix, iy;
 
for (iy = iymin; iy <= iymax; iy += 2) {
for (ix = ixmin; ix <= ixmax; ix += 2) {
float dx, dy, dist2, cover;
 
setup->quad[0].inout.mask = 0x0;
 
dx = (ix + 0.5f) - x;
dy = (iy + 0.5f) - y;
dist2 = dx * dx + dy * dy;
if (dist2 <= rmax2) {
cover = 1.0F - (dist2 - rmin2) * cscale;
setup->quad[0].input.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f);
setup->quad[0].inout.mask |= MASK_TOP_LEFT;
}
 
dx = (ix + 1.5f) - x;
dy = (iy + 0.5f) - y;
dist2 = dx * dx + dy * dy;
if (dist2 <= rmax2) {
cover = 1.0F - (dist2 - rmin2) * cscale;
setup->quad[0].input.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f);
setup->quad[0].inout.mask |= MASK_TOP_RIGHT;
}
 
dx = (ix + 0.5f) - x;
dy = (iy + 1.5f) - y;
dist2 = dx * dx + dy * dy;
if (dist2 <= rmax2) {
cover = 1.0F - (dist2 - rmin2) * cscale;
setup->quad[0].input.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f);
setup->quad[0].inout.mask |= MASK_BOTTOM_LEFT;
}
 
dx = (ix + 1.5f) - x;
dy = (iy + 1.5f) - y;
dist2 = dx * dx + dy * dy;
if (dist2 <= rmax2) {
cover = 1.0F - (dist2 - rmin2) * cscale;
setup->quad[0].input.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f);
setup->quad[0].inout.mask |= MASK_BOTTOM_RIGHT;
}
 
if (setup->quad[0].inout.mask) {
setup->quad[0].input.x0 = ix;
setup->quad[0].input.y0 = iy;
clip_emit_quad( setup, &setup->quad[0] );
}
}
}
}
else {
/* square points */
const int xmin = (int) (x + 0.75 - halfSize);
const int ymin = (int) (y + 0.25 - halfSize);
const int xmax = xmin + (int) size;
const int ymax = ymin + (int) size;
/* XXX could apply scissor to xmin,ymin,xmax,ymax now */
const int ixmin = block(xmin);
const int ixmax = block(xmax - 1);
const int iymin = block(ymin);
const int iymax = block(ymax - 1);
int ix, iy;
 
/*
debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax);
*/
for (iy = iymin; iy <= iymax; iy += 2) {
uint rowMask = 0xf;
if (iy < ymin) {
/* above the top edge */
rowMask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
}
if (iy + 1 >= ymax) {
/* below the bottom edge */
rowMask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
}
 
for (ix = ixmin; ix <= ixmax; ix += 2) {
uint mask = rowMask;
 
if (ix < xmin) {
/* fragment is past left edge of point, turn off left bits */
mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
}
if (ix + 1 >= xmax) {
/* past the right edge */
mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
}
 
setup->quad[0].inout.mask = mask;
setup->quad[0].input.x0 = ix;
setup->quad[0].input.y0 = iy;
clip_emit_quad( setup, &setup->quad[0] );
}
}
}
}
}
 
 
/**
* Called by vbuf code just before we start buffering primitives.
*/
void
sp_setup_prepare(struct setup_context *setup)
{
struct softpipe_context *sp = setup->softpipe;
 
if (sp->dirty) {
softpipe_update_derived(sp, sp->reduced_api_prim);
}
 
/* Note: nr_attrs is only used for debugging (vertex printing) */
setup->nr_vertex_attrs = draw_num_shader_outputs(sp->draw);
 
sp->quad.first->begin( sp->quad.first );
 
if (sp->reduced_api_prim == PIPE_PRIM_TRIANGLES &&
sp->rasterizer->fill_front == PIPE_POLYGON_MODE_FILL &&
sp->rasterizer->fill_back == PIPE_POLYGON_MODE_FILL) {
/* we'll do culling */
setup->cull_face = sp->rasterizer->cull_face;
}
else {
/* 'draw' will do culling */
setup->cull_face = PIPE_FACE_NONE;
}
}
 
 
void
sp_setup_destroy_context(struct setup_context *setup)
{
FREE( setup );
}
 
 
/**
* Create a new primitive setup/render stage.
*/
struct setup_context *
sp_setup_create_context(struct softpipe_context *softpipe)
{
struct setup_context *setup = CALLOC_STRUCT(setup_context);
unsigned i;
 
setup->softpipe = softpipe;
 
for (i = 0; i < MAX_QUADS; i++) {
setup->quad[i].coef = setup->coef;
setup->quad[i].posCoef = &setup->posCoef;
}
 
setup->span.left[0] = 1000000; /* greater than right[0] */
setup->span.left[1] = 1000000; /* greater than right[1] */
 
return setup;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_setup.h
0,0 → 1,53
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef SP_SETUP_H
#define SP_SETUP_H
 
struct setup_context;
struct softpipe_context;
 
void
sp_setup_tri( struct setup_context *setup,
const float (*v0)[4],
const float (*v1)[4],
const float (*v2)[4] );
 
void
sp_setup_line(struct setup_context *setup,
const float (*v0)[4],
const float (*v1)[4]);
 
void
sp_setup_point( struct setup_context *setup,
const float (*v0)[4] );
 
 
struct setup_context *sp_setup_create_context( struct softpipe_context *softpipe );
void sp_setup_prepare( struct setup_context *setup );
void sp_setup_destroy_context( struct setup_context *setup );
 
#endif
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_state.h
0,0 → 1,196
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_STATE_H
#define SP_STATE_H
 
#include "pipe/p_state.h"
#include "tgsi/tgsi_scan.h"
 
 
#define SP_NEW_VIEWPORT 0x1
#define SP_NEW_RASTERIZER 0x2
#define SP_NEW_FS 0x4
#define SP_NEW_BLEND 0x8
#define SP_NEW_CLIP 0x10
#define SP_NEW_SCISSOR 0x20
#define SP_NEW_STIPPLE 0x40
#define SP_NEW_FRAMEBUFFER 0x80
#define SP_NEW_DEPTH_STENCIL_ALPHA 0x100
#define SP_NEW_CONSTANTS 0x200
#define SP_NEW_SAMPLER 0x400
#define SP_NEW_TEXTURE 0x800
#define SP_NEW_VERTEX 0x1000
#define SP_NEW_VS 0x2000
#define SP_NEW_QUERY 0x4000
#define SP_NEW_GS 0x8000
#define SP_NEW_SO 0x10000
#define SP_NEW_SO_BUFFERS 0x20000
 
 
struct tgsi_sampler;
struct tgsi_exec_machine;
struct vertex_info;
 
 
struct sp_fragment_shader_variant_key
{
boolean polygon_stipple;
};
 
 
struct sp_fragment_shader_variant
{
const struct tgsi_token *tokens;
struct sp_fragment_shader_variant_key key;
struct tgsi_shader_info info;
 
unsigned stipple_sampler_unit;
 
/* See comments about this elsewhere */
#if 0
struct draw_fragment_shader *draw_shader;
#endif
 
void (*prepare)(const struct sp_fragment_shader_variant *shader,
struct tgsi_exec_machine *machine,
struct tgsi_sampler *sampler);
 
unsigned (*run)(const struct sp_fragment_shader_variant *shader,
struct tgsi_exec_machine *machine,
struct quad_header *quad);
 
/* Deletes this instance of the object */
void (*delete)(struct sp_fragment_shader_variant *shader,
struct tgsi_exec_machine *machine);
 
struct sp_fragment_shader_variant *next;
};
 
 
/** Subclass of pipe_shader_state */
struct sp_fragment_shader {
struct pipe_shader_state shader;
struct sp_fragment_shader_variant *variants;
struct draw_fragment_shader *draw_shader;
};
 
 
/** Subclass of pipe_shader_state */
struct sp_vertex_shader {
struct pipe_shader_state shader;
struct draw_vertex_shader *draw_data;
int max_sampler; /* -1 if no samplers */
};
 
/** Subclass of pipe_shader_state */
struct sp_geometry_shader {
struct pipe_shader_state shader;
struct draw_geometry_shader *draw_data;
int max_sampler;
};
 
struct sp_velems_state {
unsigned count;
struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
};
 
struct sp_so_state {
struct pipe_stream_output_info base;
};
 
 
void
softpipe_init_blend_funcs(struct pipe_context *pipe);
 
void
softpipe_init_clip_funcs(struct pipe_context *pipe);
 
void
softpipe_init_sampler_funcs(struct pipe_context *pipe);
 
void
softpipe_init_rasterizer_funcs(struct pipe_context *pipe);
 
void
softpipe_init_shader_funcs(struct pipe_context *pipe);
 
void
softpipe_init_streamout_funcs(struct pipe_context *pipe);
 
void
softpipe_init_vertex_funcs(struct pipe_context *pipe);
 
void
softpipe_set_framebuffer_state(struct pipe_context *,
const struct pipe_framebuffer_state *);
 
void
softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim);
 
void
softpipe_set_sampler_views(struct pipe_context *pipe,
unsigned shader,
unsigned start,
unsigned num,
struct pipe_sampler_view **views);
 
 
void
softpipe_draw_vbo(struct pipe_context *pipe,
const struct pipe_draw_info *info);
 
void
softpipe_map_texture_surfaces(struct softpipe_context *sp);
 
void
softpipe_unmap_texture_surfaces(struct softpipe_context *sp);
 
 
struct vertex_info *
softpipe_get_vertex_info(struct softpipe_context *softpipe);
 
struct vertex_info *
softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe);
 
 
struct sp_fragment_shader_variant *
softpipe_find_fs_variant(struct softpipe_context *softpipe,
struct sp_fragment_shader *fs,
const struct sp_fragment_shader_variant_key *key);
 
 
struct sp_fragment_shader_variant *
softpipe_find_fs_variant(struct softpipe_context *softpipe,
struct sp_fragment_shader *fs,
const struct sp_fragment_shader_variant_key *key);
 
 
#endif
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_state_blend.c
0,0 → 1,150
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "draw/draw_context.h"
#include "sp_context.h"
#include "sp_state.h"
 
 
static void *
softpipe_create_blend_state(struct pipe_context *pipe,
const struct pipe_blend_state *blend)
{
return mem_dup(blend, sizeof(*blend));
}
 
 
static void
softpipe_bind_blend_state(struct pipe_context *pipe,
void *blend)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
draw_flush(softpipe->draw);
 
softpipe->blend = (struct pipe_blend_state *)blend;
 
softpipe->dirty |= SP_NEW_BLEND;
}
 
 
static void
softpipe_delete_blend_state(struct pipe_context *pipe,
void *blend)
{
FREE( blend );
}
 
 
static void
softpipe_set_blend_color(struct pipe_context *pipe,
const struct pipe_blend_color *blend_color)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
unsigned i;
 
draw_flush(softpipe->draw);
 
softpipe->blend_color = *blend_color;
 
/* save clamped color too */
for (i = 0; i < 4; i++)
softpipe->blend_color_clamped.color[i] =
CLAMP(blend_color->color[i], 0.0f, 1.0f);
 
softpipe->dirty |= SP_NEW_BLEND;
}
 
 
static void *
softpipe_create_depth_stencil_state(struct pipe_context *pipe,
const struct pipe_depth_stencil_alpha_state *depth_stencil)
{
return mem_dup(depth_stencil, sizeof(*depth_stencil));
}
 
 
static void
softpipe_bind_depth_stencil_state(struct pipe_context *pipe,
void *depth_stencil)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
softpipe->depth_stencil = (struct pipe_depth_stencil_alpha_state *)depth_stencil;
 
softpipe->dirty |= SP_NEW_DEPTH_STENCIL_ALPHA;
}
 
 
static void
softpipe_delete_depth_stencil_state(struct pipe_context *pipe, void *depth)
{
FREE( depth );
}
 
 
static void
softpipe_set_stencil_ref(struct pipe_context *pipe,
const struct pipe_stencil_ref *stencil_ref)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
softpipe->stencil_ref = *stencil_ref;
 
softpipe->dirty |= SP_NEW_DEPTH_STENCIL_ALPHA;
}
 
 
static void
softpipe_set_sample_mask(struct pipe_context *pipe,
unsigned sample_mask)
{
}
 
 
void
softpipe_init_blend_funcs(struct pipe_context *pipe)
{
pipe->create_blend_state = softpipe_create_blend_state;
pipe->bind_blend_state = softpipe_bind_blend_state;
pipe->delete_blend_state = softpipe_delete_blend_state;
 
pipe->set_blend_color = softpipe_set_blend_color;
 
pipe->create_depth_stencil_alpha_state = softpipe_create_depth_stencil_state;
pipe->bind_depth_stencil_alpha_state = softpipe_bind_depth_stencil_state;
pipe->delete_depth_stencil_alpha_state = softpipe_delete_depth_stencil_state;
 
pipe->set_stencil_ref = softpipe_set_stencil_ref;
 
pipe->set_sample_mask = softpipe_set_sample_mask;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_state_clip.c
0,0 → 1,98
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
#include "sp_context.h"
#include "sp_state.h"
#include "draw/draw_context.h"
 
 
static void
softpipe_set_clip_state(struct pipe_context *pipe,
const struct pipe_clip_state *clip)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
/* pass the clip state to the draw module */
draw_set_clip_state(softpipe->draw, clip);
}
 
 
static void
softpipe_set_viewport_states(struct pipe_context *pipe,
unsigned start_slot,
unsigned num_viewports,
const struct pipe_viewport_state *viewport)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
/* pass the viewport info to the draw module */
draw_set_viewport_states(softpipe->draw, start_slot, num_viewports,
viewport);
 
softpipe->viewport = *viewport; /* struct copy */
softpipe->dirty |= SP_NEW_VIEWPORT;
}
 
 
static void
softpipe_set_scissor_states(struct pipe_context *pipe,
unsigned start_slot,
unsigned num_scissors,
const struct pipe_scissor_state *scissor)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
draw_flush(softpipe->draw);
 
softpipe->scissor = *scissor; /* struct copy */
softpipe->dirty |= SP_NEW_SCISSOR;
}
 
 
static void
softpipe_set_polygon_stipple(struct pipe_context *pipe,
const struct pipe_poly_stipple *stipple)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
draw_flush(softpipe->draw);
 
softpipe->poly_stipple = *stipple; /* struct copy */
softpipe->dirty |= SP_NEW_STIPPLE;
}
 
 
void
softpipe_init_clip_funcs(struct pipe_context *pipe)
{
pipe->set_clip_state = softpipe_set_clip_state;
pipe->set_viewport_states = softpipe_set_viewport_states;
pipe->set_scissor_states = softpipe_set_scissor_states;
pipe->set_polygon_stipple = softpipe_set_polygon_stipple;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_state_derived.c
0,0 → 1,403
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "util/u_inlines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_pstipple.h"
#include "pipe/p_shader_tokens.h"
#include "draw/draw_context.h"
#include "draw/draw_vertex.h"
#include "sp_context.h"
#include "sp_screen.h"
#include "sp_state.h"
#include "sp_texture.h"
#include "sp_tex_sample.h"
#include "sp_tex_tile_cache.h"
 
 
/**
* Mark the current vertex layout as "invalid".
* We'll validate the vertex layout later, when we start to actually
* render a point or line or tri.
*/
static void
invalidate_vertex_layout(struct softpipe_context *softpipe)
{
softpipe->vertex_info.num_attribs = 0;
}
 
 
/**
* The vertex info describes how to convert the post-transformed vertices
* (simple float[][4]) used by the 'draw' module into vertices for
* rasterization.
*
* This function validates the vertex layout and returns a pointer to a
* vertex_info object.
*/
struct vertex_info *
softpipe_get_vertex_info(struct softpipe_context *softpipe)
{
struct vertex_info *vinfo = &softpipe->vertex_info;
 
if (vinfo->num_attribs == 0) {
/* compute vertex layout now */
const struct tgsi_shader_info *fsInfo = &softpipe->fs_variant->info;
struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf;
const uint num = draw_num_shader_outputs(softpipe->draw);
uint i;
 
/* Tell draw_vbuf to simply emit the whole post-xform vertex
* as-is. No longer any need to try and emit draw vertex_header
* info.
*/
vinfo_vbuf->num_attribs = 0;
for (i = 0; i < num; i++) {
draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i);
}
draw_compute_vertex_size(vinfo_vbuf);
 
/*
* Loop over fragment shader inputs, searching for the matching output
* from the vertex shader.
*/
vinfo->num_attribs = 0;
for (i = 0; i < fsInfo->num_inputs; i++) {
int src;
enum interp_mode interp = INTERP_LINEAR;
 
switch (fsInfo->input_interpolate[i]) {
case TGSI_INTERPOLATE_CONSTANT:
interp = INTERP_CONSTANT;
break;
case TGSI_INTERPOLATE_LINEAR:
interp = INTERP_LINEAR;
break;
case TGSI_INTERPOLATE_PERSPECTIVE:
interp = INTERP_PERSPECTIVE;
break;
case TGSI_INTERPOLATE_COLOR:
assert(fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR);
break;
default:
assert(0);
}
 
switch (fsInfo->input_semantic_name[i]) {
case TGSI_SEMANTIC_POSITION:
interp = INTERP_POS;
break;
 
case TGSI_SEMANTIC_COLOR:
if (fsInfo->input_interpolate[i] == TGSI_INTERPOLATE_COLOR) {
if (softpipe->rasterizer->flatshade)
interp = INTERP_CONSTANT;
else
interp = INTERP_PERSPECTIVE;
}
break;
}
 
/* this includes texcoords and varying vars */
src = draw_find_shader_output(softpipe->draw,
fsInfo->input_semantic_name[i],
fsInfo->input_semantic_index[i]);
if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR && src == -1)
/* try and find a bcolor */
src = draw_find_shader_output(softpipe->draw,
TGSI_SEMANTIC_BCOLOR, fsInfo->input_semantic_index[i]);
 
draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src);
}
 
softpipe->psize_slot = draw_find_shader_output(softpipe->draw,
TGSI_SEMANTIC_PSIZE, 0);
if (softpipe->psize_slot >= 0) {
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
softpipe->psize_slot);
}
 
draw_compute_vertex_size(vinfo);
}
 
return vinfo;
}
 
 
/**
* Called from vbuf module.
*
* Note that there's actually two different vertex layouts in softpipe.
*
* The normal one is computed in softpipe_get_vertex_info() above and is
* used by the point/line/tri "setup" code.
*
* The other one (this one) is only used by the vbuf module (which is
* not normally used by default but used in testing). For the vbuf module,
* we basically want to pass-through the draw module's vertex layout as-is.
* When the softpipe vbuf code begins drawing, the normal vertex layout
* will come into play again.
*/
struct vertex_info *
softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe)
{
(void) softpipe_get_vertex_info(softpipe);
return &softpipe->vertex_info_vbuf;
}
 
 
/**
* Recompute cliprect from scissor bounds, scissor enable and surface size.
*/
static void
compute_cliprect(struct softpipe_context *sp)
{
/* SP_NEW_FRAMEBUFFER
*/
uint surfWidth = sp->framebuffer.width;
uint surfHeight = sp->framebuffer.height;
 
/* SP_NEW_RASTERIZER
*/
if (sp->rasterizer->scissor) {
 
/* SP_NEW_SCISSOR
*
* clip to scissor rect:
*/
sp->cliprect.minx = MAX2(sp->scissor.minx, 0);
sp->cliprect.miny = MAX2(sp->scissor.miny, 0);
sp->cliprect.maxx = MIN2(sp->scissor.maxx, surfWidth);
sp->cliprect.maxy = MIN2(sp->scissor.maxy, surfHeight);
}
else {
/* clip to surface bounds */
sp->cliprect.minx = 0;
sp->cliprect.miny = 0;
sp->cliprect.maxx = surfWidth;
sp->cliprect.maxy = surfHeight;
}
}
 
 
static void
set_shader_sampler(struct softpipe_context *softpipe,
unsigned shader,
int max_sampler)
{
int i;
for (i = 0; i <= max_sampler; i++) {
softpipe->tgsi.sampler[shader]->sp_sampler[i] =
(struct sp_sampler *)(softpipe->samplers[shader][i]);
}
}
 
static void
update_tgsi_samplers( struct softpipe_context *softpipe )
{
unsigned i, sh;
 
set_shader_sampler(softpipe, PIPE_SHADER_VERTEX,
softpipe->vs->max_sampler);
set_shader_sampler(softpipe, PIPE_SHADER_FRAGMENT,
softpipe->fs_variant->info.file_max[TGSI_FILE_SAMPLER]);
if (softpipe->gs) {
set_shader_sampler(softpipe, PIPE_SHADER_GEOMETRY,
softpipe->gs->max_sampler);
}
 
/* XXX is this really necessary here??? */
for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
struct softpipe_tex_tile_cache *tc = softpipe->tex_cache[sh][i];
if (tc && tc->texture) {
struct softpipe_resource *spt = softpipe_resource(tc->texture);
if (spt->timestamp != tc->timestamp) {
sp_tex_tile_cache_validate_texture( tc );
/*
_debug_printf("INV %d %d\n", tc->timestamp, spt->timestamp);
*/
tc->timestamp = spt->timestamp;
}
}
}
}
}
 
 
static void
update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
{
struct sp_fragment_shader_variant_key key;
 
memset(&key, 0, sizeof(key));
 
if (prim == PIPE_PRIM_TRIANGLES)
key.polygon_stipple = softpipe->rasterizer->poly_stipple_enable;
 
if (softpipe->fs) {
softpipe->fs_variant = softpipe_find_fs_variant(softpipe,
softpipe->fs, &key);
 
/* prepare the TGSI interpreter for FS execution */
softpipe->fs_variant->prepare(softpipe->fs_variant,
softpipe->fs_machine,
(struct tgsi_sampler *) softpipe->
tgsi.sampler[PIPE_SHADER_FRAGMENT]);
}
else {
softpipe->fs_variant = NULL;
}
 
/* This would be the logical place to pass the fragment shader
* to the draw module. However, doing this here, during state
* validation, causes problems with the 'draw' module helpers for
* wide/AA/stippled lines.
* In principle, the draw's fragment shader should be per-variant
* but that doesn't work. So we use a single draw fragment shader
* per fragment shader, not per variant.
*/
#if 0
if (softpipe->fs_variant) {
draw_bind_fragment_shader(softpipe->draw,
softpipe->fs_variant->draw_shader);
}
else {
draw_bind_fragment_shader(softpipe->draw, NULL);
}
#endif
}
 
 
/**
* This should be called when the polygon stipple pattern changes.
* We create a new texture from the stipple pattern and create a new
* sampler view.
*/
static void
update_polygon_stipple_pattern(struct softpipe_context *softpipe)
{
struct pipe_resource *tex;
struct pipe_sampler_view *view;
 
tex = util_pstipple_create_stipple_texture(&softpipe->pipe,
softpipe->poly_stipple.stipple);
pipe_resource_reference(&softpipe->pstipple.texture, tex);
pipe_resource_reference(&tex, NULL);
 
view = util_pstipple_create_sampler_view(&softpipe->pipe,
softpipe->pstipple.texture);
pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, view);
pipe_sampler_view_reference(&view, NULL);
}
 
 
/**
* Should be called when polygon stipple is enabled/disabled or when
* the fragment shader changes.
* We add/update the fragment sampler and sampler views to sample from
* the polygon stipple texture. The texture unit that we use depends on
* the fragment shader (we need to use a unit not otherwise used by the
* shader).
*/
static void
update_polygon_stipple_enable(struct softpipe_context *softpipe, unsigned prim)
{
if (prim == PIPE_PRIM_TRIANGLES &&
softpipe->fs_variant->key.polygon_stipple) {
const unsigned unit = softpipe->fs_variant->stipple_sampler_unit;
 
/* sampler state */
softpipe->samplers[PIPE_SHADER_FRAGMENT][unit] = softpipe->pstipple.sampler;
 
/* sampler view state */
softpipe_set_sampler_views(&softpipe->pipe, PIPE_SHADER_FRAGMENT,
unit, 1, &softpipe->pstipple.sampler_view);
 
softpipe->dirty |= SP_NEW_SAMPLER;
}
}
 
 
/* Hopefully this will remain quite simple, otherwise need to pull in
* something like the state tracker mechanism.
*/
void
softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim)
{
struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen);
 
/* Check for updated textures.
*/
if (softpipe->tex_timestamp != sp_screen->timestamp) {
softpipe->tex_timestamp = sp_screen->timestamp;
softpipe->dirty |= SP_NEW_TEXTURE;
}
 
#if DO_PSTIPPLE_IN_HELPER_MODULE
if (softpipe->dirty & SP_NEW_STIPPLE)
/* before updating samplers! */
update_polygon_stipple_pattern(softpipe);
#endif
 
if (softpipe->dirty & (SP_NEW_RASTERIZER |
SP_NEW_FS))
update_fragment_shader(softpipe, prim);
 
#if DO_PSTIPPLE_IN_HELPER_MODULE
if (softpipe->dirty & (SP_NEW_RASTERIZER |
SP_NEW_STIPPLE |
SP_NEW_FS))
update_polygon_stipple_enable(softpipe, prim);
#endif
 
/* TODO: this looks suboptimal */
if (softpipe->dirty & (SP_NEW_SAMPLER |
SP_NEW_TEXTURE |
SP_NEW_FS |
SP_NEW_VS))
update_tgsi_samplers( softpipe );
 
if (softpipe->dirty & (SP_NEW_RASTERIZER |
SP_NEW_FS |
SP_NEW_VS))
invalidate_vertex_layout( softpipe );
 
if (softpipe->dirty & (SP_NEW_SCISSOR |
SP_NEW_RASTERIZER |
SP_NEW_FRAMEBUFFER))
compute_cliprect(softpipe);
 
if (softpipe->dirty & (SP_NEW_BLEND |
SP_NEW_DEPTH_STENCIL_ALPHA |
SP_NEW_FRAMEBUFFER |
SP_NEW_FS))
sp_build_quad_pipeline(softpipe);
 
softpipe->dirty = 0;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_state_rasterizer.c
0,0 → 1,76
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "sp_context.h"
#include "sp_state.h"
#include "draw/draw_context.h"
 
 
 
static void *
softpipe_create_rasterizer_state(struct pipe_context *pipe,
const struct pipe_rasterizer_state *rast)
{
return mem_dup(rast, sizeof(*rast));
}
 
 
static void
softpipe_bind_rasterizer_state(struct pipe_context *pipe,
void *rasterizer)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
if (softpipe->rasterizer == rasterizer)
return;
 
/* pass-through to draw module */
draw_set_rasterizer_state(softpipe->draw, rasterizer, rasterizer);
 
softpipe->rasterizer = rasterizer;
 
softpipe->dirty |= SP_NEW_RASTERIZER;
}
 
 
static void
softpipe_delete_rasterizer_state(struct pipe_context *pipe,
void *rasterizer)
{
FREE( rasterizer );
}
 
 
void
softpipe_init_rasterizer_funcs(struct pipe_context *pipe)
{
pipe->create_rasterizer_state = softpipe_create_rasterizer_state;
pipe->bind_rasterizer_state = softpipe_bind_rasterizer_state;
pipe->delete_rasterizer_state = softpipe_delete_rasterizer_state;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_state_sampler.c
0,0 → 1,247
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Authors:
* Brian Paul
*/
 
#include "util/u_memory.h"
#include "util/u_inlines.h"
 
#include "draw/draw_context.h"
 
#include "sp_context.h"
#include "sp_state.h"
#include "sp_texture.h"
#include "sp_tex_sample.h"
#include "sp_tex_tile_cache.h"
 
 
/**
* Bind a range [start, start+num-1] of samplers for a shader stage.
*/
static void
softpipe_bind_sampler_states(struct pipe_context *pipe,
unsigned shader,
unsigned start,
unsigned num,
void **samplers)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
unsigned i;
 
assert(shader < PIPE_SHADER_TYPES);
assert(start + num <= Elements(softpipe->samplers[shader]));
 
/* Check for no-op */
if (start + num <= softpipe->num_samplers[shader] &&
!memcmp(softpipe->samplers[shader] + start, samplers,
num * sizeof(void *))) {
return;
}
 
draw_flush(softpipe->draw);
 
/* set the new samplers */
for (i = 0; i < num; i++) {
softpipe->samplers[shader][start + i] = samplers[i];
}
 
/* find highest non-null samplers[] entry */
{
unsigned j = MAX2(softpipe->num_samplers[shader], start + num);
while (j > 0 && softpipe->samplers[shader][j - 1] == NULL)
j--;
softpipe->num_samplers[shader] = j;
}
 
if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
draw_set_samplers(softpipe->draw,
shader,
softpipe->samplers[shader],
softpipe->num_samplers[shader]);
}
 
softpipe->dirty |= SP_NEW_SAMPLER;
}
 
 
 
static void
softpipe_bind_fragment_sampler_states(struct pipe_context *pipe,
unsigned num, void **samplers)
{
softpipe_bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, num, samplers);
}
 
 
static void
softpipe_bind_vertex_sampler_states(struct pipe_context *pipe,
unsigned num,
void **samplers)
{
softpipe_bind_sampler_states(pipe, PIPE_SHADER_VERTEX, 0, num, samplers);
}
 
 
static void
softpipe_bind_geometry_sampler_states(struct pipe_context *pipe,
unsigned num,
void **samplers)
{
softpipe_bind_sampler_states(pipe, PIPE_SHADER_GEOMETRY, 0, num, samplers);
}
 
 
 
static void
softpipe_sampler_view_destroy(struct pipe_context *pipe,
struct pipe_sampler_view *view)
{
pipe_resource_reference(&view->texture, NULL);
FREE(view);
}
 
 
void
softpipe_set_sampler_views(struct pipe_context *pipe,
unsigned shader,
unsigned start,
unsigned num,
struct pipe_sampler_view **views)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
uint i;
 
assert(shader < PIPE_SHADER_TYPES);
assert(start + num <= Elements(softpipe->sampler_views[shader]));
 
/* Check for no-op */
if (start + num <= softpipe->num_sampler_views[shader] &&
!memcmp(softpipe->sampler_views[shader] + start, views,
num * sizeof(struct pipe_sampler_view *))) {
return;
}
 
draw_flush(softpipe->draw);
 
/* set the new sampler views */
for (i = 0; i < num; i++) {
struct sp_sampler_view *sp_sviewsrc;
struct sp_sampler_view *sp_sviewdst =
&softpipe->tgsi.sampler[shader]->sp_sview[start + i];
struct pipe_sampler_view **pview = &softpipe->sampler_views[shader][start + i];
pipe_sampler_view_reference(pview, views[i]);
sp_tex_tile_cache_set_sampler_view(softpipe->tex_cache[shader][start + i],
views[i]);
/*
* We don't really have variants, however some bits are different per shader,
* so just copy?
*/
sp_sviewsrc = (struct sp_sampler_view *)*pview;
if (sp_sviewsrc) {
memcpy(sp_sviewdst, sp_sviewsrc, sizeof(*sp_sviewsrc));
sp_sviewdst->compute_lambda = softpipe_get_lambda_func(&sp_sviewdst->base, shader);
sp_sviewdst->cache = softpipe->tex_cache[shader][start + i];
}
else {
memset(sp_sviewdst, 0, sizeof(*sp_sviewsrc));
}
}
 
 
/* find highest non-null sampler_views[] entry */
{
unsigned j = MAX2(softpipe->num_sampler_views[shader], start + num);
while (j > 0 && softpipe->sampler_views[shader][j - 1] == NULL)
j--;
softpipe->num_sampler_views[shader] = j;
}
 
if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
draw_set_sampler_views(softpipe->draw,
shader,
softpipe->sampler_views[shader],
softpipe->num_sampler_views[shader]);
}
 
softpipe->dirty |= SP_NEW_TEXTURE;
}
 
 
static void
softpipe_set_fragment_sampler_views(struct pipe_context *pipe,
unsigned num,
struct pipe_sampler_view **views)
{
softpipe_set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num, views);
}
 
 
static void
softpipe_set_vertex_sampler_views(struct pipe_context *pipe,
unsigned num,
struct pipe_sampler_view **views)
{
softpipe_set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0, num, views);
}
 
 
static void
softpipe_set_geometry_sampler_views(struct pipe_context *pipe,
unsigned num,
struct pipe_sampler_view **views)
{
softpipe_set_sampler_views(pipe, PIPE_SHADER_GEOMETRY, 0, num, views);
}
 
 
static void
softpipe_delete_sampler_state(struct pipe_context *pipe,
void *sampler)
{
FREE( sampler );
}
 
 
void
softpipe_init_sampler_funcs(struct pipe_context *pipe)
{
pipe->create_sampler_state = softpipe_create_sampler_state;
pipe->bind_fragment_sampler_states = softpipe_bind_fragment_sampler_states;
pipe->bind_vertex_sampler_states = softpipe_bind_vertex_sampler_states;
pipe->bind_geometry_sampler_states = softpipe_bind_geometry_sampler_states;
pipe->delete_sampler_state = softpipe_delete_sampler_state;
 
pipe->set_fragment_sampler_views = softpipe_set_fragment_sampler_views;
pipe->set_vertex_sampler_views = softpipe_set_vertex_sampler_views;
pipe->set_geometry_sampler_views = softpipe_set_geometry_sampler_views;
 
pipe->create_sampler_view = softpipe_create_sampler_view;
pipe->sampler_view_destroy = softpipe_sampler_view_destroy;
}
 
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_state_shader.c
0,0 → 1,398
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "sp_context.h"
#include "sp_state.h"
#include "sp_fs.h"
#include "sp_texture.h"
 
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_pstipple.h"
#include "draw/draw_context.h"
#include "draw/draw_vs.h"
#include "draw/draw_gs.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_scan.h"
#include "tgsi/tgsi_parse.h"
 
 
/**
* Create a new fragment shader variant.
*/
static struct sp_fragment_shader_variant *
create_fs_variant(struct softpipe_context *softpipe,
struct sp_fragment_shader *fs,
const struct sp_fragment_shader_variant_key *key)
{
struct sp_fragment_shader_variant *var;
struct pipe_shader_state *stipple_fs = NULL, *curfs = &fs->shader;
unsigned unit = 0;
 
#if DO_PSTIPPLE_IN_HELPER_MODULE
if (key->polygon_stipple) {
/* get new shader that implements polygon stippling */
stipple_fs = util_pstipple_create_fragment_shader(&softpipe->pipe,
curfs, &unit);
curfs = stipple_fs;
}
#endif
 
/* codegen, create variant object */
var = softpipe_create_fs_variant_exec(softpipe, curfs);
 
if (var) {
var->key = *key;
var->tokens = tgsi_dup_tokens(curfs->tokens);
var->stipple_sampler_unit = unit;
 
tgsi_scan_shader(var->tokens, &var->info);
 
/* See comments elsewhere about draw fragment shaders */
#if 0
/* draw's fs state */
var->draw_shader = draw_create_fragment_shader(softpipe->draw,
&fs->shader);
if (!var->draw_shader) {
var->delete(var);
FREE((void *) var->tokens);
return NULL;
}
#endif
 
/* insert variant into linked list */
var->next = fs->variants;
fs->variants = var;
}
 
if (stipple_fs) {
FREE((void *) stipple_fs->tokens);
FREE(stipple_fs);
}
 
return var;
}
 
 
struct sp_fragment_shader_variant *
softpipe_find_fs_variant(struct softpipe_context *sp,
struct sp_fragment_shader *fs,
const struct sp_fragment_shader_variant_key *key)
{
struct sp_fragment_shader_variant *var;
 
for (var = fs->variants; var; var = var->next) {
if (memcmp(&var->key, key, sizeof(*key)) == 0) {
/* found it */
return var;
}
}
 
return create_fs_variant(sp, fs, key);
}
 
 
static void *
softpipe_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader);
 
/* debug */
if (softpipe->dump_fs)
tgsi_dump(templ->tokens, 0);
 
/* we need to keep a local copy of the tokens */
state->shader.tokens = tgsi_dup_tokens(templ->tokens);
 
/* draw's fs state */
state->draw_shader = draw_create_fragment_shader(softpipe->draw,
&state->shader);
if (!state->draw_shader) {
FREE((void *) state->shader.tokens);
FREE(state);
return NULL;
}
 
return state;
}
 
 
static void
softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs;
 
if (softpipe->fs == fs)
return;
 
draw_flush(softpipe->draw);
 
softpipe->fs = fs;
 
/* This depends on the current fragment shader and must always be
* re-validated before use.
*/
softpipe->fs_variant = NULL;
 
if (state)
draw_bind_fragment_shader(softpipe->draw,
state->draw_shader);
else
draw_bind_fragment_shader(softpipe->draw, NULL);
 
softpipe->dirty |= SP_NEW_FS;
}
 
 
static void
softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_fragment_shader *state = fs;
struct sp_fragment_shader_variant *var, *next_var;
 
assert(fs != softpipe->fs);
 
/* delete variants */
for (var = state->variants; var; var = next_var) {
next_var = var->next;
 
assert(var != softpipe->fs_variant);
 
/* See comments elsewhere about draw fragment shaders */
#if 0
draw_delete_fragment_shader(softpipe->draw, var->draw_shader);
#endif
 
var->delete(var, softpipe->fs_machine);
}
 
draw_delete_fragment_shader(softpipe->draw, state->draw_shader);
 
FREE((void *) state->shader.tokens);
FREE(state);
}
 
 
static void *
softpipe_create_vs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_vertex_shader *state;
 
state = CALLOC_STRUCT(sp_vertex_shader);
if (state == NULL )
goto fail;
 
/* copy shader tokens, the ones passed in will go away.
*/
state->shader.tokens = tgsi_dup_tokens(templ->tokens);
if (state->shader.tokens == NULL)
goto fail;
 
state->draw_data = draw_create_vertex_shader(softpipe->draw, templ);
if (state->draw_data == NULL)
goto fail;
 
state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
 
return state;
 
fail:
if (state) {
FREE( (void *)state->shader.tokens );
FREE( state->draw_data );
FREE( state );
}
return NULL;
}
 
 
static void
softpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
softpipe->vs = (struct sp_vertex_shader *) vs;
 
draw_bind_vertex_shader(softpipe->draw,
(softpipe->vs ? softpipe->vs->draw_data : NULL));
 
softpipe->dirty |= SP_NEW_VS;
}
 
 
static void
softpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
struct sp_vertex_shader *state = (struct sp_vertex_shader *) vs;
 
draw_delete_vertex_shader(softpipe->draw, state->draw_data);
FREE( (void *)state->shader.tokens );
FREE( state );
}
 
 
static void *
softpipe_create_gs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_geometry_shader *state;
 
state = CALLOC_STRUCT(sp_geometry_shader);
if (state == NULL )
goto fail;
 
state->shader = *templ;
 
if (templ->tokens) {
/* debug */
if (softpipe->dump_gs)
tgsi_dump(templ->tokens, 0);
 
/* copy shader tokens, the ones passed in will go away.
*/
state->shader.tokens = tgsi_dup_tokens(templ->tokens);
if (state->shader.tokens == NULL)
goto fail;
 
state->draw_data = draw_create_geometry_shader(softpipe->draw, templ);
if (state->draw_data == NULL)
goto fail;
 
state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
}
 
return state;
 
fail:
if (state) {
FREE( (void *)state->shader.tokens );
FREE( state->draw_data );
FREE( state );
}
return NULL;
}
 
 
static void
softpipe_bind_gs_state(struct pipe_context *pipe, void *gs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
softpipe->gs = (struct sp_geometry_shader *)gs;
 
draw_bind_geometry_shader(softpipe->draw,
(softpipe->gs ? softpipe->gs->draw_data : NULL));
 
softpipe->dirty |= SP_NEW_GS;
}
 
 
static void
softpipe_delete_gs_state(struct pipe_context *pipe, void *gs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
struct sp_geometry_shader *state =
(struct sp_geometry_shader *)gs;
 
draw_delete_geometry_shader(softpipe->draw,
(state) ? state->draw_data : 0);
 
FREE((void *) state->shader.tokens);
FREE(state);
}
 
 
static void
softpipe_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
struct pipe_constant_buffer *cb)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct pipe_resource *constants = cb ? cb->buffer : NULL;
unsigned size;
const void *data;
 
if (cb && cb->user_buffer) {
constants = softpipe_user_buffer_create(pipe->screen,
(void *) cb->user_buffer,
cb->buffer_size,
PIPE_BIND_CONSTANT_BUFFER);
}
 
size = constants ? constants->width0 : 0;
data = constants ? softpipe_resource(constants)->data : NULL;
 
assert(shader < PIPE_SHADER_TYPES);
 
draw_flush(softpipe->draw);
 
/* note: reference counting */
pipe_resource_reference(&softpipe->constants[shader][index], constants);
 
if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size);
}
 
softpipe->mapped_constants[shader][index] = data;
softpipe->const_buffer_size[shader][index] = size;
 
softpipe->dirty |= SP_NEW_CONSTANTS;
 
if (cb && cb->user_buffer) {
pipe_resource_reference(&constants, NULL);
}
}
 
 
void
softpipe_init_shader_funcs(struct pipe_context *pipe)
{
pipe->create_fs_state = softpipe_create_fs_state;
pipe->bind_fs_state = softpipe_bind_fs_state;
pipe->delete_fs_state = softpipe_delete_fs_state;
 
pipe->create_vs_state = softpipe_create_vs_state;
pipe->bind_vs_state = softpipe_bind_vs_state;
pipe->delete_vs_state = softpipe_delete_vs_state;
 
pipe->create_gs_state = softpipe_create_gs_state;
pipe->bind_gs_state = softpipe_bind_gs_state;
pipe->delete_gs_state = softpipe_delete_gs_state;
 
pipe->set_constant_buffer = softpipe_set_constant_buffer;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_state_so.c
0,0 → 1,89
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "sp_context.h"
#include "sp_state.h"
#include "sp_texture.h"
 
#include "util/u_format.h"
#include "util/u_memory.h"
#include "draw/draw_context.h"
#include "pipebuffer/pb_buffer.h"
 
static struct pipe_stream_output_target *
softpipe_create_so_target(struct pipe_context *pipe,
struct pipe_resource *buffer,
unsigned buffer_offset,
unsigned buffer_size)
{
struct draw_so_target *t;
 
t = CALLOC_STRUCT(draw_so_target);
t->target.context = pipe;
t->target.reference.count = 1;
pipe_resource_reference(&t->target.buffer, buffer);
t->target.buffer_offset = buffer_offset;
t->target.buffer_size = buffer_size;
return &t->target;
}
 
static void
softpipe_so_target_destroy(struct pipe_context *pipe,
struct pipe_stream_output_target *target)
{
pipe_resource_reference(&target->buffer, NULL);
FREE(target);
}
 
static void
softpipe_set_so_targets(struct pipe_context *pipe,
unsigned num_targets,
struct pipe_stream_output_target **targets,
unsigned append_bitmask)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
unsigned i;
 
for (i = 0; i < num_targets; i++) {
pipe_so_target_reference((struct pipe_stream_output_target **)&softpipe->so_targets[i], targets[i]);
}
 
for (; i < softpipe->num_so_targets; i++) {
pipe_so_target_reference((struct pipe_stream_output_target **)&softpipe->so_targets[i], NULL);
}
 
softpipe->num_so_targets = num_targets;
}
 
void
softpipe_init_streamout_funcs(struct pipe_context *pipe)
{
pipe->create_stream_output_target = softpipe_create_so_target;
pipe->stream_output_target_destroy = softpipe_so_target_destroy;
pipe->set_stream_output_targets = softpipe_set_so_targets;
}
 
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_state_surface.c
0,0 → 1,106
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "sp_context.h"
#include "sp_state.h"
#include "sp_tile_cache.h"
 
#include "draw/draw_context.h"
 
#include "util/u_format.h"
#include "util/u_inlines.h"
 
 
/**
* XXX this might get moved someday
* Set the framebuffer surface info: color buffers, zbuffer, stencil buffer.
* Here, we flush the old surfaces and update the tile cache to point to the new
* surfaces.
*/
void
softpipe_set_framebuffer_state(struct pipe_context *pipe,
const struct pipe_framebuffer_state *fb)
{
struct softpipe_context *sp = softpipe_context(pipe);
uint i;
 
draw_flush(sp->draw);
 
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
struct pipe_surface *cb = i < fb->nr_cbufs ? fb->cbufs[i] : NULL;
 
/* check if changing cbuf */
if (sp->framebuffer.cbufs[i] != cb) {
/* flush old */
sp_flush_tile_cache(sp->cbuf_cache[i]);
 
/* assign new */
pipe_surface_reference(&sp->framebuffer.cbufs[i], cb);
 
/* update cache */
sp_tile_cache_set_surface(sp->cbuf_cache[i], cb);
}
}
 
sp->framebuffer.nr_cbufs = fb->nr_cbufs;
 
/* zbuf changing? */
if (sp->framebuffer.zsbuf != fb->zsbuf) {
/* flush old */
sp_flush_tile_cache(sp->zsbuf_cache);
 
/* assign new */
pipe_surface_reference(&sp->framebuffer.zsbuf, fb->zsbuf);
 
/* update cache */
sp_tile_cache_set_surface(sp->zsbuf_cache, fb->zsbuf);
 
/* Tell draw module how deep the Z/depth buffer is */
if (sp->framebuffer.zsbuf) {
int depth_bits;
double mrd;
depth_bits = util_format_get_component_bits(sp->framebuffer.zsbuf->format,
UTIL_FORMAT_COLORSPACE_ZS,
0);
if (depth_bits > 16) {
mrd = 0.0000001;
}
else {
mrd = 0.00002;
}
draw_set_mrd(sp->draw, mrd);
}
}
 
sp->framebuffer.width = fb->width;
sp->framebuffer.height = fb->height;
 
sp->dirty |= SP_NEW_FRAMEBUFFER;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_state_vertex.c
0,0 → 1,122
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "sp_context.h"
#include "sp_state.h"
 
#include "util/u_memory.h"
#include "util/u_helpers.h"
#include "util/u_inlines.h"
#include "util/u_transfer.h"
#include "draw/draw_context.h"
 
 
static void *
softpipe_create_vertex_elements_state(struct pipe_context *pipe,
unsigned count,
const struct pipe_vertex_element *attribs)
{
struct sp_velems_state *velems;
assert(count <= PIPE_MAX_ATTRIBS);
velems = (struct sp_velems_state *) MALLOC(sizeof(struct sp_velems_state));
if (velems) {
velems->count = count;
memcpy(velems->velem, attribs, sizeof(*attribs) * count);
}
return velems;
}
 
 
static void
softpipe_bind_vertex_elements_state(struct pipe_context *pipe,
void *velems)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_velems_state *sp_velems = (struct sp_velems_state *) velems;
 
softpipe->velems = sp_velems;
 
softpipe->dirty |= SP_NEW_VERTEX;
 
if (sp_velems)
draw_set_vertex_elements(softpipe->draw, sp_velems->count, sp_velems->velem);
}
 
 
static void
softpipe_delete_vertex_elements_state(struct pipe_context *pipe, void *velems)
{
FREE( velems );
}
 
 
static void
softpipe_set_vertex_buffers(struct pipe_context *pipe,
unsigned start_slot, unsigned count,
const struct pipe_vertex_buffer *buffers)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
assert(count <= PIPE_MAX_ATTRIBS);
 
util_set_vertex_buffers_count(softpipe->vertex_buffer,
&softpipe->num_vertex_buffers,
buffers, start_slot, count);
 
softpipe->dirty |= SP_NEW_VERTEX;
 
draw_set_vertex_buffers(softpipe->draw, start_slot, count, buffers);
}
 
 
static void
softpipe_set_index_buffer(struct pipe_context *pipe,
const struct pipe_index_buffer *ib)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
if (ib)
memcpy(&softpipe->index_buffer, ib, sizeof(softpipe->index_buffer));
else
memset(&softpipe->index_buffer, 0, sizeof(softpipe->index_buffer));
}
 
 
void
softpipe_init_vertex_funcs(struct pipe_context *pipe)
{
pipe->create_vertex_elements_state = softpipe_create_vertex_elements_state;
pipe->bind_vertex_elements_state = softpipe_bind_vertex_elements_state;
pipe->delete_vertex_elements_state = softpipe_delete_vertex_elements_state;
 
pipe->set_vertex_buffers = softpipe_set_vertex_buffers;
pipe->set_index_buffer = softpipe_set_index_buffer;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_surface.c
0,0 → 1,130
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#include "util/u_format.h"
#include "util/u_surface.h"
#include "sp_context.h"
#include "sp_surface.h"
#include "sp_query.h"
 
static void sp_blit(struct pipe_context *pipe,
const struct pipe_blit_info *info)
{
struct softpipe_context *sp = softpipe_context(pipe);
 
if (info->src.resource->nr_samples > 1 &&
info->dst.resource->nr_samples <= 1 &&
!util_format_is_depth_or_stencil(info->src.resource->format) &&
!util_format_is_pure_integer(info->src.resource->format)) {
debug_printf("softpipe: color resolve unimplemented\n");
return;
}
 
if (util_try_blit_via_copy_region(pipe, info)) {
return; /* done */
}
 
if (!util_blitter_is_blit_supported(sp->blitter, info)) {
debug_printf("softpipe: blit unsupported %s -> %s\n",
util_format_short_name(info->src.resource->format),
util_format_short_name(info->dst.resource->format));
return;
}
 
/* XXX turn off occlusion and streamout queries */
 
util_blitter_save_vertex_buffer_slot(sp->blitter, sp->vertex_buffer);
util_blitter_save_vertex_elements(sp->blitter, sp->velems);
util_blitter_save_vertex_shader(sp->blitter, sp->vs);
util_blitter_save_geometry_shader(sp->blitter, sp->gs);
util_blitter_save_so_targets(sp->blitter, sp->num_so_targets,
(struct pipe_stream_output_target**)sp->so_targets);
util_blitter_save_rasterizer(sp->blitter, sp->rasterizer);
util_blitter_save_viewport(sp->blitter, &sp->viewport);
util_blitter_save_scissor(sp->blitter, &sp->scissor);
util_blitter_save_fragment_shader(sp->blitter, sp->fs);
util_blitter_save_blend(sp->blitter, sp->blend);
util_blitter_save_depth_stencil_alpha(sp->blitter, sp->depth_stencil);
util_blitter_save_stencil_ref(sp->blitter, &sp->stencil_ref);
/*util_blitter_save_sample_mask(sp->blitter, sp->sample_mask);*/
util_blitter_save_framebuffer(sp->blitter, &sp->framebuffer);
util_blitter_save_fragment_sampler_states(sp->blitter,
sp->num_samplers[PIPE_SHADER_FRAGMENT],
(void**)sp->samplers[PIPE_SHADER_FRAGMENT]);
util_blitter_save_fragment_sampler_views(sp->blitter,
sp->num_sampler_views[PIPE_SHADER_FRAGMENT],
sp->sampler_views[PIPE_SHADER_FRAGMENT]);
util_blitter_save_render_condition(sp->blitter, sp->render_cond_query,
sp->render_cond_cond, sp->render_cond_mode);
util_blitter_blit(sp->blitter, info);
}
 
static void
softpipe_clear_render_target(struct pipe_context *pipe,
struct pipe_surface *dst,
const union pipe_color_union *color,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
if (!softpipe_check_render_cond(softpipe))
return;
 
util_clear_render_target(pipe, dst, color,
dstx, dsty, width, height);
}
 
 
static void
softpipe_clear_depth_stencil(struct pipe_context *pipe,
struct pipe_surface *dst,
unsigned clear_flags,
double depth,
unsigned stencil,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
if (!softpipe_check_render_cond(softpipe))
return;
 
util_clear_depth_stencil(pipe, dst, clear_flags,
depth, stencil,
dstx, dsty, width, height);
}
 
 
void
sp_init_surface_functions(struct softpipe_context *sp)
{
sp->pipe.resource_copy_region = util_resource_copy_region;
sp->pipe.clear_render_target = softpipe_clear_render_target;
sp->pipe.clear_depth_stencil = softpipe_clear_depth_stencil;
sp->pipe.blit = sp_blit;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_surface.h
0,0 → 1,42
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_SURFACE_H
#define SP_SURFACE_H
 
 
struct softpipe_context;
 
 
extern void
sp_init_surface_functions(struct softpipe_context *sp);
 
 
#endif /* SP_SURFACE_H */
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_tex_sample.c
0,0 → 1,3157
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2008-2010 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/**
* Texture sampling
*
* Authors:
* Brian Paul
* Keith Whitwell
*/
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_math.h"
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "sp_quad.h" /* only for #define QUAD_* tokens */
#include "sp_tex_sample.h"
#include "sp_texture.h"
#include "sp_tex_tile_cache.h"
 
 
/** Set to one to help debug texture sampling */
#define DEBUG_TEX 0
 
 
/*
* Return fractional part of 'f'. Used for computing interpolation weights.
* Need to be careful with negative values.
* Note, if this function isn't perfect you'll sometimes see 1-pixel bands
* of improperly weighted linear-filtered textures.
* The tests/texwrap.c demo is a good test.
*/
static INLINE float
frac(float f)
{
return f - floorf(f);
}
 
 
 
/**
* Linear interpolation macro
*/
static INLINE float
lerp(float a, float v0, float v1)
{
return v0 + a * (v1 - v0);
}
 
 
/**
* Do 2D/bilinear interpolation of float values.
* v00, v10, v01 and v11 are typically four texture samples in a square/box.
* a and b are the horizontal and vertical interpolants.
* It's important that this function is inlined when compiled with
* optimization! If we find that's not true on some systems, convert
* to a macro.
*/
static INLINE float
lerp_2d(float a, float b,
float v00, float v10, float v01, float v11)
{
const float temp0 = lerp(a, v00, v10);
const float temp1 = lerp(a, v01, v11);
return lerp(b, temp0, temp1);
}
 
 
/**
* As above, but 3D interpolation of 8 values.
*/
static INLINE float
lerp_3d(float a, float b, float c,
float v000, float v100, float v010, float v110,
float v001, float v101, float v011, float v111)
{
const float temp0 = lerp_2d(a, b, v000, v100, v010, v110);
const float temp1 = lerp_2d(a, b, v001, v101, v011, v111);
return lerp(c, temp0, temp1);
}
 
 
 
/**
* Compute coord % size for repeat wrap modes.
* Note that if coord is negative, coord % size doesn't give the right
* value. To avoid that problem we add a large multiple of the size
* (rather than using a conditional).
*/
static INLINE int
repeat(int coord, unsigned size)
{
return (coord + size * 1024) % size;
}
 
 
/**
* Apply texture coord wrapping mode and return integer texture indexes
* for a vector of four texcoords (S or T or P).
* \param wrapMode PIPE_TEX_WRAP_x
* \param s the incoming texcoords
* \param size the texture image size
* \param icoord returns the integer texcoords
*/
static void
wrap_nearest_repeat(float s, unsigned size, int *icoord)
{
/* s limited to [0,1) */
/* i limited to [0,size-1] */
int i = util_ifloor(s * size);
*icoord = repeat(i, size);
}
 
 
static void
wrap_nearest_clamp(float s, unsigned size, int *icoord)
{
/* s limited to [0,1] */
/* i limited to [0,size-1] */
if (s <= 0.0F)
*icoord = 0;
else if (s >= 1.0F)
*icoord = size - 1;
else
*icoord = util_ifloor(s * size);
}
 
 
static void
wrap_nearest_clamp_to_edge(float s, unsigned size, int *icoord)
{
/* s limited to [min,max] */
/* i limited to [0, size-1] */
const float min = 1.0F / (2.0F * size);
const float max = 1.0F - min;
if (s < min)
*icoord = 0;
else if (s > max)
*icoord = size - 1;
else
*icoord = util_ifloor(s * size);
}
 
 
static void
wrap_nearest_clamp_to_border(float s, unsigned size, int *icoord)
{
/* s limited to [min,max] */
/* i limited to [-1, size] */
const float min = -1.0F / (2.0F * size);
const float max = 1.0F - min;
if (s <= min)
*icoord = -1;
else if (s >= max)
*icoord = size;
else
*icoord = util_ifloor(s * size);
}
 
 
static void
wrap_nearest_mirror_repeat(float s, unsigned size, int *icoord)
{
const float min = 1.0F / (2.0F * size);
const float max = 1.0F - min;
const int flr = util_ifloor(s);
float u = frac(s);
if (flr & 1)
u = 1.0F - u;
if (u < min)
*icoord = 0;
else if (u > max)
*icoord = size - 1;
else
*icoord = util_ifloor(u * size);
}
 
 
static void
wrap_nearest_mirror_clamp(float s, unsigned size, int *icoord)
{
/* s limited to [0,1] */
/* i limited to [0,size-1] */
const float u = fabsf(s);
if (u <= 0.0F)
*icoord = 0;
else if (u >= 1.0F)
*icoord = size - 1;
else
*icoord = util_ifloor(u * size);
}
 
 
static void
wrap_nearest_mirror_clamp_to_edge(float s, unsigned size, int *icoord)
{
/* s limited to [min,max] */
/* i limited to [0, size-1] */
const float min = 1.0F / (2.0F * size);
const float max = 1.0F - min;
const float u = fabsf(s);
if (u < min)
*icoord = 0;
else if (u > max)
*icoord = size - 1;
else
*icoord = util_ifloor(u * size);
}
 
 
static void
wrap_nearest_mirror_clamp_to_border(float s, unsigned size, int *icoord)
{
/* s limited to [min,max] */
/* i limited to [0, size-1] */
const float min = -1.0F / (2.0F * size);
const float max = 1.0F - min;
const float u = fabsf(s);
if (u < min)
*icoord = -1;
else if (u > max)
*icoord = size;
else
*icoord = util_ifloor(u * size);
}
 
 
/**
* Used to compute texel locations for linear sampling
* \param wrapMode PIPE_TEX_WRAP_x
* \param s the texcoord
* \param size the texture image size
* \param icoord0 returns first texture index
* \param icoord1 returns second texture index (usually icoord0 + 1)
* \param w returns blend factor/weight between texture indices
* \param icoord returns the computed integer texture coord
*/
static void
wrap_linear_repeat(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = s * size - 0.5F;
*icoord0 = repeat(util_ifloor(u), size);
*icoord1 = repeat(*icoord0 + 1, size);
*w = frac(u);
}
 
 
static void
wrap_linear_clamp(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = CLAMP(s, 0.0F, 1.0F);
u = u * size - 0.5f;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
*w = frac(u);
}
 
 
static void
wrap_linear_clamp_to_edge(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = CLAMP(s, 0.0F, 1.0F);
u = u * size - 0.5f;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
if (*icoord0 < 0)
*icoord0 = 0;
if (*icoord1 >= (int) size)
*icoord1 = size - 1;
*w = frac(u);
}
 
 
static void
wrap_linear_clamp_to_border(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
const float min = -1.0F / (2.0F * size);
const float max = 1.0F - min;
float u = CLAMP(s, min, max);
u = u * size - 0.5f;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
*w = frac(u);
}
 
 
static void
wrap_linear_mirror_repeat(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
const int flr = util_ifloor(s);
float u = frac(s);
if (flr & 1)
u = 1.0F - u;
u = u * size - 0.5F;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
if (*icoord0 < 0)
*icoord0 = 0;
if (*icoord1 >= (int) size)
*icoord1 = size - 1;
*w = frac(u);
}
 
 
static void
wrap_linear_mirror_clamp(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = fabsf(s);
if (u >= 1.0F)
u = (float) size;
else
u *= size;
u -= 0.5F;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
*w = frac(u);
}
 
 
static void
wrap_linear_mirror_clamp_to_edge(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = fabsf(s);
if (u >= 1.0F)
u = (float) size;
else
u *= size;
u -= 0.5F;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
if (*icoord0 < 0)
*icoord0 = 0;
if (*icoord1 >= (int) size)
*icoord1 = size - 1;
*w = frac(u);
}
 
 
static void
wrap_linear_mirror_clamp_to_border(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
const float min = -1.0F / (2.0F * size);
const float max = 1.0F - min;
float u = fabsf(s);
if (u <= min)
u = min * size;
else if (u >= max)
u = max * size;
else
u *= size;
u -= 0.5F;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
*w = frac(u);
}
 
 
/**
* PIPE_TEX_WRAP_CLAMP for nearest sampling, unnormalized coords.
*/
static void
wrap_nearest_unorm_clamp(float s, unsigned size, int *icoord)
{
int i = util_ifloor(s);
*icoord = CLAMP(i, 0, (int) size-1);
}
 
 
/**
* PIPE_TEX_WRAP_CLAMP_TO_BORDER for nearest sampling, unnormalized coords.
*/
static void
wrap_nearest_unorm_clamp_to_border(float s, unsigned size, int *icoord)
{
*icoord = util_ifloor( CLAMP(s, -0.5F, (float) size + 0.5F) );
}
 
 
/**
* PIPE_TEX_WRAP_CLAMP_TO_EDGE for nearest sampling, unnormalized coords.
*/
static void
wrap_nearest_unorm_clamp_to_edge(float s, unsigned size, int *icoord)
{
*icoord = util_ifloor( CLAMP(s, 0.5F, (float) size - 0.5F) );
}
 
 
/**
* PIPE_TEX_WRAP_CLAMP for linear sampling, unnormalized coords.
*/
static void
wrap_linear_unorm_clamp(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
/* Not exactly what the spec says, but it matches NVIDIA output */
float u = CLAMP(s - 0.5F, 0.0f, (float) size - 1.0f);
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
*w = frac(u);
}
 
 
/**
* PIPE_TEX_WRAP_CLAMP_TO_BORDER for linear sampling, unnormalized coords.
*/
static void
wrap_linear_unorm_clamp_to_border(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = CLAMP(s, -0.5F, (float) size + 0.5F);
u -= 0.5F;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
if (*icoord1 > (int) size - 1)
*icoord1 = size - 1;
*w = frac(u);
}
 
 
/**
* PIPE_TEX_WRAP_CLAMP_TO_EDGE for linear sampling, unnormalized coords.
*/
static void
wrap_linear_unorm_clamp_to_edge(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = CLAMP(s, +0.5F, (float) size - 0.5F);
u -= 0.5F;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
if (*icoord1 > (int) size - 1)
*icoord1 = size - 1;
*w = frac(u);
}
 
 
/**
* Do coordinate to array index conversion. For array textures.
*/
static INLINE void
wrap_array_layer(float coord, unsigned size, int *layer)
{
int c = util_ifloor(coord + 0.5F);
*layer = CLAMP(c, 0, (int) size - 1);
}
 
 
/**
* Examine the quad's texture coordinates to compute the partial
* derivatives w.r.t X and Y, then compute lambda (level of detail).
*/
static float
compute_lambda_1d(const struct sp_sampler_view *sview,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sview->base.texture;
float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]);
float rho = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
 
return util_fast_log2(rho);
}
 
 
static float
compute_lambda_2d(const struct sp_sampler_view *sview,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sview->base.texture;
float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]);
float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
float dtdy = fabsf(t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]);
float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, sview->base.u.tex.first_level);
float rho = MAX2(maxx, maxy);
 
return util_fast_log2(rho);
}
 
 
static float
compute_lambda_3d(const struct sp_sampler_view *sview,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sview->base.texture;
float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]);
float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
float dtdy = fabsf(t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]);
float dpdx = fabsf(p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]);
float dpdy = fabsf(p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT]);
float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, sview->base.u.tex.first_level);
float maxz = MAX2(dpdx, dpdy) * u_minify(texture->depth0, sview->base.u.tex.first_level);
float rho;
 
rho = MAX2(maxx, maxy);
rho = MAX2(rho, maxz);
 
return util_fast_log2(rho);
}
 
 
/**
* Compute lambda for a vertex texture sampler.
* Since there aren't derivatives to use, just return 0.
*/
static float
compute_lambda_vert(const struct sp_sampler_view *sview,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE])
{
return 0.0f;
}
 
 
 
/**
* Get a texel from a texture, using the texture tile cache.
*
* \param addr the template tex address containing cube, z, face info.
* \param x the x coord of texel within 2D image
* \param y the y coord of texel within 2D image
* \param rgba the quad to put the texel/color into
*
* XXX maybe move this into sp_tex_tile_cache.c and merge with the
* sp_get_cached_tile_tex() function.
*/
 
 
 
 
static INLINE const float *
get_texel_2d_no_border(const struct sp_sampler_view *sp_sview,
union tex_tile_address addr, int x, int y)
{
const struct softpipe_tex_cached_tile *tile;
addr.bits.x = x / TEX_TILE_SIZE;
addr.bits.y = y / TEX_TILE_SIZE;
y %= TEX_TILE_SIZE;
x %= TEX_TILE_SIZE;
 
tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
 
return &tile->data.color[y][x][0];
}
 
 
static INLINE const float *
get_texel_2d(const struct sp_sampler_view *sp_sview,
const struct sp_sampler *sp_samp,
union tex_tile_address addr, int x, int y)
{
const struct pipe_resource *texture = sp_sview->base.texture;
unsigned level = addr.bits.level;
 
if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
y < 0 || y >= (int) u_minify(texture->height0, level)) {
return sp_samp->base.border_color.f;
}
else {
return get_texel_2d_no_border( sp_sview, addr, x, y );
}
}
 
/*
* seamless cubemap neighbour array.
* this array is used to find the adjacent face in each of 4 directions,
* left, right, up, down. (or -x, +x, -y, +y).
*/
static const unsigned face_array[PIPE_TEX_FACE_MAX][4] = {
/* pos X first then neg X is Z different, Y the same */
/* PIPE_TEX_FACE_POS_X,*/
{ PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z,
PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
/* PIPE_TEX_FACE_NEG_X */
{ PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z,
PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
 
/* pos Y first then neg Y is X different, X the same */
/* PIPE_TEX_FACE_POS_Y */
{ PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z },
 
/* PIPE_TEX_FACE_NEG_Y */
{ PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z },
 
/* pos Z first then neg Y is X different, X the same */
/* PIPE_TEX_FACE_POS_Z */
{ PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
 
/* PIPE_TEX_FACE_NEG_Z */
{ PIPE_TEX_FACE_POS_X, PIPE_TEX_FACE_NEG_X,
PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y }
};
 
static INLINE unsigned
get_next_face(unsigned face, int x, int y)
{
int idx = 0;
 
if (x == 0 && y == 0)
return face;
if (x == -1)
idx = 0;
else if (x == 1)
idx = 1;
else if (y == -1)
idx = 2;
else if (y == 1)
idx = 3;
 
return face_array[face][idx];
}
 
static INLINE const float *
get_texel_cube_seamless(const struct sp_sampler_view *sp_sview,
union tex_tile_address addr, int x, int y,
float *corner)
{
const struct pipe_resource *texture = sp_sview->base.texture;
unsigned level = addr.bits.level;
unsigned face = addr.bits.face;
int new_x, new_y;
int max_x, max_y;
int c;
 
max_x = (int) u_minify(texture->width0, level);
max_y = (int) u_minify(texture->height0, level);
new_x = x;
new_y = y;
 
/* the corner case */
if ((x < 0 || x >= max_x) &&
(y < 0 || y >= max_y)) {
const float *c1, *c2, *c3;
int fx = x < 0 ? 0 : max_x - 1;
int fy = y < 0 ? 0 : max_y - 1;
c1 = get_texel_2d_no_border( sp_sview, addr, fx, fy);
addr.bits.face = get_next_face(face, (x < 0) ? -1 : 1, 0);
c2 = get_texel_2d_no_border( sp_sview, addr, (x < 0) ? max_x - 1 : 0, fy);
addr.bits.face = get_next_face(face, 0, (y < 0) ? -1 : 1);
c3 = get_texel_2d_no_border( sp_sview, addr, fx, (y < 0) ? max_y - 1 : 0);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
corner[c] = CLAMP((c1[c] + c2[c] + c3[c]), 0.0F, 1.0F) / 3;
 
return corner;
}
/* change the face */
if (x < 0) {
new_x = max_x - 1;
face = get_next_face(face, -1, 0);
} else if (x >= max_x) {
new_x = 0;
face = get_next_face(face, 1, 0);
} else if (y < 0) {
new_y = max_y - 1;
face = get_next_face(face, 0, -1);
} else if (y >= max_y) {
new_y = 0;
face = get_next_face(face, 0, 1);
}
 
addr.bits.face = face;
return get_texel_2d_no_border( sp_sview, addr, new_x, new_y );
}
 
/* Gather a quad of adjacent texels within a tile:
*/
static INLINE void
get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_view *sp_sview,
union tex_tile_address addr,
unsigned x, unsigned y,
const float *out[4])
{
const struct softpipe_tex_cached_tile *tile;
 
addr.bits.x = x / TEX_TILE_SIZE;
addr.bits.y = y / TEX_TILE_SIZE;
y %= TEX_TILE_SIZE;
x %= TEX_TILE_SIZE;
 
tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
out[0] = &tile->data.color[y ][x ][0];
out[1] = &tile->data.color[y ][x+1][0];
out[2] = &tile->data.color[y+1][x ][0];
out[3] = &tile->data.color[y+1][x+1][0];
}
 
 
/* Gather a quad of potentially non-adjacent texels:
*/
static INLINE void
get_texel_quad_2d_no_border(const struct sp_sampler_view *sp_sview,
union tex_tile_address addr,
int x0, int y0,
int x1, int y1,
const float *out[4])
{
out[0] = get_texel_2d_no_border( sp_sview, addr, x0, y0 );
out[1] = get_texel_2d_no_border( sp_sview, addr, x1, y0 );
out[2] = get_texel_2d_no_border( sp_sview, addr, x0, y1 );
out[3] = get_texel_2d_no_border( sp_sview, addr, x1, y1 );
}
 
/* Can involve a lot of unnecessary checks for border color:
*/
static INLINE void
get_texel_quad_2d(const struct sp_sampler_view *sp_sview,
const struct sp_sampler *sp_samp,
union tex_tile_address addr,
int x0, int y0,
int x1, int y1,
const float *out[4])
{
out[0] = get_texel_2d( sp_sview, sp_samp, addr, x0, y0 );
out[1] = get_texel_2d( sp_sview, sp_samp, addr, x1, y0 );
out[3] = get_texel_2d( sp_sview, sp_samp, addr, x1, y1 );
out[2] = get_texel_2d( sp_sview, sp_samp, addr, x0, y1 );
}
 
 
 
/* 3d variants:
*/
static INLINE const float *
get_texel_3d_no_border(const struct sp_sampler_view *sp_sview,
union tex_tile_address addr, int x, int y, int z)
{
const struct softpipe_tex_cached_tile *tile;
 
addr.bits.x = x / TEX_TILE_SIZE;
addr.bits.y = y / TEX_TILE_SIZE;
addr.bits.z = z;
y %= TEX_TILE_SIZE;
x %= TEX_TILE_SIZE;
 
tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
 
return &tile->data.color[y][x][0];
}
 
 
static INLINE const float *
get_texel_3d(const struct sp_sampler_view *sp_sview,
const struct sp_sampler *sp_samp,
union tex_tile_address addr, int x, int y, int z)
{
const struct pipe_resource *texture = sp_sview->base.texture;
unsigned level = addr.bits.level;
 
if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
y < 0 || y >= (int) u_minify(texture->height0, level) ||
z < 0 || z >= (int) u_minify(texture->depth0, level)) {
return sp_samp->base.border_color.f;
}
else {
return get_texel_3d_no_border( sp_sview, addr, x, y, z );
}
}
 
 
/* Get texel pointer for 1D array texture */
static INLINE const float *
get_texel_1d_array(const struct sp_sampler_view *sp_sview,
const struct sp_sampler *sp_samp,
union tex_tile_address addr, int x, int y)
{
const struct pipe_resource *texture = sp_sview->base.texture;
unsigned level = addr.bits.level;
 
if (x < 0 || x >= (int) u_minify(texture->width0, level)) {
return sp_samp->base.border_color.f;
}
else {
return get_texel_2d_no_border(sp_sview, addr, x, y);
}
}
 
 
/* Get texel pointer for 2D array texture */
static INLINE const float *
get_texel_2d_array(const struct sp_sampler_view *sp_sview,
const struct sp_sampler *sp_samp,
union tex_tile_address addr, int x, int y, int layer)
{
const struct pipe_resource *texture = sp_sview->base.texture;
unsigned level = addr.bits.level;
 
assert(layer < (int) texture->array_size);
assert(layer >= 0);
 
if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
y < 0 || y >= (int) u_minify(texture->height0, level)) {
return sp_samp->base.border_color.f;
}
else {
return get_texel_3d_no_border(sp_sview, addr, x, y, layer);
}
}
 
 
/* Get texel pointer for cube array texture */
static INLINE const float *
get_texel_cube_array(const struct sp_sampler_view *sp_sview,
const struct sp_sampler *sp_samp,
union tex_tile_address addr, int x, int y, int layer)
{
const struct pipe_resource *texture = sp_sview->base.texture;
unsigned level = addr.bits.level;
 
assert(layer < (int) texture->array_size);
assert(layer >= 0);
 
if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
y < 0 || y >= (int) u_minify(texture->height0, level)) {
return sp_samp->base.border_color.f;
}
else {
return get_texel_3d_no_border(sp_sview, addr, x, y, layer);
}
}
/**
* Given the logbase2 of a mipmap's base level size and a mipmap level,
* return the size (in texels) of that mipmap level.
* For example, if level[0].width = 256 then base_pot will be 8.
* If level = 2, then we'll return 64 (the width at level=2).
* Return 1 if level > base_pot.
*/
static INLINE unsigned
pot_level_size(unsigned base_pot, unsigned level)
{
return (base_pot >= level) ? (1 << (base_pot - level)) : 1;
}
 
 
static void
print_sample(const char *function, const float *rgba)
{
debug_printf("%s %g %g %g %g\n",
function,
rgba[0], rgba[TGSI_NUM_CHANNELS], rgba[2*TGSI_NUM_CHANNELS], rgba[3*TGSI_NUM_CHANNELS]);
}
 
 
static void
print_sample_4(const char *function, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
debug_printf("%s %g %g %g %g, %g %g %g %g, %g %g %g %g, %g %g %g %g\n",
function,
rgba[0][0], rgba[1][0], rgba[2][0], rgba[3][0],
rgba[0][1], rgba[1][1], rgba[2][1], rgba[3][1],
rgba[0][2], rgba[1][2], rgba[2][2], rgba[3][2],
rgba[0][3], rgba[1][3], rgba[2][3], rgba[3][3]);
}
 
 
/* Some image-filter fastpaths:
*/
static INLINE void
img_filter_2d_linear_repeat_POT(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
unsigned xpot = pot_level_size(sp_sview->xpot, level);
unsigned ypot = pot_level_size(sp_sview->ypot, level);
int xmax = (xpot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, xpot) - 1; */
int ymax = (ypot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, ypot) - 1; */
union tex_tile_address addr;
int c;
 
float u = s * xpot - 0.5F;
float v = t * ypot - 0.5F;
 
int uflr = util_ifloor(u);
int vflr = util_ifloor(v);
 
float xw = u - (float)uflr;
float yw = v - (float)vflr;
 
int x0 = uflr & (xpot - 1);
int y0 = vflr & (ypot - 1);
 
const float *tx[4];
addr.value = 0;
addr.bits.level = level;
 
/* Can we fetch all four at once:
*/
if (x0 < xmax && y0 < ymax) {
get_texel_quad_2d_no_border_single_tile(sp_sview, addr, x0, y0, tx);
}
else {
unsigned x1 = (x0 + 1) & (xpot - 1);
unsigned y1 = (y0 + 1) & (ypot - 1);
get_texel_quad_2d_no_border(sp_sview, addr, x0, y0, x1, y1, tx);
}
 
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++) {
rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
tx[0][c], tx[1][c],
tx[2][c], tx[3][c]);
}
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static INLINE void
img_filter_2d_nearest_repeat_POT(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float rgba[TGSI_QUAD_SIZE])
{
unsigned xpot = pot_level_size(sp_sview->xpot, level);
unsigned ypot = pot_level_size(sp_sview->ypot, level);
const float *out;
union tex_tile_address addr;
int c;
 
float u = s * xpot;
float v = t * ypot;
 
int uflr = util_ifloor(u);
int vflr = util_ifloor(v);
 
int x0 = uflr & (xpot - 1);
int y0 = vflr & (ypot - 1);
 
addr.value = 0;
addr.bits.level = level;
 
out = get_texel_2d_no_border(sp_sview, addr, x0, y0);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static INLINE void
img_filter_2d_nearest_clamp_POT(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float rgba[TGSI_QUAD_SIZE])
{
unsigned xpot = pot_level_size(sp_sview->xpot, level);
unsigned ypot = pot_level_size(sp_sview->ypot, level);
union tex_tile_address addr;
int c;
 
float u = s * xpot;
float v = t * ypot;
 
int x0, y0;
const float *out;
 
addr.value = 0;
addr.bits.level = level;
 
x0 = util_ifloor(u);
if (x0 < 0)
x0 = 0;
else if (x0 > (int) xpot - 1)
x0 = xpot - 1;
 
y0 = util_ifloor(v);
if (y0 < 0)
y0 = 0;
else if (y0 > (int) ypot - 1)
y0 = ypot - 1;
out = get_texel_2d_no_border(sp_sview, addr, x0, y0);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static void
img_filter_1d_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float rgba[TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width;
int x;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
 
assert(width > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->nearest_texcoord_s(s, width, &x);
 
out = get_texel_2d(sp_sview, sp_samp, addr, x, 0);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static void
img_filter_1d_array_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width;
int x, layer;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
 
assert(width > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->nearest_texcoord_s(s, width, &x);
wrap_array_layer(t, texture->array_size, &layer);
 
out = get_texel_1d_array(sp_sview, sp_samp, addr, x, layer);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static void
img_filter_2d_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x, y;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
addr.value = 0;
addr.bits.level = level;
 
sp_samp->nearest_texcoord_s(s, width, &x);
sp_samp->nearest_texcoord_t(t, height, &y);
 
out = get_texel_2d(sp_sview, sp_samp, addr, x, y);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static void
img_filter_2d_array_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x, y, layer;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
addr.value = 0;
addr.bits.level = level;
 
sp_samp->nearest_texcoord_s(s, width, &x);
sp_samp->nearest_texcoord_t(t, height, &y);
wrap_array_layer(p, texture->array_size, &layer);
 
out = get_texel_2d_array(sp_sview, sp_samp, addr, x, y, layer);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static INLINE union tex_tile_address
face(union tex_tile_address addr, unsigned face )
{
addr.bits.face = face;
return addr;
}
 
 
static void
img_filter_cube_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x, y;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
addr.value = 0;
addr.bits.level = level;
 
/*
* If NEAREST filtering is done within a miplevel, always apply wrap
* mode CLAMP_TO_EDGE.
*/
if (sp_samp->base.seamless_cube_map) {
wrap_nearest_clamp_to_edge(s, width, &x);
wrap_nearest_clamp_to_edge(t, height, &y);
} else {
sp_samp->nearest_texcoord_s(s, width, &x);
sp_samp->nearest_texcoord_t(t, height, &y);
}
 
out = get_texel_2d(sp_sview, sp_samp, face(addr, face_id), x, y);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
static void
img_filter_cube_array_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x, y, layer;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
addr.value = 0;
addr.bits.level = level;
 
sp_samp->nearest_texcoord_s(s, width, &x);
sp_samp->nearest_texcoord_t(t, height, &y);
wrap_array_layer(p, texture->array_size, &layer);
 
out = get_texel_cube_array(sp_sview, sp_samp, addr, x, y, layer * 6 + face_id);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
static void
img_filter_3d_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height, depth;
int x, y, z;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
depth = u_minify(texture->depth0, level);
 
assert(width > 0);
assert(height > 0);
assert(depth > 0);
 
sp_samp->nearest_texcoord_s(s, width, &x);
sp_samp->nearest_texcoord_t(t, height, &y);
sp_samp->nearest_texcoord_p(p, depth, &z);
 
addr.value = 0;
addr.bits.level = level;
 
out = get_texel_3d(sp_sview, sp_samp, addr, x, y, z);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
}
 
 
static void
img_filter_1d_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width;
int x0, x1;
float xw; /* weights */
union tex_tile_address addr;
const float *tx0, *tx1;
int c;
 
width = u_minify(texture->width0, level);
 
assert(width > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
 
tx0 = get_texel_2d(sp_sview, sp_samp, addr, x0, 0);
tx1 = get_texel_2d(sp_sview, sp_samp, addr, x1, 0);
 
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
}
 
 
static void
img_filter_1d_array_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width;
int x0, x1, layer;
float xw; /* weights */
union tex_tile_address addr;
const float *tx0, *tx1;
int c;
 
width = u_minify(texture->width0, level);
 
assert(width > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
wrap_array_layer(t, texture->array_size, &layer);
 
tx0 = get_texel_1d_array(sp_sview, sp_samp, addr, x0, layer);
tx1 = get_texel_1d_array(sp_sview, sp_samp, addr, x1, layer);
 
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
}
 
 
static void
img_filter_2d_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x0, y0, x1, y1;
float xw, yw; /* weights */
union tex_tile_address addr;
const float *tx0, *tx1, *tx2, *tx3;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
 
tx0 = get_texel_2d(sp_sview, sp_samp, addr, x0, y0);
tx1 = get_texel_2d(sp_sview, sp_samp, addr, x1, y0);
tx2 = get_texel_2d(sp_sview, sp_samp, addr, x0, y1);
tx3 = get_texel_2d(sp_sview, sp_samp, addr, x1, y1);
 
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
tx0[c], tx1[c],
tx2[c], tx3[c]);
}
 
 
static void
img_filter_2d_array_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x0, y0, x1, y1, layer;
float xw, yw; /* weights */
union tex_tile_address addr;
const float *tx0, *tx1, *tx2, *tx3;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
wrap_array_layer(p, texture->array_size, &layer);
 
tx0 = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y0, layer);
tx1 = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y0, layer);
tx2 = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y1, layer);
tx3 = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y1, layer);
 
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
tx0[c], tx1[c],
tx2[c], tx3[c]);
}
 
 
static void
img_filter_cube_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x0, y0, x1, y1;
float xw, yw; /* weights */
union tex_tile_address addr, addrj;
const float *tx0, *tx1, *tx2, *tx3;
float corner0[TGSI_QUAD_SIZE], corner1[TGSI_QUAD_SIZE],
corner2[TGSI_QUAD_SIZE], corner3[TGSI_QUAD_SIZE];
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
 
addr.value = 0;
addr.bits.level = level;
 
/*
* For seamless if LINEAR filtering is done within a miplevel,
* always apply wrap mode CLAMP_TO_BORDER.
*/
if (sp_samp->base.seamless_cube_map) {
wrap_linear_clamp_to_border(s, width, &x0, &x1, &xw);
wrap_linear_clamp_to_border(t, height, &y0, &y1, &yw);
} else {
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
}
 
addrj = face(addr, face_id);
 
if (sp_samp->base.seamless_cube_map) {
tx0 = get_texel_cube_seamless(sp_sview, addrj, x0, y0, corner0);
tx1 = get_texel_cube_seamless(sp_sview, addrj, x1, y0, corner1);
tx2 = get_texel_cube_seamless(sp_sview, addrj, x0, y1, corner2);
tx3 = get_texel_cube_seamless(sp_sview, addrj, x1, y1, corner3);
} else {
tx0 = get_texel_2d(sp_sview, sp_samp, addrj, x0, y0);
tx1 = get_texel_2d(sp_sview, sp_samp, addrj, x1, y0);
tx2 = get_texel_2d(sp_sview, sp_samp, addrj, x0, y1);
tx3 = get_texel_2d(sp_sview, sp_samp, addrj, x1, y1);
}
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
tx0[c], tx1[c],
tx2[c], tx3[c]);
}
 
 
static void
img_filter_cube_array_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x0, y0, x1, y1, layer;
float xw, yw; /* weights */
union tex_tile_address addr;
const float *tx0, *tx1, *tx2, *tx3;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
wrap_array_layer(p, texture->array_size, &layer);
 
tx0 = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y0, layer * 6 + face_id);
tx1 = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y0, layer * 6 + face_id);
tx2 = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y1, layer * 6 + face_id);
tx3 = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y1, layer * 6 + face_id);
 
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
tx0[c], tx1[c],
tx2[c], tx3[c]);
}
 
static void
img_filter_3d_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height, depth;
int x0, x1, y0, y1, z0, z1;
float xw, yw, zw; /* interpolation weights */
union tex_tile_address addr;
const float *tx00, *tx01, *tx02, *tx03, *tx10, *tx11, *tx12, *tx13;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
depth = u_minify(texture->depth0, level);
 
addr.value = 0;
addr.bits.level = level;
 
assert(width > 0);
assert(height > 0);
assert(depth > 0);
 
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
sp_samp->linear_texcoord_p(p, depth, &z0, &z1, &zw);
 
 
tx00 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z0);
tx01 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z0);
tx02 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z0);
tx03 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z0);
tx10 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z1);
tx11 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z1);
tx12 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z1);
tx13 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z1);
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp_3d(xw, yw, zw,
tx00[c], tx01[c],
tx02[c], tx03[c],
tx10[c], tx11[c],
tx12[c], tx13[c]);
}
 
 
/* Calculate level of detail for every fragment,
* with lambda already computed.
* Note that lambda has already been biased by global LOD bias.
* \param biased_lambda per-quad lambda.
* \param lod_in per-fragment lod_bias or explicit_lod.
* \param lod returns the per-fragment lod.
*/
static INLINE void
compute_lod(const struct pipe_sampler_state *sampler,
enum tgsi_sampler_control control,
const float biased_lambda,
const float lod_in[TGSI_QUAD_SIZE],
float lod[TGSI_QUAD_SIZE])
{
float min_lod = sampler->min_lod;
float max_lod = sampler->max_lod;
uint i;
 
switch (control) {
case tgsi_sampler_lod_none:
case tgsi_sampler_lod_zero:
/* XXX FIXME */
case tgsi_sampler_derivs_explicit:
lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(biased_lambda, min_lod, max_lod);
break;
case tgsi_sampler_lod_bias:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
lod[i] = biased_lambda + lod_in[i];
lod[i] = CLAMP(lod[i], min_lod, max_lod);
}
break;
case tgsi_sampler_lod_explicit:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
lod[i] = CLAMP(lod_in[i], min_lod, max_lod);
}
break;
default:
assert(0);
lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
}
}
 
 
/* Calculate level of detail for every fragment.
* \param lod_in per-fragment lod_bias or explicit_lod.
* \param lod results per-fragment lod.
*/
static INLINE void
compute_lambda_lod(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float lod[TGSI_QUAD_SIZE])
{
const struct pipe_sampler_state *sampler = &sp_samp->base;
float lod_bias = sampler->lod_bias;
float min_lod = sampler->min_lod;
float max_lod = sampler->max_lod;
float lambda;
uint i;
 
switch (control) {
case tgsi_sampler_lod_none:
/* XXX FIXME */
case tgsi_sampler_derivs_explicit:
lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias;
lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(lambda, min_lod, max_lod);
break;
case tgsi_sampler_lod_bias:
lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias;
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
lod[i] = lambda + lod_in[i];
lod[i] = CLAMP(lod[i], min_lod, max_lod);
}
break;
case tgsi_sampler_lod_explicit:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
lod[i] = CLAMP(lod_in[i], min_lod, max_lod);
}
break;
case tgsi_sampler_lod_zero:
/* this is all static state in the sampler really need clamp here? */
lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(lod_bias, min_lod, max_lod);
break;
default:
assert(0);
lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
}
}
 
 
static void
mip_filter_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sp_sview->base.texture;
int j;
float lod[TGSI_QUAD_SIZE];
 
compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int level0 = sp_sview->base.u.tex.first_level + (int)lod[j];
 
if (lod[j] < 0.0)
mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.u.tex.first_level,
sp_sview->faces[j], &rgba[0][j]);
 
else if (level0 >= (int) texture->last_level)
min_filter(sp_sview, sp_samp, s[j], t[j], p[j], texture->last_level,
sp_sview->faces[j], &rgba[0][j]);
 
else {
float levelBlend = frac(lod[j]);
float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
int c;
 
min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level0,
sp_sview->faces[j], &rgbax[0][0]);
min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level0+1,
sp_sview->faces[j], &rgbax[0][1]);
 
for (c = 0; c < 4; c++) {
rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
}
}
}
 
if (DEBUG_TEX) {
print_sample_4(__FUNCTION__, rgba);
}
}
 
 
/**
* Compute nearest mipmap level from texcoords.
* Then sample the texture level for four elements of a quad.
* \param c0 the LOD bias factors, or absolute LODs (depending on control)
*/
static void
mip_filter_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sp_sview->base.texture;
float lod[TGSI_QUAD_SIZE];
int j;
 
compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (lod[j] < 0.0)
mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.u.tex.first_level,
sp_sview->faces[j], &rgba[0][j]);
else {
int level = sp_sview->base.u.tex.first_level + (int)(lod[j] + 0.5F);
level = MIN2(level, (int)texture->last_level);
min_filter(sp_sview, sp_samp, s[j], t[j], p[j],
level, sp_sview->faces[j], &rgba[0][j]);
}
}
 
if (DEBUG_TEX) {
print_sample_4(__FUNCTION__, rgba);
}
}
 
 
static void
mip_filter_none(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
float lod[TGSI_QUAD_SIZE];
int j;
 
compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (lod[j] < 0.0) {
mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.u.tex.first_level,
sp_sview->faces[j], &rgba[0][j]);
}
else {
min_filter(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.u.tex.first_level,
sp_sview->faces[j], &rgba[0][j]);
}
}
}
 
 
static void
mip_filter_none_no_filter_select(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
int j;
 
for (j = 0; j < TGSI_QUAD_SIZE; j++)
mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.u.tex.first_level,
sp_sview->faces[j], &rgba[0][j]);
}
 
 
/* For anisotropic filtering */
#define WEIGHT_LUT_SIZE 1024
 
static float *weightLut = NULL;
 
/**
* Creates the look-up table used to speed-up EWA sampling
*/
static void
create_filter_table(void)
{
unsigned i;
if (!weightLut) {
weightLut = (float *) MALLOC(WEIGHT_LUT_SIZE * sizeof(float));
 
for (i = 0; i < WEIGHT_LUT_SIZE; ++i) {
float alpha = 2;
float r2 = (float) i / (float) (WEIGHT_LUT_SIZE - 1);
float weight = (float) exp(-alpha * r2);
weightLut[i] = weight;
}
}
}
 
 
/**
* Elliptical weighted average (EWA) filter for producing high quality
* anisotropic filtered results.
* Based on the Higher Quality Elliptical Weighted Average Filter
* published by Paul S. Heckbert in his Master's Thesis
* "Fundamentals of Texture Mapping and Image Warping" (1989)
*/
static void
img_filter_2d_ewa(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
unsigned level,
const float dudx, const float dvdx,
const float dudy, const float dvdy,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sp_sview->base.texture;
 
// ??? Won't the image filters blow up if level is negative?
unsigned level0 = level > 0 ? level : 0;
float scaling = 1.0f / (1 << level0);
int width = u_minify(texture->width0, level0);
int height = u_minify(texture->height0, level0);
 
float ux = dudx * scaling;
float vx = dvdx * scaling;
float uy = dudy * scaling;
float vy = dvdy * scaling;
 
/* compute ellipse coefficients to bound the region:
* A*x*x + B*x*y + C*y*y = F.
*/
float A = vx*vx+vy*vy+1;
float B = -2*(ux*vx+uy*vy);
float C = ux*ux+uy*uy+1;
float F = A*C-B*B/4.0f;
 
/* check if it is an ellipse */
/* ASSERT(F > 0.0); */
 
/* Compute the ellipse's (u,v) bounding box in texture space */
float d = -B*B+4.0f*C*A;
float box_u = 2.0f / d * sqrtf(d*C*F); /* box_u -> half of bbox with */
float box_v = 2.0f / d * sqrtf(A*d*F); /* box_v -> half of bbox height */
 
float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
float s_buffer[TGSI_QUAD_SIZE];
float t_buffer[TGSI_QUAD_SIZE];
float weight_buffer[TGSI_QUAD_SIZE];
unsigned buffer_next;
int j;
float den; /* = 0.0F; */
float ddq;
float U; /* = u0 - tex_u; */
int v;
 
/* Scale ellipse formula to directly index the Filter Lookup Table.
* i.e. scale so that F = WEIGHT_LUT_SIZE-1
*/
double formScale = (double) (WEIGHT_LUT_SIZE - 1) / F;
A *= formScale;
B *= formScale;
C *= formScale;
/* F *= formScale; */ /* no need to scale F as we don't use it below here */
 
/* For each quad, the du and dx values are the same and so the ellipse is
* also the same. Note that texel/image access can only be performed using
* a quad, i.e. it is not possible to get the pixel value for a single
* tex coord. In order to have a better performance, the access is buffered
* using the s_buffer/t_buffer and weight_buffer. Only when the buffer is
* full, then the pixel values are read from the image.
*/
ddq = 2 * A;
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
/* Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse
* and incrementally update the value of Ax^2+Bxy*Cy^2; when this
* value, q, is less than F, we're inside the ellipse
*/
float tex_u = -0.5F + s[j] * texture->width0 * scaling;
float tex_v = -0.5F + t[j] * texture->height0 * scaling;
 
int u0 = (int) floorf(tex_u - box_u);
int u1 = (int) ceilf(tex_u + box_u);
int v0 = (int) floorf(tex_v - box_v);
int v1 = (int) ceilf(tex_v + box_v);
 
float num[4] = {0.0F, 0.0F, 0.0F, 0.0F};
buffer_next = 0;
den = 0;
U = u0 - tex_u;
for (v = v0; v <= v1; ++v) {
float V = v - tex_v;
float dq = A * (2 * U + 1) + B * V;
float q = (C * V + B * U) * V + A * U * U;
 
int u;
for (u = u0; u <= u1; ++u) {
/* Note that the ellipse has been pre-scaled so F =
* WEIGHT_LUT_SIZE - 1
*/
if (q < WEIGHT_LUT_SIZE) {
/* as a LUT is used, q must never be negative;
* should not happen, though
*/
const int qClamped = q >= 0.0F ? q : 0;
float weight = weightLut[qClamped];
 
weight_buffer[buffer_next] = weight;
s_buffer[buffer_next] = u / ((float) width);
t_buffer[buffer_next] = v / ((float) height);
buffer_next++;
if (buffer_next == TGSI_QUAD_SIZE) {
/* 4 texel coords are in the buffer -> read it now */
unsigned jj;
/* it is assumed that samp->min_img_filter is set to
* img_filter_2d_nearest or one of the
* accelerated img_filter_2d_nearest_XXX functions.
*/
for (jj = 0; jj < buffer_next; jj++) {
min_filter(sp_sview, sp_samp, s_buffer[jj], t_buffer[jj], p[jj],
level, sp_sview->faces[j], &rgba_temp[0][jj]);
num[0] += weight_buffer[jj] * rgba_temp[0][jj];
num[1] += weight_buffer[jj] * rgba_temp[1][jj];
num[2] += weight_buffer[jj] * rgba_temp[2][jj];
num[3] += weight_buffer[jj] * rgba_temp[3][jj];
}
 
buffer_next = 0;
}
 
den += weight;
}
q += dq;
dq += ddq;
}
}
 
/* if the tex coord buffer contains unread values, we will read
* them now.
*/
if (buffer_next > 0) {
unsigned jj;
/* it is assumed that samp->min_img_filter is set to
* img_filter_2d_nearest or one of the
* accelerated img_filter_2d_nearest_XXX functions.
*/
for (jj = 0; jj < buffer_next; jj++) {
min_filter(sp_sview, sp_samp, s_buffer[jj], t_buffer[jj], p[jj],
level, sp_sview->faces[j], &rgba_temp[0][jj]);
num[0] += weight_buffer[jj] * rgba_temp[0][jj];
num[1] += weight_buffer[jj] * rgba_temp[1][jj];
num[2] += weight_buffer[jj] * rgba_temp[2][jj];
num[3] += weight_buffer[jj] * rgba_temp[3][jj];
}
}
 
if (den <= 0.0F) {
/* Reaching this place would mean that no pixels intersected
* the ellipse. This should never happen because the filter
* we use always intersects at least one pixel.
*/
 
/*rgba[0]=0;
rgba[1]=0;
rgba[2]=0;
rgba[3]=0;*/
/* not enough pixels in resampling, resort to direct interpolation */
min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level,
sp_sview->faces[j], &rgba_temp[0][j]);
den = 1;
num[0] = rgba_temp[0][j];
num[1] = rgba_temp[1][j];
num[2] = rgba_temp[2][j];
num[3] = rgba_temp[3][j];
}
 
rgba[0][j] = num[0] / den;
rgba[1][j] = num[1] / den;
rgba[2][j] = num[2] / den;
rgba[3][j] = num[3] / den;
}
}
 
 
/**
* Sample 2D texture using an anisotropic filter.
*/
static void
mip_filter_linear_aniso(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sp_sview->base.texture;
int level0;
float lambda;
float lod[TGSI_QUAD_SIZE];
 
float s_to_u = u_minify(texture->width0, sp_sview->base.u.tex.first_level);
float t_to_v = u_minify(texture->height0, sp_sview->base.u.tex.first_level);
float dudx = (s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]) * s_to_u;
float dudy = (s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]) * s_to_u;
float dvdx = (t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]) * t_to_v;
float dvdy = (t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]) * t_to_v;
if (control == tgsi_sampler_lod_bias ||
control == tgsi_sampler_lod_none ||
/* XXX FIXME */
control == tgsi_sampler_derivs_explicit) {
/* note: instead of working with Px and Py, we will use the
* squared length instead, to avoid sqrt.
*/
float Px2 = dudx * dudx + dvdx * dvdx;
float Py2 = dudy * dudy + dvdy * dvdy;
 
float Pmax2;
float Pmin2;
float e;
const float maxEccentricity = sp_samp->base.max_anisotropy * sp_samp->base.max_anisotropy;
if (Px2 < Py2) {
Pmax2 = Py2;
Pmin2 = Px2;
}
else {
Pmax2 = Px2;
Pmin2 = Py2;
}
/* if the eccentricity of the ellipse is too big, scale up the shorter
* of the two vectors to limit the maximum amount of work per pixel
*/
e = Pmax2 / Pmin2;
if (e > maxEccentricity) {
/* float s=e / maxEccentricity;
minor[0] *= s;
minor[1] *= s;
Pmin2 *= s; */
Pmin2 = Pmax2 / maxEccentricity;
}
/* note: we need to have Pmin=sqrt(Pmin2) here, but we can avoid
* this since 0.5*log(x) = log(sqrt(x))
*/
lambda = 0.5F * util_fast_log2(Pmin2) + sp_samp->base.lod_bias;
compute_lod(&sp_samp->base, control, lambda, lod_in, lod);
}
else {
assert(control == tgsi_sampler_lod_explicit ||
control == tgsi_sampler_lod_zero);
compute_lod(&sp_samp->base, control, sp_samp->base.lod_bias, lod_in, lod);
}
/* XXX: Take into account all lod values.
*/
lambda = lod[0];
level0 = sp_sview->base.u.tex.first_level + (int)lambda;
 
/* If the ellipse covers the whole image, we can
* simply return the average of the whole image.
*/
if (level0 >= (int) texture->last_level) {
int j;
for (j = 0; j < TGSI_QUAD_SIZE; j++)
min_filter(sp_sview, sp_samp, s[j], t[j], p[j], texture->last_level,
sp_sview->faces[j], &rgba[0][j]);
}
else {
/* don't bother interpolating between multiple LODs; it doesn't
* seem to be worth the extra running time.
*/
img_filter_2d_ewa(sp_sview, sp_samp, min_filter, mag_filter,
s, t, p, level0,
dudx, dvdx, dudy, dvdy, rgba);
}
 
if (DEBUG_TEX) {
print_sample_4(__FUNCTION__, rgba);
}
}
 
 
/**
* Specialized version of mip_filter_linear with hard-wired calls to
* 2d lambda calculation and 2d_linear_repeat_POT img filters.
*/
static void
mip_filter_linear_2d_linear_repeat_POT(
struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sp_sview->base.texture;
int j;
float lod[TGSI_QUAD_SIZE];
 
compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int level0 = sp_sview->base.u.tex.first_level + (int)lod[j];
 
/* Catches both negative and large values of level0:
*/
if ((unsigned)level0 >= texture->last_level) {
if (level0 < 0)
img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.u.tex.first_level,
sp_sview->faces[j], &rgba[0][j]);
else
img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.texture->last_level,
sp_sview->faces[j], &rgba[0][j]);
 
}
else {
float levelBlend = frac(lod[j]);
float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
int c;
 
img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j], level0,
sp_sview->faces[j], &rgbax[0][0]);
img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j], level0+1,
sp_sview->faces[j], &rgbax[0][1]);
 
for (c = 0; c < TGSI_NUM_CHANNELS; c++)
rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
}
}
 
if (DEBUG_TEX) {
print_sample_4(__FUNCTION__, rgba);
}
}
 
 
/**
* Do shadow/depth comparisons.
*/
static void
sample_compare(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float c1[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
const struct pipe_sampler_state *sampler = &sp_samp->base;
int j, k0, k1, k2, k3;
float val;
float pc0, pc1, pc2, pc3;
 
/**
* Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
* for 2D Array texture we need to use the 'c0' (aka Q).
* When we sampled the depth texture, the depth value was put into all
* RGBA channels. We look at the red channel here.
*/
 
if (sp_sview->base.texture->target == PIPE_TEXTURE_2D_ARRAY ||
sp_sview->base.texture->target == PIPE_TEXTURE_CUBE) {
pc0 = CLAMP(c0[0], 0.0F, 1.0F);
pc1 = CLAMP(c0[1], 0.0F, 1.0F);
pc2 = CLAMP(c0[2], 0.0F, 1.0F);
pc3 = CLAMP(c0[3], 0.0F, 1.0F);
} else if (sp_sview->base.texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
pc0 = CLAMP(c1[0], 0.0F, 1.0F);
pc1 = CLAMP(c1[1], 0.0F, 1.0F);
pc2 = CLAMP(c1[2], 0.0F, 1.0F);
pc3 = CLAMP(c1[3], 0.0F, 1.0F);
} else {
pc0 = CLAMP(p[0], 0.0F, 1.0F);
pc1 = CLAMP(p[1], 0.0F, 1.0F);
pc2 = CLAMP(p[2], 0.0F, 1.0F);
pc3 = CLAMP(p[3], 0.0F, 1.0F);
}
/* compare four texcoords vs. four texture samples */
switch (sampler->compare_func) {
case PIPE_FUNC_LESS:
k0 = pc0 < rgba[0][0];
k1 = pc1 < rgba[0][1];
k2 = pc2 < rgba[0][2];
k3 = pc3 < rgba[0][3];
break;
case PIPE_FUNC_LEQUAL:
k0 = pc0 <= rgba[0][0];
k1 = pc1 <= rgba[0][1];
k2 = pc2 <= rgba[0][2];
k3 = pc3 <= rgba[0][3];
break;
case PIPE_FUNC_GREATER:
k0 = pc0 > rgba[0][0];
k1 = pc1 > rgba[0][1];
k2 = pc2 > rgba[0][2];
k3 = pc3 > rgba[0][3];
break;
case PIPE_FUNC_GEQUAL:
k0 = pc0 >= rgba[0][0];
k1 = pc1 >= rgba[0][1];
k2 = pc2 >= rgba[0][2];
k3 = pc3 >= rgba[0][3];
break;
case PIPE_FUNC_EQUAL:
k0 = pc0 == rgba[0][0];
k1 = pc1 == rgba[0][1];
k2 = pc2 == rgba[0][2];
k3 = pc3 == rgba[0][3];
break;
case PIPE_FUNC_NOTEQUAL:
k0 = pc0 != rgba[0][0];
k1 = pc1 != rgba[0][1];
k2 = pc2 != rgba[0][2];
k3 = pc3 != rgba[0][3];
break;
case PIPE_FUNC_ALWAYS:
k0 = k1 = k2 = k3 = 1;
break;
case PIPE_FUNC_NEVER:
k0 = k1 = k2 = k3 = 0;
break;
default:
k0 = k1 = k2 = k3 = 0;
assert(0);
break;
}
 
if (sampler->mag_img_filter == PIPE_TEX_FILTER_LINEAR) {
/* convert four pass/fail values to an intensity in [0,1] */
/*
* XXX this doesn't actually make much sense.
* We just average the result of four _pixels_ and output the same
* value for all of the four pixels of the quad.
* This really needs to work on the _samples_ i.e. inside the img filter.
*/
val = 0.25F * (k0 + k1 + k2 + k3);
 
/* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
for (j = 0; j < 4; j++) {
rgba[0][j] = rgba[1][j] = rgba[2][j] = val;
rgba[3][j] = 1.0F;
}
} else {
for (j = 0; j < 4; j++) {
rgba[0][j] = k0;
rgba[1][j] = k1;
rgba[2][j] = k2;
rgba[3][j] = 1.0F;
}
}
}
 
 
static void
do_swizzling(const struct pipe_sampler_view *sview,
float in[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
float out[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
int j;
const unsigned swizzle_r = sview->swizzle_r;
const unsigned swizzle_g = sview->swizzle_g;
const unsigned swizzle_b = sview->swizzle_b;
const unsigned swizzle_a = sview->swizzle_a;
 
switch (swizzle_r) {
case PIPE_SWIZZLE_ZERO:
for (j = 0; j < 4; j++)
out[0][j] = 0.0f;
break;
case PIPE_SWIZZLE_ONE:
for (j = 0; j < 4; j++)
out[0][j] = 1.0f;
break;
default:
assert(swizzle_r < 4);
for (j = 0; j < 4; j++)
out[0][j] = in[swizzle_r][j];
}
 
switch (swizzle_g) {
case PIPE_SWIZZLE_ZERO:
for (j = 0; j < 4; j++)
out[1][j] = 0.0f;
break;
case PIPE_SWIZZLE_ONE:
for (j = 0; j < 4; j++)
out[1][j] = 1.0f;
break;
default:
assert(swizzle_g < 4);
for (j = 0; j < 4; j++)
out[1][j] = in[swizzle_g][j];
}
 
switch (swizzle_b) {
case PIPE_SWIZZLE_ZERO:
for (j = 0; j < 4; j++)
out[2][j] = 0.0f;
break;
case PIPE_SWIZZLE_ONE:
for (j = 0; j < 4; j++)
out[2][j] = 1.0f;
break;
default:
assert(swizzle_b < 4);
for (j = 0; j < 4; j++)
out[2][j] = in[swizzle_b][j];
}
 
switch (swizzle_a) {
case PIPE_SWIZZLE_ZERO:
for (j = 0; j < 4; j++)
out[3][j] = 0.0f;
break;
case PIPE_SWIZZLE_ONE:
for (j = 0; j < 4; j++)
out[3][j] = 1.0f;
break;
default:
assert(swizzle_a < 4);
for (j = 0; j < 4; j++)
out[3][j] = in[swizzle_a][j];
}
}
 
 
static wrap_nearest_func
get_nearest_unorm_wrap(unsigned mode)
{
switch (mode) {
case PIPE_TEX_WRAP_CLAMP:
return wrap_nearest_unorm_clamp;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
return wrap_nearest_unorm_clamp_to_edge;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
return wrap_nearest_unorm_clamp_to_border;
default:
assert(0);
return wrap_nearest_unorm_clamp;
}
}
 
 
static wrap_nearest_func
get_nearest_wrap(unsigned mode)
{
switch (mode) {
case PIPE_TEX_WRAP_REPEAT:
return wrap_nearest_repeat;
case PIPE_TEX_WRAP_CLAMP:
return wrap_nearest_clamp;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
return wrap_nearest_clamp_to_edge;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
return wrap_nearest_clamp_to_border;
case PIPE_TEX_WRAP_MIRROR_REPEAT:
return wrap_nearest_mirror_repeat;
case PIPE_TEX_WRAP_MIRROR_CLAMP:
return wrap_nearest_mirror_clamp;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
return wrap_nearest_mirror_clamp_to_edge;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
return wrap_nearest_mirror_clamp_to_border;
default:
assert(0);
return wrap_nearest_repeat;
}
}
 
 
static wrap_linear_func
get_linear_unorm_wrap(unsigned mode)
{
switch (mode) {
case PIPE_TEX_WRAP_CLAMP:
return wrap_linear_unorm_clamp;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
return wrap_linear_unorm_clamp_to_edge;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
return wrap_linear_unorm_clamp_to_border;
default:
assert(0);
return wrap_linear_unorm_clamp;
}
}
 
 
static wrap_linear_func
get_linear_wrap(unsigned mode)
{
switch (mode) {
case PIPE_TEX_WRAP_REPEAT:
return wrap_linear_repeat;
case PIPE_TEX_WRAP_CLAMP:
return wrap_linear_clamp;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
return wrap_linear_clamp_to_edge;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
return wrap_linear_clamp_to_border;
case PIPE_TEX_WRAP_MIRROR_REPEAT:
return wrap_linear_mirror_repeat;
case PIPE_TEX_WRAP_MIRROR_CLAMP:
return wrap_linear_mirror_clamp;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
return wrap_linear_mirror_clamp_to_edge;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
return wrap_linear_mirror_clamp_to_border;
default:
assert(0);
return wrap_linear_repeat;
}
}
 
 
/**
* Is swizzling needed for the given state key?
*/
static INLINE bool
any_swizzle(const struct pipe_sampler_view *view)
{
return (view->swizzle_r != PIPE_SWIZZLE_RED ||
view->swizzle_g != PIPE_SWIZZLE_GREEN ||
view->swizzle_b != PIPE_SWIZZLE_BLUE ||
view->swizzle_a != PIPE_SWIZZLE_ALPHA);
}
 
 
static img_filter_func
get_img_filter(const struct sp_sampler_view *sp_sview,
const struct pipe_sampler_state *sampler,
unsigned filter)
{
switch (sp_sview->base.texture->target) {
case PIPE_BUFFER:
case PIPE_TEXTURE_1D:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_1d_nearest;
else
return img_filter_1d_linear;
break;
case PIPE_TEXTURE_1D_ARRAY:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_1d_array_nearest;
else
return img_filter_1d_array_linear;
break;
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_RECT:
/* Try for fast path:
*/
if (sp_sview->pot2d &&
sampler->wrap_s == sampler->wrap_t &&
sampler->normalized_coords)
{
switch (sampler->wrap_s) {
case PIPE_TEX_WRAP_REPEAT:
switch (filter) {
case PIPE_TEX_FILTER_NEAREST:
return img_filter_2d_nearest_repeat_POT;
case PIPE_TEX_FILTER_LINEAR:
return img_filter_2d_linear_repeat_POT;
default:
break;
}
break;
case PIPE_TEX_WRAP_CLAMP:
switch (filter) {
case PIPE_TEX_FILTER_NEAREST:
return img_filter_2d_nearest_clamp_POT;
default:
break;
}
}
}
/* Otherwise use default versions:
*/
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_2d_nearest;
else
return img_filter_2d_linear;
break;
case PIPE_TEXTURE_2D_ARRAY:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_2d_array_nearest;
else
return img_filter_2d_array_linear;
break;
case PIPE_TEXTURE_CUBE:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_cube_nearest;
else
return img_filter_cube_linear;
break;
case PIPE_TEXTURE_CUBE_ARRAY:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_cube_array_nearest;
else
return img_filter_cube_array_linear;
break;
case PIPE_TEXTURE_3D:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_3d_nearest;
else
return img_filter_3d_linear;
break;
default:
assert(0);
return img_filter_1d_nearest;
}
}
 
 
static void
sample_mip(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
mip_filter_func mip_filter;
img_filter_func min_img_filter = NULL;
img_filter_func mag_img_filter = NULL;
 
if (sp_sview->pot2d & sp_samp->min_mag_equal_repeat_linear) {
mip_filter = mip_filter_linear_2d_linear_repeat_POT;
}
else {
mip_filter = sp_samp->mip_filter;
min_img_filter = get_img_filter(sp_sview, &sp_samp->base, sp_samp->min_img_filter);
if (sp_samp->min_mag_equal) {
mag_img_filter = min_img_filter;
}
else {
mag_img_filter = get_img_filter(sp_sview, &sp_samp->base, sp_samp->base.mag_img_filter);
}
}
 
mip_filter(sp_sview, sp_samp, min_img_filter, mag_img_filter,
s, t, p, c0, lod, control, rgba);
 
if (sp_samp->base.compare_mode != PIPE_TEX_COMPARE_NONE) {
sample_compare(sp_sview, sp_samp, s, t, p, c0, lod, control, rgba);
}
 
if (sp_sview->need_swizzle) {
float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
memcpy(rgba_temp, rgba, sizeof(rgba_temp));
do_swizzling(&sp_sview->base, rgba_temp, rgba);
}
 
}
 
 
/**
* Use 3D texcoords to choose a cube face, then sample the 2D cube faces.
* Put face info into the sampler faces[] array.
*/
static void
sample_cube(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float c1[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
unsigned j;
float ssss[4], tttt[4];
 
/* Not actually used, but the intermediate steps that do the
* dereferencing don't know it.
*/
static float pppp[4] = { 0, 0, 0, 0 };
 
pppp[0] = c0[0];
pppp[1] = c0[1];
pppp[2] = c0[2];
pppp[3] = c0[3];
/*
major axis
direction target sc tc ma
---------- ------------------------------- --- --- ---
+rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
-rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
+ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
-ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
+rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
-rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
*/
 
/* Choose the cube face and compute new s/t coords for the 2D face.
*
* Use the same cube face for all four pixels in the quad.
*
* This isn't ideal, but if we want to use a different cube face
* per pixel in the quad, we'd have to also compute the per-face
* LOD here too. That's because the four post-face-selection
* texcoords are no longer related to each other (they're
* per-face!) so we can't use subtraction to compute the partial
* deriviates to compute the LOD. Doing so (near cube edges
* anyway) gives us pretty much random values.
*/
{
/* use the average of the four pixel's texcoords to choose the face */
const float rx = 0.25F * (s[0] + s[1] + s[2] + s[3]);
const float ry = 0.25F * (t[0] + t[1] + t[2] + t[3]);
const float rz = 0.25F * (p[0] + p[1] + p[2] + p[3]);
const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
 
if (arx >= ary && arx >= arz) {
float sign = (rx >= 0.0F) ? 1.0F : -1.0F;
uint face = (rx >= 0.0F) ? PIPE_TEX_FACE_POS_X : PIPE_TEX_FACE_NEG_X;
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
const float ima = -0.5F / fabsf(s[j]);
ssss[j] = sign * p[j] * ima + 0.5F;
tttt[j] = t[j] * ima + 0.5F;
sp_sview->faces[j] = face;
}
}
else if (ary >= arx && ary >= arz) {
float sign = (ry >= 0.0F) ? 1.0F : -1.0F;
uint face = (ry >= 0.0F) ? PIPE_TEX_FACE_POS_Y : PIPE_TEX_FACE_NEG_Y;
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
const float ima = -0.5F / fabsf(t[j]);
ssss[j] = -s[j] * ima + 0.5F;
tttt[j] = sign * -p[j] * ima + 0.5F;
sp_sview->faces[j] = face;
}
}
else {
float sign = (rz >= 0.0F) ? 1.0F : -1.0F;
uint face = (rz >= 0.0F) ? PIPE_TEX_FACE_POS_Z : PIPE_TEX_FACE_NEG_Z;
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
const float ima = -0.5F / fabsf(p[j]);
ssss[j] = sign * -s[j] * ima + 0.5F;
tttt[j] = t[j] * ima + 0.5F;
sp_sview->faces[j] = face;
}
}
}
 
sample_mip(sp_sview, sp_samp, ssss, tttt, pppp, c0, c1, control, rgba);
}
 
 
static void
sp_get_dims(struct sp_sampler_view *sp_sview, int level,
int dims[4])
{
const struct pipe_sampler_view *view = &sp_sview->base;
const struct pipe_resource *texture = view->texture;
 
/* undefined according to EXT_gpu_program */
level += view->u.tex.first_level;
if (level > view->u.tex.last_level)
return;
 
dims[0] = u_minify(texture->width0, level);
 
switch(texture->target) {
case PIPE_TEXTURE_1D_ARRAY:
dims[1] = view->u.tex.last_layer - view->u.tex.first_layer + 1;
/* fallthrough */
case PIPE_TEXTURE_1D:
return;
case PIPE_TEXTURE_2D_ARRAY:
dims[2] = view->u.tex.last_layer - view->u.tex.first_layer + 1;
/* fallthrough */
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_CUBE:
case PIPE_TEXTURE_RECT:
dims[1] = u_minify(texture->height0, level);
return;
case PIPE_TEXTURE_3D:
dims[1] = u_minify(texture->height0, level);
dims[2] = u_minify(texture->depth0, level);
return;
case PIPE_TEXTURE_CUBE_ARRAY:
dims[1] = u_minify(texture->height0, level);
dims[2] = (view->u.tex.last_layer - view->u.tex.first_layer + 1) / 6;
break;
case PIPE_BUFFER:
dims[0] /= util_format_get_blocksize(view->format);
return;
default:
assert(!"unexpected texture target in sp_get_dims()");
return;
}
}
 
/**
* This function is only used for getting unfiltered texels via the
* TXF opcode. The GL spec says that out-of-bounds texel fetches
* produce undefined results. Instead of crashing, lets just clamp
* coords to the texture image size.
*/
static void
sp_get_texels(struct sp_sampler_view *sp_sview,
const int v_i[TGSI_QUAD_SIZE],
const int v_j[TGSI_QUAD_SIZE],
const int v_k[TGSI_QUAD_SIZE],
const int lod[TGSI_QUAD_SIZE],
const int8_t offset[3],
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
union tex_tile_address addr;
const struct pipe_resource *texture = sp_sview->base.texture;
int j, c;
const float *tx;
int width, height, depth;
 
addr.value = 0;
/* TODO write a better test for LOD */
addr.bits.level = lod[0];
 
width = u_minify(texture->width0, addr.bits.level);
height = u_minify(texture->height0, addr.bits.level);
depth = u_minify(texture->depth0, addr.bits.level);
 
switch(texture->target) {
case PIPE_BUFFER:
case PIPE_TEXTURE_1D:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
tx = get_texel_2d_no_border(sp_sview, addr, x, 0);
for (c = 0; c < 4; c++) {
rgba[c][j] = tx[c];
}
}
break;
case PIPE_TEXTURE_1D_ARRAY:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
int y = CLAMP(v_j[j], sp_sview->base.u.tex.first_layer, sp_sview->base.u.tex.last_layer);
tx = get_texel_2d_no_border(sp_sview, addr, x, y);
for (c = 0; c < 4; c++) {
rgba[c][j] = tx[c];
}
}
break;
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_RECT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
tx = get_texel_2d_no_border(sp_sview, addr, x, y);
for (c = 0; c < 4; c++) {
rgba[c][j] = tx[c];
}
}
break;
case PIPE_TEXTURE_2D_ARRAY:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
int layer = CLAMP(v_k[j], sp_sview->base.u.tex.first_layer, sp_sview->base.u.tex.last_layer);
tx = get_texel_3d_no_border(sp_sview, addr, x, y, layer);
for (c = 0; c < 4; c++) {
rgba[c][j] = tx[c];
}
}
break;
case PIPE_TEXTURE_3D:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
int z = CLAMP(v_k[j] + offset[2], 0, depth - 1);
tx = get_texel_3d_no_border(sp_sview, addr, x, y, z);
for (c = 0; c < 4; c++) {
rgba[c][j] = tx[c];
}
}
break;
case PIPE_TEXTURE_CUBE: /* TXF can't work on CUBE according to spec */
default:
assert(!"Unknown or CUBE texture type in TXF processing\n");
break;
}
 
if (sp_sview->need_swizzle) {
float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
memcpy(rgba_temp, rgba, sizeof(rgba_temp));
do_swizzling(&sp_sview->base, rgba_temp, rgba);
}
}
 
 
void *
softpipe_create_sampler_state(struct pipe_context *pipe,
const struct pipe_sampler_state *sampler)
{
struct sp_sampler *samp = CALLOC_STRUCT(sp_sampler);
 
samp->base = *sampler;
 
/* Note that (for instance) linear_texcoord_s and
* nearest_texcoord_s may be active at the same time, if the
* sampler min_img_filter differs from its mag_img_filter.
*/
if (sampler->normalized_coords) {
samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s );
samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t );
samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r );
 
samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s );
samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t );
samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r );
}
else {
samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s );
samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t );
samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r );
 
samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s );
samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t );
samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r );
}
 
samp->min_img_filter = sampler->min_img_filter;
 
switch (sampler->min_mip_filter) {
case PIPE_TEX_MIPFILTER_NONE:
if (sampler->min_img_filter == sampler->mag_img_filter)
samp->mip_filter = mip_filter_none_no_filter_select;
else
samp->mip_filter = mip_filter_none;
break;
 
case PIPE_TEX_MIPFILTER_NEAREST:
samp->mip_filter = mip_filter_nearest;
break;
 
case PIPE_TEX_MIPFILTER_LINEAR:
if (sampler->min_img_filter == sampler->mag_img_filter &&
sampler->normalized_coords &&
sampler->wrap_s == PIPE_TEX_WRAP_REPEAT &&
sampler->wrap_t == PIPE_TEX_WRAP_REPEAT &&
sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR &&
sampler->max_anisotropy <= 1) {
samp->min_mag_equal_repeat_linear = TRUE;
}
samp->mip_filter = mip_filter_linear;
 
/* Anisotropic filtering extension. */
if (sampler->max_anisotropy > 1) {
samp->mip_filter = mip_filter_linear_aniso;
 
/* Override min_img_filter:
* min_img_filter needs to be set to NEAREST since we need to access
* each texture pixel as it is and weight it later; using linear
* filters will have incorrect results.
* By setting the filter to NEAREST here, we can avoid calling the
* generic img_filter_2d_nearest in the anisotropic filter function,
* making it possible to use one of the accelerated implementations
*/
samp->min_img_filter = PIPE_TEX_FILTER_NEAREST;
 
/* on first access create the lookup table containing the filter weights. */
if (!weightLut) {
create_filter_table();
}
}
break;
}
if (samp->min_img_filter == sampler->mag_img_filter) {
samp->min_mag_equal = TRUE;
}
 
return (void *)samp;
}
 
 
compute_lambda_func
softpipe_get_lambda_func(const struct pipe_sampler_view *view, unsigned shader)
{
if (shader != PIPE_SHADER_FRAGMENT)
return compute_lambda_vert;
 
switch (view->texture->target) {
case PIPE_BUFFER:
case PIPE_TEXTURE_1D:
case PIPE_TEXTURE_1D_ARRAY:
return compute_lambda_1d;
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_2D_ARRAY:
case PIPE_TEXTURE_RECT:
case PIPE_TEXTURE_CUBE:
case PIPE_TEXTURE_CUBE_ARRAY:
return compute_lambda_2d;
case PIPE_TEXTURE_3D:
return compute_lambda_3d;
default:
assert(0);
return compute_lambda_1d;
}
}
 
 
struct pipe_sampler_view *
softpipe_create_sampler_view(struct pipe_context *pipe,
struct pipe_resource *resource,
const struct pipe_sampler_view *templ)
{
struct sp_sampler_view *sview = CALLOC_STRUCT(sp_sampler_view);
struct softpipe_resource *spr = (struct softpipe_resource *)resource;
 
if (sview) {
struct pipe_sampler_view *view = &sview->base;
*view = *templ;
view->reference.count = 1;
view->texture = NULL;
pipe_resource_reference(&view->texture, resource);
view->context = pipe;
 
if (any_swizzle(view)) {
sview->need_swizzle = TRUE;
}
 
if (resource->target == PIPE_TEXTURE_CUBE ||
resource->target == PIPE_TEXTURE_CUBE_ARRAY)
sview->get_samples = sample_cube;
else {
sview->get_samples = sample_mip;
}
sview->pot2d = spr->pot &&
(resource->target == PIPE_TEXTURE_2D ||
resource->target == PIPE_TEXTURE_RECT);
 
sview->xpot = util_logbase2( resource->width0 );
sview->ypot = util_logbase2( resource->height0 );
}
 
return (struct pipe_sampler_view *) sview;
}
 
 
static void
sp_tgsi_get_dims(struct tgsi_sampler *tgsi_sampler,
const unsigned sview_index,
int level, int dims[4])
{
struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
 
assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
/* TODO should have defined behavior if no texture is bound. */
sp_get_dims(&sp_samp->sp_sview[sview_index], level, dims);
}
 
 
static void
sp_tgsi_get_samples(struct tgsi_sampler *tgsi_sampler,
const unsigned sview_index,
const unsigned sampler_index,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod[TGSI_QUAD_SIZE],
float derivs[3][2][TGSI_QUAD_SIZE],
const int8_t offset[3],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
 
assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
assert(sampler_index < PIPE_MAX_SAMPLERS);
assert(sp_samp->sp_sampler[sampler_index]);
/* FIXME should have defined behavior if no texture is bound. */
assert(sp_samp->sp_sview[sview_index].get_samples);
sp_samp->sp_sview[sview_index].get_samples(&sp_samp->sp_sview[sview_index],
sp_samp->sp_sampler[sampler_index],
s, t, p, c0, lod, control, rgba);
}
 
 
static void
sp_tgsi_get_texel(struct tgsi_sampler *tgsi_sampler,
const unsigned sview_index,
const int i[TGSI_QUAD_SIZE],
const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE],
const int lod[TGSI_QUAD_SIZE], const int8_t offset[3],
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
 
assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
/* FIXME should have defined behavior if no texture is bound. */
assert(sp_samp->sp_sview[sview_index].base.texture);
sp_get_texels(&sp_samp->sp_sview[sview_index], i, j, k, lod, offset, rgba);
}
 
 
struct sp_tgsi_sampler *
sp_create_tgsi_sampler(void)
{
struct sp_tgsi_sampler *samp = CALLOC_STRUCT(sp_tgsi_sampler);
if (!samp)
return NULL;
 
samp->base.get_dims = sp_tgsi_get_dims;
samp->base.get_samples = sp_tgsi_get_samples;
samp->base.get_texel = sp_tgsi_get_texel;
 
return samp;
}
 
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_tex_sample.h
0,0 → 1,167
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2010 VMware, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef SP_TEX_SAMPLE_H
#define SP_TEX_SAMPLE_H
 
 
#include "tgsi/tgsi_exec.h"
 
 
struct sp_sampler_view;
struct sp_sampler;
 
typedef void (*wrap_nearest_func)(float s,
unsigned size,
int *icoord);
 
typedef void (*wrap_linear_func)(float s,
unsigned size,
int *icoord0,
int *icoord1,
float *w);
 
typedef float (*compute_lambda_func)(const struct sp_sampler_view *sp_sview,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE]);
 
typedef void (*img_filter_func)(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba);
 
typedef void (*mip_filter_func)(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
 
 
typedef void (*filter_func)(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
 
 
typedef void (*fetch_func)(struct sp_sampler_view *sp_sview,
const int i[TGSI_QUAD_SIZE],
const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE],
const int lod[TGSI_QUAD_SIZE], const int8_t offset[3],
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
 
 
struct sp_sampler_view
{
struct pipe_sampler_view base;
 
/* For sp_get_samples_2d_linear_POT:
*/
unsigned xpot;
unsigned ypot;
 
boolean need_swizzle;
boolean pot2d;
 
filter_func get_samples;
 
/* this is just abusing the sampler_view object as local storage */
unsigned faces[TGSI_QUAD_SIZE];
 
/* these are different per shader type */
struct softpipe_tex_tile_cache *cache;
compute_lambda_func compute_lambda;
 
};
 
 
struct sp_sampler {
struct pipe_sampler_state base;
 
boolean min_mag_equal_repeat_linear;
boolean min_mag_equal;
unsigned min_img_filter;
 
wrap_nearest_func nearest_texcoord_s;
wrap_nearest_func nearest_texcoord_t;
wrap_nearest_func nearest_texcoord_p;
 
wrap_linear_func linear_texcoord_s;
wrap_linear_func linear_texcoord_t;
wrap_linear_func linear_texcoord_p;
 
mip_filter_func mip_filter;
};
 
 
/**
* Subclass of tgsi_sampler
*/
struct sp_tgsi_sampler
{
struct tgsi_sampler base; /**< base class */
struct sp_sampler *sp_sampler[PIPE_MAX_SAMPLERS];
struct sp_sampler_view sp_sview[PIPE_MAX_SHADER_SAMPLER_VIEWS];
 
};
 
compute_lambda_func
softpipe_get_lambda_func(const struct pipe_sampler_view *view, unsigned shader);
 
 
void *
softpipe_create_sampler_state(struct pipe_context *pipe,
const struct pipe_sampler_state *sampler);
 
 
struct pipe_sampler_view *
softpipe_create_sampler_view(struct pipe_context *pipe,
struct pipe_resource *resource,
const struct pipe_sampler_view *templ);
 
 
struct sp_tgsi_sampler *
sp_create_tgsi_sampler(void);
 
 
#endif /* SP_TEX_SAMPLE_H */
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_tex_tile_cache.c
0,0 → 1,296
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/**
* Texture tile caching.
*
* Author:
* Brian Paul
*/
 
#include "util/u_inlines.h"
#include "util/u_memory.h"
#include "util/u_tile.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "sp_context.h"
#include "sp_texture.h"
#include "sp_tex_tile_cache.h"
 
 
struct softpipe_tex_tile_cache *
sp_create_tex_tile_cache( struct pipe_context *pipe )
{
struct softpipe_tex_tile_cache *tc;
uint pos;
 
/* make sure max texture size works */
assert((TEX_TILE_SIZE << TEX_ADDR_BITS) >= (1 << (SP_MAX_TEXTURE_2D_LEVELS-1)));
 
tc = CALLOC_STRUCT( softpipe_tex_tile_cache );
if (tc) {
tc->pipe = pipe;
for (pos = 0; pos < Elements(tc->entries); pos++) {
tc->entries[pos].addr.bits.invalid = 1;
}
tc->last_tile = &tc->entries[0]; /* any tile */
}
return tc;
}
 
 
void
sp_destroy_tex_tile_cache(struct softpipe_tex_tile_cache *tc)
{
if (tc) {
uint pos;
 
for (pos = 0; pos < Elements(tc->entries); pos++) {
/*assert(tc->entries[pos].x < 0);*/
}
if (tc->transfer) {
tc->pipe->transfer_unmap(tc->pipe, tc->transfer);
}
if (tc->tex_trans) {
tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans);
}
 
FREE( tc );
}
}
 
 
/**
* Invalidate all cached tiles for the cached texture.
* Should be called when the texture is modified.
*/
void
sp_tex_tile_cache_validate_texture(struct softpipe_tex_tile_cache *tc)
{
unsigned i;
 
assert(tc);
assert(tc->texture);
 
for (i = 0; i < Elements(tc->entries); i++) {
tc->entries[i].addr.bits.invalid = 1;
}
}
 
static boolean
sp_tex_tile_is_compat_view(struct softpipe_tex_tile_cache *tc,
struct pipe_sampler_view *view)
{
if (!view)
return FALSE;
return (tc->texture == view->texture &&
tc->format == view->format &&
tc->swizzle_r == view->swizzle_r &&
tc->swizzle_g == view->swizzle_g &&
tc->swizzle_b == view->swizzle_b &&
tc->swizzle_a == view->swizzle_a);
}
 
/**
* Specify the sampler view to cache.
*/
void
sp_tex_tile_cache_set_sampler_view(struct softpipe_tex_tile_cache *tc,
struct pipe_sampler_view *view)
{
struct pipe_resource *texture = view ? view->texture : NULL;
uint i;
 
assert(!tc->transfer);
 
if (!sp_tex_tile_is_compat_view(tc, view)) {
pipe_resource_reference(&tc->texture, texture);
 
if (tc->tex_trans_map) {
tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans);
tc->tex_trans = NULL;
tc->tex_trans_map = NULL;
}
 
if (view) {
tc->swizzle_r = view->swizzle_r;
tc->swizzle_g = view->swizzle_g;
tc->swizzle_b = view->swizzle_b;
tc->swizzle_a = view->swizzle_a;
tc->format = view->format;
}
 
/* mark as entries as invalid/empty */
/* XXX we should try to avoid this when the teximage hasn't changed */
for (i = 0; i < Elements(tc->entries); i++) {
tc->entries[i].addr.bits.invalid = 1;
}
 
tc->tex_face = -1; /* any invalid value here */
}
}
 
 
 
 
/**
* Flush the tile cache: write all dirty tiles back to the transfer.
* any tiles "flagged" as cleared will be "really" cleared.
*/
void
sp_flush_tex_tile_cache(struct softpipe_tex_tile_cache *tc)
{
int pos;
 
if (tc->texture) {
/* caching a texture, mark all entries as empty */
for (pos = 0; pos < Elements(tc->entries); pos++) {
tc->entries[pos].addr.bits.invalid = 1;
}
tc->tex_face = -1;
}
 
}
 
 
/**
* Given the texture face, level, zslice, x and y values, compute
* the cache entry position/index where we'd hope to find the
* cached texture tile.
* This is basically a direct-map cache.
* XXX There's probably lots of ways in which we can improve this.
*/
static INLINE uint
tex_cache_pos( union tex_tile_address addr )
{
uint entry = (addr.bits.x +
addr.bits.y * 9 +
addr.bits.z * 3 +
addr.bits.face +
addr.bits.level * 7);
 
return entry % NUM_TEX_TILE_ENTRIES;
}
 
/**
* Similar to sp_get_cached_tile() but for textures.
* Tiles are read-only and indexed with more params.
*/
const struct softpipe_tex_cached_tile *
sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc,
union tex_tile_address addr )
{
struct softpipe_tex_cached_tile *tile;
boolean zs = util_format_is_depth_or_stencil(tc->format);
 
tile = tc->entries + tex_cache_pos( addr );
 
if (addr.value != tile->addr.value) {
 
/* cache miss. Most misses are because we've invalidated the
* texture cache previously -- most commonly on binding a new
* texture. Currently we effectively flush the cache on texture
* bind.
*/
#if 0
_debug_printf("miss at %u: x=%d y=%d z=%d face=%d level=%d\n"
" tile %u: x=%d y=%d z=%d face=%d level=%d\n",
pos, x/TILE_SIZE, y/TILE_SIZE, z, face, level,
pos, tile->addr.bits.x, tile->addr.bits.y, tile->z, tile->face, tile->level);
#endif
 
/* check if we need to get a new transfer */
if (!tc->tex_trans ||
tc->tex_face != addr.bits.face ||
tc->tex_level != addr.bits.level ||
tc->tex_z != addr.bits.z) {
/* get new transfer (view into texture) */
unsigned width, height, layer;
 
if (tc->tex_trans_map) {
tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans);
tc->tex_trans = NULL;
tc->tex_trans_map = NULL;
}
 
width = u_minify(tc->texture->width0, addr.bits.level);
if (tc->texture->target == PIPE_TEXTURE_1D_ARRAY) {
height = tc->texture->array_size;
layer = 0;
}
else {
height = u_minify(tc->texture->height0, addr.bits.level);
layer = addr.bits.face + addr.bits.z;
}
 
tc->tex_trans_map =
pipe_transfer_map(tc->pipe, tc->texture,
addr.bits.level,
layer,
PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED,
0, 0, width, height, &tc->tex_trans);
 
tc->tex_face = addr.bits.face;
tc->tex_level = addr.bits.level;
tc->tex_z = addr.bits.z;
}
 
/* Get tile from the transfer (view into texture), explicitly passing
* the image format.
*/
if (!zs && util_format_is_pure_uint(tc->format)) {
pipe_get_tile_ui_format(tc->tex_trans, tc->tex_trans_map,
addr.bits.x * TEX_TILE_SIZE,
addr.bits.y * TEX_TILE_SIZE,
TEX_TILE_SIZE,
TEX_TILE_SIZE,
tc->format,
(unsigned *) tile->data.colorui);
} else if (!zs && util_format_is_pure_sint(tc->format)) {
pipe_get_tile_i_format(tc->tex_trans, tc->tex_trans_map,
addr.bits.x * TEX_TILE_SIZE,
addr.bits.y * TEX_TILE_SIZE,
TEX_TILE_SIZE,
TEX_TILE_SIZE,
tc->format,
(int *) tile->data.colori);
} else {
pipe_get_tile_rgba_format(tc->tex_trans, tc->tex_trans_map,
addr.bits.x * TEX_TILE_SIZE,
addr.bits.y * TEX_TILE_SIZE,
TEX_TILE_SIZE,
TEX_TILE_SIZE,
tc->format,
(float *) tile->data.color);
}
tile->addr = addr;
}
 
tc->last_tile = tile;
return tile;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_tex_tile_cache.h
0,0 → 1,164
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef SP_TEX_TILE_CACHE_H
#define SP_TEX_TILE_CACHE_H
 
 
#include "pipe/p_compiler.h"
#include "sp_limits.h"
 
 
struct softpipe_context;
struct softpipe_tex_tile_cache;
 
 
/**
* Cache tile size (width and height). This needs to be a power of two.
*/
#define TEX_TILE_SIZE_LOG2 5
#define TEX_TILE_SIZE (1 << TEX_TILE_SIZE_LOG2)
 
 
#define TEX_ADDR_BITS (SP_MAX_TEXTURE_2D_LEVELS - 1 - TEX_TILE_SIZE_LOG2)
#define TEX_Z_BITS (SP_MAX_TEXTURE_2D_LEVELS - 1)
 
/**
* Texture tile address as a union for fast compares.
*/
union tex_tile_address {
struct {
unsigned x:TEX_ADDR_BITS; /* 16K / TILE_SIZE */
unsigned y:TEX_ADDR_BITS; /* 16K / TILE_SIZE */
unsigned z:TEX_Z_BITS; /* 16K -- z not tiled */
unsigned face:3;
unsigned level:4;
unsigned invalid:1;
} bits;
uint64_t value;
};
 
 
struct softpipe_tex_cached_tile
{
union tex_tile_address addr;
union {
float color[TEX_TILE_SIZE][TEX_TILE_SIZE][4];
unsigned int colorui[TEX_TILE_SIZE][TEX_TILE_SIZE][4];
int colori[TEX_TILE_SIZE][TEX_TILE_SIZE][4];
} data;
};
 
/*
* The number of cache entries.
* Should not be decreased to lower than 16, and even that
* seems too low to avoid cache thrashing in some cases (because
* the cache is direct mapped, see tex_cache_pos() function).
*/
#define NUM_TEX_TILE_ENTRIES 16
 
struct softpipe_tex_tile_cache
{
struct pipe_context *pipe;
struct pipe_transfer *transfer;
void *transfer_map;
 
struct pipe_resource *texture; /**< if caching a texture */
unsigned timestamp;
 
struct softpipe_tex_cached_tile entries[NUM_TEX_TILE_ENTRIES];
 
struct pipe_transfer *tex_trans;
void *tex_trans_map;
int tex_face, tex_level, tex_z;
 
unsigned swizzle_r;
unsigned swizzle_g;
unsigned swizzle_b;
unsigned swizzle_a;
enum pipe_format format;
 
struct softpipe_tex_cached_tile *last_tile; /**< most recently retrieved tile */
};
 
 
extern struct softpipe_tex_tile_cache *
sp_create_tex_tile_cache( struct pipe_context *pipe );
 
extern void
sp_destroy_tex_tile_cache(struct softpipe_tex_tile_cache *tc);
 
extern void
sp_tex_tile_cache_set_sampler_view(struct softpipe_tex_tile_cache *tc,
struct pipe_sampler_view *view);
 
void
sp_tex_tile_cache_validate_texture(struct softpipe_tex_tile_cache *tc);
 
extern void
sp_flush_tex_tile_cache(struct softpipe_tex_tile_cache *tc);
 
 
 
extern const struct softpipe_tex_cached_tile *
sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc,
union tex_tile_address addr );
 
static INLINE union tex_tile_address
tex_tile_address( unsigned x,
unsigned y,
unsigned z,
unsigned face,
unsigned level )
{
union tex_tile_address addr;
 
addr.value = 0;
addr.bits.x = x / TEX_TILE_SIZE;
addr.bits.y = y / TEX_TILE_SIZE;
addr.bits.z = z;
addr.bits.face = face;
addr.bits.level = level;
 
return addr;
}
 
/* Quickly retrieve tile if it matches last lookup.
*/
static INLINE const struct softpipe_tex_cached_tile *
sp_get_cached_tile_tex(struct softpipe_tex_tile_cache *tc,
union tex_tile_address addr )
{
if (tc->last_tile->addr.value == addr.value)
return tc->last_tile;
 
return sp_find_cached_tile_tex( tc, addr );
}
 
 
#endif /* SP_TEX_TILE_CACHE_H */
 
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_texture.c
0,0 → 1,526
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
* Michel Dänzer <michel@tungstengraphics.com>
*/
 
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
 
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_transfer.h"
 
#include "sp_context.h"
#include "sp_flush.h"
#include "sp_texture.h"
#include "sp_screen.h"
 
#include "state_tracker/sw_winsys.h"
 
 
/**
* Conventional allocation path for non-display textures:
* Use a simple, maximally packed layout.
*/
static boolean
softpipe_resource_layout(struct pipe_screen *screen,
struct softpipe_resource *spr,
boolean allocate)
{
struct pipe_resource *pt = &spr->base;
unsigned level;
unsigned width = pt->width0;
unsigned height = pt->height0;
unsigned depth = pt->depth0;
unsigned buffer_size = 0;
 
for (level = 0; level <= pt->last_level; level++) {
unsigned slices;
 
if (pt->target == PIPE_TEXTURE_CUBE)
slices = 6;
else if (pt->target == PIPE_TEXTURE_3D)
slices = depth;
else
slices = pt->array_size;
 
spr->stride[level] = util_format_get_stride(pt->format, width);
 
spr->level_offset[level] = buffer_size;
 
buffer_size += (util_format_get_nblocksy(pt->format, height) *
slices * spr->stride[level]);
 
width = u_minify(width, 1);
height = u_minify(height, 1);
depth = u_minify(depth, 1);
}
 
if (buffer_size > SP_MAX_TEXTURE_SIZE)
return FALSE;
 
if (allocate) {
spr->data = align_malloc(buffer_size, 16);
return spr->data != NULL;
}
else {
return TRUE;
}
}
 
 
/**
* Check the size of the texture specified by 'res'.
* \return TRUE if OK, FALSE if too large.
*/
static boolean
softpipe_can_create_resource(struct pipe_screen *screen,
const struct pipe_resource *res)
{
struct softpipe_resource spr;
memset(&spr, 0, sizeof(spr));
spr.base = *res;
return softpipe_resource_layout(screen, &spr, FALSE);
}
 
 
/**
* Texture layout for simple color buffers.
*/
static boolean
softpipe_displaytarget_layout(struct pipe_screen *screen,
struct softpipe_resource *spr)
{
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
 
/* Round up the surface size to a multiple of the tile size?
*/
spr->dt = winsys->displaytarget_create(winsys,
spr->base.bind,
spr->base.format,
spr->base.width0,
spr->base.height0,
16,
&spr->stride[0] );
 
return spr->dt != NULL;
}
 
 
/**
* Create new pipe_resource given the template information.
*/
static struct pipe_resource *
softpipe_resource_create(struct pipe_screen *screen,
const struct pipe_resource *templat)
{
struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource);
if (!spr)
return NULL;
 
assert(templat->format != PIPE_FORMAT_NONE);
 
spr->base = *templat;
pipe_reference_init(&spr->base.reference, 1);
spr->base.screen = screen;
 
spr->pot = (util_is_power_of_two(templat->width0) &&
util_is_power_of_two(templat->height0) &&
util_is_power_of_two(templat->depth0));
 
if (spr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT |
PIPE_BIND_SHARED)) {
if (!softpipe_displaytarget_layout(screen, spr))
goto fail;
}
else {
if (!softpipe_resource_layout(screen, spr, TRUE))
goto fail;
}
return &spr->base;
 
fail:
FREE(spr);
return NULL;
}
 
 
static void
softpipe_resource_destroy(struct pipe_screen *pscreen,
struct pipe_resource *pt)
{
struct softpipe_screen *screen = softpipe_screen(pscreen);
struct softpipe_resource *spr = softpipe_resource(pt);
 
if (spr->dt) {
/* display target */
struct sw_winsys *winsys = screen->winsys;
winsys->displaytarget_destroy(winsys, spr->dt);
}
else if (!spr->userBuffer) {
/* regular texture */
align_free(spr->data);
}
 
FREE(spr);
}
 
 
static struct pipe_resource *
softpipe_resource_from_handle(struct pipe_screen *screen,
const struct pipe_resource *templat,
struct winsys_handle *whandle)
{
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource);
if (!spr)
return NULL;
 
spr->base = *templat;
pipe_reference_init(&spr->base.reference, 1);
spr->base.screen = screen;
 
spr->pot = (util_is_power_of_two(templat->width0) &&
util_is_power_of_two(templat->height0) &&
util_is_power_of_two(templat->depth0));
 
spr->dt = winsys->displaytarget_from_handle(winsys,
templat,
whandle,
&spr->stride[0]);
if (!spr->dt)
goto fail;
 
return &spr->base;
 
fail:
FREE(spr);
return NULL;
}
 
 
static boolean
softpipe_resource_get_handle(struct pipe_screen *screen,
struct pipe_resource *pt,
struct winsys_handle *whandle)
{
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
struct softpipe_resource *spr = softpipe_resource(pt);
 
assert(spr->dt);
if (!spr->dt)
return FALSE;
 
return winsys->displaytarget_get_handle(winsys, spr->dt, whandle);
}
 
 
/**
* Helper function to compute offset (in bytes) for a particular
* texture level/face/slice from the start of the buffer.
*/
static unsigned
sp_get_tex_image_offset(const struct softpipe_resource *spr,
unsigned level, unsigned layer)
{
const unsigned hgt = u_minify(spr->base.height0, level);
const unsigned nblocksy = util_format_get_nblocksy(spr->base.format, hgt);
unsigned offset = spr->level_offset[level];
 
if (spr->base.target == PIPE_TEXTURE_CUBE ||
spr->base.target == PIPE_TEXTURE_CUBE_ARRAY ||
spr->base.target == PIPE_TEXTURE_3D ||
spr->base.target == PIPE_TEXTURE_2D_ARRAY) {
offset += layer * nblocksy * spr->stride[level];
}
else if (spr->base.target == PIPE_TEXTURE_1D_ARRAY) {
offset += layer * spr->stride[level];
}
else {
assert(layer == 0);
}
 
return offset;
}
 
 
/**
* Get a pipe_surface "view" into a texture resource.
*/
static struct pipe_surface *
softpipe_create_surface(struct pipe_context *pipe,
struct pipe_resource *pt,
const struct pipe_surface *surf_tmpl)
{
struct pipe_surface *ps;
 
ps = CALLOC_STRUCT(pipe_surface);
if (ps) {
pipe_reference_init(&ps->reference, 1);
pipe_resource_reference(&ps->texture, pt);
ps->context = pipe;
ps->format = surf_tmpl->format;
if (pt->target != PIPE_BUFFER) {
assert(surf_tmpl->u.tex.level <= pt->last_level);
ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
ps->u.tex.level = surf_tmpl->u.tex.level;
ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
if (ps->u.tex.first_layer != ps->u.tex.last_layer) {
debug_printf("creating surface with multiple layers, rendering to first layer only\n");
}
}
else {
/* setting width as number of elements should get us correct renderbuffer width */
ps->width = surf_tmpl->u.buf.last_element - surf_tmpl->u.buf.first_element + 1;
ps->height = pt->height0;
ps->u.buf.first_element = surf_tmpl->u.buf.first_element;
ps->u.buf.last_element = surf_tmpl->u.buf.last_element;
assert(ps->u.buf.first_element <= ps->u.buf.last_element);
assert(ps->u.buf.last_element < ps->width);
}
}
return ps;
}
 
 
/**
* Free a pipe_surface which was created with softpipe_create_surface().
*/
static void
softpipe_surface_destroy(struct pipe_context *pipe,
struct pipe_surface *surf)
{
/* Effectively do the texture_update work here - if texture images
* needed post-processing to put them into hardware layout, this is
* where it would happen. For softpipe, nothing to do.
*/
assert(surf->texture);
pipe_resource_reference(&surf->texture, NULL);
FREE(surf);
}
 
 
/**
* Geta pipe_transfer object which is used for moving data in/out of
* a resource object.
* \param pipe rendering context
* \param resource the resource to transfer in/out of
* \param level which mipmap level
* \param usage bitmask of PIPE_TRANSFER_x flags
* \param box the 1D/2D/3D region of interest
*/
static void *
softpipe_transfer_map(struct pipe_context *pipe,
struct pipe_resource *resource,
unsigned level,
unsigned usage,
const struct pipe_box *box,
struct pipe_transfer **transfer)
{
struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys;
struct softpipe_resource *spr = softpipe_resource(resource);
struct softpipe_transfer *spt;
struct pipe_transfer *pt;
enum pipe_format format = resource->format;
const unsigned hgt = u_minify(spr->base.height0, level);
const unsigned nblocksy = util_format_get_nblocksy(format, hgt);
uint8_t *map;
 
assert(resource);
assert(level <= resource->last_level);
 
/* make sure the requested region is in the image bounds */
assert(box->x + box->width <= (int) u_minify(resource->width0, level));
if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
assert(box->y + box->height <= (int) resource->array_size);
}
else {
assert(box->y + box->height <= (int) u_minify(resource->height0, level));
if (resource->target == PIPE_TEXTURE_2D_ARRAY) {
assert(box->z + box->depth <= (int) resource->array_size);
}
else if (resource->target == PIPE_TEXTURE_CUBE) {
assert(box->z < 6);
}
else if (resource->target == PIPE_TEXTURE_CUBE_ARRAY) {
assert(box->z <= (int) resource->array_size);
}
else {
assert(box->z + box->depth <= (int) u_minify(resource->depth0, level));
}
}
 
/*
* Transfers, like other pipe operations, must happen in order, so flush the
* context if necessary.
*/
if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
boolean read_only = !(usage & PIPE_TRANSFER_WRITE);
boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK);
if (!softpipe_flush_resource(pipe, resource,
level, box->depth > 1 ? -1 : box->z,
0, /* flush_flags */
read_only,
TRUE, /* cpu_access */
do_not_block)) {
/*
* It would have blocked, but state tracker requested no to.
*/
assert(do_not_block);
return NULL;
}
}
 
spt = CALLOC_STRUCT(softpipe_transfer);
if (!spt)
return NULL;
 
pt = &spt->base;
 
pipe_resource_reference(&pt->resource, resource);
pt->level = level;
pt->usage = usage;
pt->box = *box;
pt->stride = spr->stride[level];
pt->layer_stride = pt->stride * nblocksy;
 
spt->offset = sp_get_tex_image_offset(spr, level, box->z);
 
spt->offset +=
box->y / util_format_get_blockheight(format) * spt->base.stride +
box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
 
/* resources backed by display target treated specially:
*/
if (spr->dt) {
map = winsys->displaytarget_map(winsys, spr->dt, usage);
}
else {
map = spr->data;
}
 
if (map == NULL) {
pipe_resource_reference(&pt->resource, NULL);
FREE(spt);
return NULL;
}
 
*transfer = pt;
return map + spt->offset;
}
 
 
/**
* Unmap memory mapping for given pipe_transfer object.
*/
static void
softpipe_transfer_unmap(struct pipe_context *pipe,
struct pipe_transfer *transfer)
{
struct softpipe_resource *spr;
 
assert(transfer->resource);
spr = softpipe_resource(transfer->resource);
 
if (spr->dt) {
/* display target */
struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys;
winsys->displaytarget_unmap(winsys, spr->dt);
}
 
if (transfer->usage & PIPE_TRANSFER_WRITE) {
/* Mark the texture as dirty to expire the tile caches. */
spr->timestamp++;
}
 
pipe_resource_reference(&transfer->resource, NULL);
FREE(transfer);
}
 
/**
* Create buffer which wraps user-space data.
*/
struct pipe_resource *
softpipe_user_buffer_create(struct pipe_screen *screen,
void *ptr,
unsigned bytes,
unsigned bind_flags)
{
struct softpipe_resource *spr;
 
spr = CALLOC_STRUCT(softpipe_resource);
if (!spr)
return NULL;
 
pipe_reference_init(&spr->base.reference, 1);
spr->base.screen = screen;
spr->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
spr->base.bind = bind_flags;
spr->base.usage = PIPE_USAGE_IMMUTABLE;
spr->base.flags = 0;
spr->base.width0 = bytes;
spr->base.height0 = 1;
spr->base.depth0 = 1;
spr->base.array_size = 1;
spr->userBuffer = TRUE;
spr->data = ptr;
 
return &spr->base;
}
 
 
void
softpipe_init_texture_funcs(struct pipe_context *pipe)
{
pipe->transfer_map = softpipe_transfer_map;
pipe->transfer_unmap = softpipe_transfer_unmap;
 
pipe->transfer_flush_region = u_default_transfer_flush_region;
pipe->transfer_inline_write = u_default_transfer_inline_write;
 
pipe->create_surface = softpipe_create_surface;
pipe->surface_destroy = softpipe_surface_destroy;
}
 
 
void
softpipe_init_screen_texture_funcs(struct pipe_screen *screen)
{
screen->resource_create = softpipe_resource_create;
screen->resource_destroy = softpipe_resource_destroy;
screen->resource_from_handle = softpipe_resource_from_handle;
screen->resource_get_handle = softpipe_resource_get_handle;
screen->can_create_resource = softpipe_can_create_resource;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_texture.h
0,0 → 1,103
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef SP_TEXTURE_H
#define SP_TEXTURE_H
 
 
#include "pipe/p_state.h"
#include "sp_limits.h"
 
 
struct pipe_context;
struct pipe_screen;
struct softpipe_context;
 
 
/**
* Subclass of pipe_resource.
*/
struct softpipe_resource
{
struct pipe_resource base;
 
unsigned long level_offset[SP_MAX_TEXTURE_2D_LEVELS];
unsigned stride[SP_MAX_TEXTURE_2D_LEVELS];
 
/**
* Display target, only valid for PIPE_TEXTURE_2D with the
* PIPE_BIND_DISPLAY_TARGET usage.
*/
struct sw_displaytarget *dt;
 
/**
* Malloc'ed data for regular buffers and textures, or a mapping to dt above.
*/
void *data;
 
/* True if texture images are power-of-two in all dimensions:
*/
boolean pot;
boolean userBuffer;
 
unsigned timestamp;
};
 
 
/**
* Subclass of pipe_transfer.
*/
struct softpipe_transfer
{
struct pipe_transfer base;
 
unsigned long offset;
};
 
 
/** cast wrappers */
static INLINE struct softpipe_resource *
softpipe_resource(struct pipe_resource *pt)
{
return (struct softpipe_resource *) pt;
}
 
static INLINE struct softpipe_transfer *
softpipe_transfer(struct pipe_transfer *pt)
{
return (struct softpipe_transfer *) pt;
}
 
 
extern void
softpipe_init_screen_texture_funcs(struct pipe_screen *screen);
 
extern void
softpipe_init_texture_funcs(struct pipe_context *pipe);
 
 
#endif /* SP_TEXTURE */
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_tile_cache.c
0,0 → 1,615
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
/**
* Render target tile caching.
*
* Author:
* Brian Paul
*/
 
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_tile.h"
#include "sp_tile_cache.h"
 
static struct softpipe_cached_tile *
sp_alloc_tile(struct softpipe_tile_cache *tc);
 
 
/**
* Return the position in the cache for the tile that contains win pos (x,y).
* We currently use a direct mapped cache so this is like a hack key.
* At some point we should investige something more sophisticated, like
* a LRU replacement policy.
*/
#define CACHE_POS(x, y) \
(((x) + (y) * 5) % NUM_ENTRIES)
 
 
 
/**
* Is the tile at (x,y) in cleared state?
*/
static INLINE uint
is_clear_flag_set(const uint *bitvec, union tile_address addr)
{
int pos, bit;
pos = addr.bits.y * (MAX_WIDTH / TILE_SIZE) + addr.bits.x;
assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32);
bit = bitvec[pos / 32] & (1 << (pos & 31));
return bit;
}
 
/**
* Mark the tile at (x,y) as not cleared.
*/
static INLINE void
clear_clear_flag(uint *bitvec, union tile_address addr)
{
int pos;
pos = addr.bits.y * (MAX_WIDTH / TILE_SIZE) + addr.bits.x;
assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32);
bitvec[pos / 32] &= ~(1 << (pos & 31));
}
 
struct softpipe_tile_cache *
sp_create_tile_cache( struct pipe_context *pipe )
{
struct softpipe_tile_cache *tc;
uint pos;
int maxLevels, maxTexSize;
 
/* sanity checking: max sure MAX_WIDTH/HEIGHT >= largest texture image */
maxLevels = pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
maxTexSize = 1 << (maxLevels - 1);
assert(MAX_WIDTH >= maxTexSize);
 
assert(sizeof(union tile_address) == 4);
 
assert((TILE_SIZE << TILE_ADDR_BITS) >= MAX_WIDTH);
 
tc = CALLOC_STRUCT( softpipe_tile_cache );
if (tc) {
tc->pipe = pipe;
for (pos = 0; pos < Elements(tc->tile_addrs); pos++) {
tc->tile_addrs[pos].bits.invalid = 1;
}
tc->last_tile_addr.bits.invalid = 1;
 
/* this allocation allows us to guarantee that allocation
* failures are never fatal later
*/
tc->tile = MALLOC_STRUCT( softpipe_cached_tile );
if (!tc->tile)
{
FREE(tc);
return NULL;
}
 
/* XXX this code prevents valgrind warnings about use of uninitialized
* memory in programs that don't clear the surface before rendering.
* However, it breaks clearing in other situations (such as in
* progs/tests/drawbuffers, see bug 24402).
*/
#if 0
/* set flags to indicate all the tiles are cleared */
memset(tc->clear_flags, 255, sizeof(tc->clear_flags));
#endif
}
return tc;
}
 
 
void
sp_destroy_tile_cache(struct softpipe_tile_cache *tc)
{
if (tc) {
uint pos;
 
for (pos = 0; pos < Elements(tc->entries); pos++) {
/*assert(tc->entries[pos].x < 0);*/
FREE( tc->entries[pos] );
}
FREE( tc->tile );
 
if (tc->transfer) {
tc->pipe->transfer_unmap(tc->pipe, tc->transfer);
}
 
FREE( tc );
}
}
 
 
/**
* Specify the surface to cache.
*/
void
sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
struct pipe_surface *ps)
{
struct pipe_context *pipe = tc->pipe;
 
if (tc->transfer_map) {
if (ps == tc->surface)
return;
 
pipe->transfer_unmap(pipe, tc->transfer);
tc->transfer = NULL;
tc->transfer_map = NULL;
}
 
tc->surface = ps;
 
if (ps) {
if (ps->texture->target != PIPE_BUFFER) {
tc->transfer_map = pipe_transfer_map(pipe, ps->texture,
ps->u.tex.level, ps->u.tex.first_layer,
PIPE_TRANSFER_READ_WRITE |
PIPE_TRANSFER_UNSYNCHRONIZED,
0, 0, ps->width, ps->height,
&tc->transfer);
}
else {
/* can't render to buffers */
assert(0);
}
 
tc->depth_stencil = util_format_is_depth_or_stencil(ps->format);
}
}
 
 
/**
* Return the transfer being cached.
*/
struct pipe_surface *
sp_tile_cache_get_surface(struct softpipe_tile_cache *tc)
{
return tc->surface;
}
 
 
/**
* Set pixels in a tile to the given clear color/value, float.
*/
static void
clear_tile_rgba(struct softpipe_cached_tile *tile,
enum pipe_format format,
const union pipe_color_union *clear_value)
{
if (clear_value->f[0] == 0.0 &&
clear_value->f[1] == 0.0 &&
clear_value->f[2] == 0.0 &&
clear_value->f[3] == 0.0) {
memset(tile->data.color, 0, sizeof(tile->data.color));
}
else {
uint i, j;
 
if (util_format_is_pure_uint(format)) {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.colorui128[i][j][0] = clear_value->ui[0];
tile->data.colorui128[i][j][1] = clear_value->ui[1];
tile->data.colorui128[i][j][2] = clear_value->ui[2];
tile->data.colorui128[i][j][3] = clear_value->ui[3];
}
}
} else if (util_format_is_pure_sint(format)) {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.colori128[i][j][0] = clear_value->i[0];
tile->data.colori128[i][j][1] = clear_value->i[1];
tile->data.colori128[i][j][2] = clear_value->i[2];
tile->data.colori128[i][j][3] = clear_value->i[3];
}
}
} else {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.color[i][j][0] = clear_value->f[0];
tile->data.color[i][j][1] = clear_value->f[1];
tile->data.color[i][j][2] = clear_value->f[2];
tile->data.color[i][j][3] = clear_value->f[3];
}
}
}
}
}
 
 
/**
* Set a tile to a solid value/color.
*/
static void
clear_tile(struct softpipe_cached_tile *tile,
enum pipe_format format,
uint64_t clear_value)
{
uint i, j;
 
switch (util_format_get_blocksize(format)) {
case 1:
memset(tile->data.any, (int) clear_value, TILE_SIZE * TILE_SIZE);
break;
case 2:
if (clear_value == 0) {
memset(tile->data.any, 0, 2 * TILE_SIZE * TILE_SIZE);
}
else {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.depth16[i][j] = (ushort) clear_value;
}
}
}
break;
case 4:
if (clear_value == 0) {
memset(tile->data.any, 0, 4 * TILE_SIZE * TILE_SIZE);
}
else {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.depth32[i][j] = (uint) clear_value;
}
}
}
break;
case 8:
if (clear_value == 0) {
memset(tile->data.any, 0, 8 * TILE_SIZE * TILE_SIZE);
}
else {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.depth64[i][j] = clear_value;
}
}
}
break;
default:
assert(0);
}
}
 
 
/**
* Actually clear the tiles which were flagged as being in a clear state.
*/
static void
sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc)
{
struct pipe_transfer *pt = tc->transfer;
const uint w = tc->transfer->box.width;
const uint h = tc->transfer->box.height;
uint x, y;
uint numCleared = 0;
 
assert(pt->resource);
if (!tc->tile)
tc->tile = sp_alloc_tile(tc);
 
/* clear the scratch tile to the clear value */
if (tc->depth_stencil) {
clear_tile(tc->tile, pt->resource->format, tc->clear_val);
} else {
clear_tile_rgba(tc->tile, pt->resource->format, &tc->clear_color);
}
 
/* push the tile to all positions marked as clear */
for (y = 0; y < h; y += TILE_SIZE) {
for (x = 0; x < w; x += TILE_SIZE) {
union tile_address addr = tile_address(x, y);
 
if (is_clear_flag_set(tc->clear_flags, addr)) {
/* write the scratch tile to the surface */
if (tc->depth_stencil) {
pipe_put_tile_raw(pt, tc->transfer_map,
x, y, TILE_SIZE, TILE_SIZE,
tc->tile->data.any, 0/*STRIDE*/);
}
else {
if (util_format_is_pure_uint(tc->surface->format)) {
pipe_put_tile_ui_format(pt, tc->transfer_map,
x, y, TILE_SIZE, TILE_SIZE,
pt->resource->format,
(unsigned *) tc->tile->data.colorui128);
} else if (util_format_is_pure_sint(tc->surface->format)) {
pipe_put_tile_i_format(pt, tc->transfer_map,
x, y, TILE_SIZE, TILE_SIZE,
pt->resource->format,
(int *) tc->tile->data.colori128);
} else {
pipe_put_tile_rgba(pt, tc->transfer_map,
x, y, TILE_SIZE, TILE_SIZE,
(float *) tc->tile->data.color);
}
}
numCleared++;
}
}
}
 
/* reset all clear flags to zero */
memset(tc->clear_flags, 0, sizeof(tc->clear_flags));
 
#if 0
debug_printf("num cleared: %u\n", numCleared);
#endif
}
 
static void
sp_flush_tile(struct softpipe_tile_cache* tc, unsigned pos)
{
if (!tc->tile_addrs[pos].bits.invalid) {
if (tc->depth_stencil) {
pipe_put_tile_raw(tc->transfer, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->entries[pos]->data.depth32, 0/*STRIDE*/);
}
else {
if (util_format_is_pure_uint(tc->surface->format)) {
pipe_put_tile_ui_format(tc->transfer, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(unsigned *) tc->entries[pos]->data.colorui128);
} else if (util_format_is_pure_sint(tc->surface->format)) {
pipe_put_tile_i_format(tc->transfer, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(int *) tc->entries[pos]->data.colori128);
} else {
pipe_put_tile_rgba_format(tc->transfer, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(float *) tc->entries[pos]->data.color);
}
}
tc->tile_addrs[pos].bits.invalid = 1; /* mark as empty */
}
}
 
/**
* Flush the tile cache: write all dirty tiles back to the transfer.
* any tiles "flagged" as cleared will be "really" cleared.
*/
void
sp_flush_tile_cache(struct softpipe_tile_cache *tc)
{
struct pipe_transfer *pt = tc->transfer;
int inuse = 0, pos;
 
if (pt) {
/* caching a drawing transfer */
for (pos = 0; pos < Elements(tc->entries); pos++) {
struct softpipe_cached_tile *tile = tc->entries[pos];
if (!tile)
{
assert(tc->tile_addrs[pos].bits.invalid);
continue;
}
 
sp_flush_tile(tc, pos);
++inuse;
}
 
sp_tile_cache_flush_clear(tc);
 
 
tc->last_tile_addr.bits.invalid = 1;
}
 
#if 0
debug_printf("flushed tiles in use: %d\n", inuse);
#endif
}
 
static struct softpipe_cached_tile *
sp_alloc_tile(struct softpipe_tile_cache *tc)
{
struct softpipe_cached_tile * tile = MALLOC_STRUCT(softpipe_cached_tile);
if (!tile)
{
/* in this case, steal an existing tile */
if (!tc->tile)
{
unsigned pos;
for (pos = 0; pos < Elements(tc->entries); ++pos) {
if (!tc->entries[pos])
continue;
 
sp_flush_tile(tc, pos);
tc->tile = tc->entries[pos];
tc->entries[pos] = NULL;
break;
}
 
/* this should never happen */
if (!tc->tile)
abort();
}
 
tile = tc->tile;
tc->tile = NULL;
 
tc->last_tile_addr.bits.invalid = 1;
}
return tile;
}
 
/**
* Get a tile from the cache.
* \param x, y position of tile, in pixels
*/
struct softpipe_cached_tile *
sp_find_cached_tile(struct softpipe_tile_cache *tc,
union tile_address addr )
{
struct pipe_transfer *pt = tc->transfer;
/* cache pos/entry: */
const int pos = CACHE_POS(addr.bits.x,
addr.bits.y);
struct softpipe_cached_tile *tile = tc->entries[pos];
 
if (!tile) {
tile = sp_alloc_tile(tc);
tc->entries[pos] = tile;
}
 
if (addr.value != tc->tile_addrs[pos].value) {
 
assert(pt->resource);
if (tc->tile_addrs[pos].bits.invalid == 0) {
/* put dirty tile back in framebuffer */
if (tc->depth_stencil) {
pipe_put_tile_raw(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tile->data.depth32, 0/*STRIDE*/);
}
else {
if (util_format_is_pure_uint(tc->surface->format)) {
pipe_put_tile_ui_format(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(unsigned *) tile->data.colorui128);
} else if (util_format_is_pure_sint(tc->surface->format)) {
pipe_put_tile_i_format(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(int *) tile->data.colori128);
} else {
pipe_put_tile_rgba_format(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(float *) tile->data.color);
}
}
}
 
tc->tile_addrs[pos] = addr;
 
if (is_clear_flag_set(tc->clear_flags, addr)) {
/* don't get tile from framebuffer, just clear it */
if (tc->depth_stencil) {
clear_tile(tile, pt->resource->format, tc->clear_val);
}
else {
clear_tile_rgba(tile, pt->resource->format, &tc->clear_color);
}
clear_clear_flag(tc->clear_flags, addr);
}
else {
/* get new tile data from transfer */
if (tc->depth_stencil) {
pipe_get_tile_raw(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tile->data.depth32, 0/*STRIDE*/);
}
else {
if (util_format_is_pure_uint(tc->surface->format)) {
pipe_get_tile_ui_format(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(unsigned *) tile->data.colorui128);
} else if (util_format_is_pure_sint(tc->surface->format)) {
pipe_get_tile_i_format(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(int *) tile->data.colori128);
} else {
pipe_get_tile_rgba_format(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(float *) tile->data.color);
}
}
}
}
 
tc->last_tile = tile;
tc->last_tile_addr = addr;
return tile;
}
 
 
 
 
 
/**
* When a whole surface is being cleared to a value we can avoid
* fetching tiles above.
* Save the color and set a 'clearflag' for each tile of the screen.
*/
void
sp_tile_cache_clear(struct softpipe_tile_cache *tc,
const union pipe_color_union *color,
uint64_t clearValue)
{
uint pos;
 
tc->clear_color = *color;
 
tc->clear_val = clearValue;
 
/* set flags to indicate all the tiles are cleared */
memset(tc->clear_flags, 255, sizeof(tc->clear_flags));
 
for (pos = 0; pos < Elements(tc->tile_addrs); pos++) {
tc->tile_addrs[pos].bits.invalid = 1;
}
tc->last_tile_addr.bits.invalid = 1;
}
/contrib/sdk/sources/Mesa/mesa-9.2.5/src/gallium/drivers/softpipe/sp_tile_cache.h
0,0 → 1,159
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
 
#ifndef SP_TILE_CACHE_H
#define SP_TILE_CACHE_H
 
 
#include "pipe/p_compiler.h"
#include "sp_texture.h"
 
 
struct softpipe_tile_cache;
 
 
/**
* Cache tile size (width and height). This needs to be a power of two.
*/
#define TILE_SIZE_LOG2 6
#define TILE_SIZE (1 << TILE_SIZE_LOG2)
 
 
#define TILE_ADDR_BITS (SP_MAX_TEXTURE_2D_LEVELS - 1 - TILE_SIZE_LOG2)
 
 
/**
* Surface tile address as a union for fast compares.
*/
union tile_address {
struct {
unsigned x:TILE_ADDR_BITS; /* 16K / TILE_SIZE */
unsigned y:TILE_ADDR_BITS; /* 16K / TILE_SIZE */
unsigned invalid:1;
unsigned pad:15;
} bits;
unsigned value;
};
 
 
struct softpipe_cached_tile
{
union {
float color[TILE_SIZE][TILE_SIZE][4];
uint color32[TILE_SIZE][TILE_SIZE];
uint depth32[TILE_SIZE][TILE_SIZE];
ushort depth16[TILE_SIZE][TILE_SIZE];
ubyte stencil8[TILE_SIZE][TILE_SIZE];
uint colorui128[TILE_SIZE][TILE_SIZE][4];
int colori128[TILE_SIZE][TILE_SIZE][4];
uint64_t depth64[TILE_SIZE][TILE_SIZE];
ubyte any[1];
} data;
};
 
#define NUM_ENTRIES 50
 
 
struct softpipe_tile_cache
{
struct pipe_context *pipe;
struct pipe_surface *surface; /**< the surface we're caching */
struct pipe_transfer *transfer;
void *transfer_map;
 
union tile_address tile_addrs[NUM_ENTRIES];
struct softpipe_cached_tile *entries[NUM_ENTRIES];
uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32];
union pipe_color_union clear_color; /**< for color bufs */
uint64_t clear_val; /**< for z+stencil */
boolean depth_stencil; /**< Is the surface a depth/stencil format? */
 
struct softpipe_cached_tile *tile; /**< scratch tile for clears */
 
union tile_address last_tile_addr;
struct softpipe_cached_tile *last_tile; /**< most recently retrieved tile */
};
 
 
extern struct softpipe_tile_cache *
sp_create_tile_cache( struct pipe_context *pipe );
 
extern void
sp_destroy_tile_cache(struct softpipe_tile_cache *tc);
 
extern void
sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
struct pipe_surface *sps);
 
extern struct pipe_surface *
sp_tile_cache_get_surface(struct softpipe_tile_cache *tc);
 
extern void
sp_flush_tile_cache(struct softpipe_tile_cache *tc);
 
extern void
sp_tile_cache_clear(struct softpipe_tile_cache *tc,
const union pipe_color_union *color,
uint64_t clearValue);
 
extern struct softpipe_cached_tile *
sp_find_cached_tile(struct softpipe_tile_cache *tc,
union tile_address addr );
 
 
static INLINE union tile_address
tile_address( unsigned x,
unsigned y )
{
union tile_address addr;
 
addr.value = 0;
addr.bits.x = x / TILE_SIZE;
addr.bits.y = y / TILE_SIZE;
return addr;
}
 
/* Quickly retrieve tile if it matches last lookup.
*/
static INLINE struct softpipe_cached_tile *
sp_get_cached_tile(struct softpipe_tile_cache *tc,
int x, int y )
{
union tile_address addr = tile_address( x, y );
 
if (tc->last_tile_addr.value == addr.value)
return tc->last_tile;
 
return sp_find_cached_tile( tc, addr );
}
 
 
 
 
#endif /* SP_TILE_CACHE_H */