/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 */ |